So, that means that for instance, here the name f is visible in the block, it refers

to this outer block named f. But the name x here, refers to the inner

name x not the outer name x. The inner name x shadows the occurrence of

the outer name. Let's do an exercise.

I take a small variation of the program you've just seen.

The question is, what is the value of result in this program?

Possible answers are here. Think about it and pick one.

So, let's see how we would find the answer to that one.

If we look at the value of result, then what we see is that the first thing we do

is we compute the value of x to be f of three, f is this function here.

It adds one to it's parameter so that would be give x for x the value of four.

So then, the value of x times x would be sixteen, and we take that value, and add x

to it. What's the value of x here?

Well, we're now outside the block so the value of x here is no longer visible.

And the value we do see here is that this first definition, so that would be zero.

So, the answer of the whole expression, the result of the whole expression is

sixteen. So we've seen the definitions of outer

scopes are visible inside a block unless they're shadowed.

You can use that to simplify square root by eliminating redundant occurrences of

the x parameter, which means, everywhere, the same thing.

So, what you see here in the worksheet is that the x parameter that comes into

square root is duplicated here, here, and here, but it's never changed.

It's always passed as it is before. So, we can simply eliminate it, all these

occurrences here. And eliminate the corresponding parameter

in the application. And, we have the same version of square

root, but now it's much cleaner. We have avoided the redundancy of passing

the parameter x around everywhere by using the simple trick that the value of x is

actually visible inside all these nested functions.

So, that gives you another reason for nesting things, it's not just name space

control but it's also reusing outer definitions without passing them

explicitly in parameters. Okay, one thing we haven't mentioned so

far were semicolons, simply because so far we haven't seen them.

Even though in Java every statement would be terminated by a semicolon, in Scala

they are in most cases optional. You could have written val x is equals one

with a semicolon but most people would omit that.

The only situation where you really need a semicolon is if you want to put several

definitions or expressions on one line. Then, the semicolon is needed to separate

them. So for instance, here, you have a value

definition of y equals x plus one. And then a use of the variable y in a

subsequent expression and you need the semicolon here to separate the two.

Being able to commit semicolons at the end of lines is very co, convenient, but

there's one issue with it. How would you write an expression that

spans several lines? To see the problem, consider this

expression here, some long expression, then it continued on the second line with

some other expressions. That would actually be interpreted by the

Scala compiler as two expressions. The first expression is the some wrong

expression then, it would be the implied semicolon, and then comes plus with the

other expression. There are two ways to overcome this

problem. You could write the multiline expressions

in parenthesis, because semicolons are never inserted inside a pair of

parenthesis. So, you could write some wrong expression

plus some other expression as long as you put it in parenthesis and that's fine.

Or, the other way to do that is to write the operator on the first line as the last

word on the first line because this tells the Scala compiler that the expression is

not yet finished. So, if a line ends in infix operator the

Scala compiler will assume the next line forms part of the same expression.

So, to summarize what we have seen this week, we've seen elements of functional

programming in Scala, arithmetic and Boolean expressions, conditional

expressions, if then else, functions with recursion, nesting and lexical scope.

You've learned the difference between call by name and call by value evaluation

strategies. And I believe, most importantly, you've

learned a way to reason about program execution.

You can now reduce expressions using the substitution model.

That model will be an important tool for the coming sessions.