Or there could also be a constant set, let's say N, where N was, like, defined as

well, N=2.2.so So we can use name constants as well as constant literals.

And then you can take these building blocks, and compose com-, more complicated

map- patterns from them. So one example for that would be a pattern

that reads a sum of, let's say number one and the second operand would be a variable

x. So that would match objects which are sums with their left operant that is a

number. And the number needs to have a numeric

value one. And the right operand of the sum needs to

be a node of type Var. And the name field of the Var can be

anything but after the pattern in the right-hand side where we then use the

expression we can refer to x as the name of that variable.

We'll see an example in a minute. So here's some of the fine print.

One tricky bit is how to distinguish a variable such as N which can match

anything from a constant. Such as N,

Which, in this case, matches just the number two and nothing else.

Syntactically, we need to find a way to distinguish one from the other.

So the convention Scala uses here is that variables always must begin with a lower

case letter. Whereas, constants should begin with a

capital letter. The only exceptions here are the reserved

words, null, true, and false. But these are literals that the compiler

knows about. There's another restriction on variables,

and that's that the same variable name can only appear once in a pattern.

So for instance, sum of x,x is not a legal pattern, you have to write sum of x,y

instead. So now we know what the form of match

expressions and patterns is. The question is how are they evaluated.

So let's take an expression of the form that we've seen that would match the value

of the selector E with the patterns P1 to PN in the order they're written.

On the next slide, we'll see what that means exactly, matching an expression with

a pattern. If a pattern matches, then the whole

expression is rewritten to the right hand side of the first pattern that matches.

And when we do that, the reference is to pattern variables in the pattern here out

of place by corresponding parts and the selector.

But what does, does it mean that a pattern matches an expression?

Well, we look at the possible forms of patterns to determine that.

Let's say we have a constructive pattern. So, there's a class name and some

arguments that would match all values of type C or a sub type of type C that's also

legal. That have been constructed with arguments

that, in turn. Match the patterns P1 one to Pn. If, if

the pattern is a variable pattern, x, and that matches any value.

And it also will bind the name of the variable x to this value.

So, in the, in the associated expression we can then use x as the name for the

value that is matched. And the third case was a constant pattern

C, so this one matches any value that is equal to C, where equality is understood

in the sense of equal sequels. So these rules might have sounded dry and

difficult but it will all become clear if we look at an example.

So let's look at an application of our evaluation function which I have put up

here on the side with a trade sum of number one, number two as an argument.

Well the first thing that we would do as usual is rewrite that application by the

body of Eval, where the actual argument replaces the former parameter.

So the result is this expression here. The E variable here gets substituted with

the actual argument sum of number one, sum of number two.

The next step is, we have to evaluate the match expression.

What we need to do here is we have to match the selector expression against all

the patterns. The first one doesn't match, because the

constructor is different. The second one does match,

Sum matches sum. And that means that the two variables, e1

and e2 will be bound to number one and number two.

And after that, the expression, all expression will rewrite to the right hand

side expression here, which is Eval one plus Eval two.

So that means we're left with Eval. Now, instead of e1 we use, we would use number

one. We,

We would use number one. The, value that was bound to the variable

and instead.instead Of e2, we use number two.

So, the next step, then, would be that we have to rewrite the function application

on the left here. So what we get here is this expression

here. We have a selector of number one and the

match expression, which is the right hand side of eval.

And then that's the rest that we have to add to the result.

If we look at the match expression then now we see the first pattern is the one

that matches, the number is the same thing here.

The variable end that's bound to one and that's the thing we return so one is the

number we return and afterwards we need to do an eval of number which will give two

as by the same reasoning as what we have seen just now.

So, there always have to three. So far all our pattern matching methods

were defined outside of the class hierarchy, so where there was decomposing

classes from the outside. But it's also perfectly possible to have

pattern matching methods inside the class hierarchy as methods of base classes

themselves. Such as the Eval method that you see here.

So that is just the same as the previous eval method except now we match on the

receiver object itself. So you see how this stuff match.

And instead of writing eval of e what, Of e here.

It would be e1.eval because eval is now a method of, of, the trait expression.

Either one is perfectly acceptable. Once you've done that you might also ask

well what are the trade-offs to do it this way or with the previous object-oriented

decompositions solution we've seen, where we had essentially be the base trait exper

and the def eval, which was empty and then in some, there would be a def Eval,

Which was concrete and in number there would be another.