[MUSIC]

Now I want to continue our example of implementing an expression

language in both FP and OOP,

by considering what happens when we want to later go back and extend our software.

So in the previous segment, we implemented this blue grid.

And we did it by row in object-oriented programming and

by column in functional programming.

But what if later we come back, and

we want to add some additional features to our program?

Maybe even some other person wants to extend our software.

Well maybe they want to add a row like a new kind of expression like

multiplications or maybe they want to add a column,

a new operation, like go through an expression and

see if it contains all non negative constants something like this.

So if you know what kind of extensibility you want to make natural and best support.

It should very much affect your decision of how you decompose

your software in the first place.

In particular, let's consider first functional then, OPD composition.

Under the functional decomposition,

we're going to see that it's very easy to add a new column.

You just write a new function.

It will not affect any of your existing functions.

It's just a new function.

And all the old functions continue to work just like they always did.

On the other hand, if we go to add a new constructor to our data type,

this affects all of our old functions, right?

They will have to deal with this new case and

will have to go back and change all of them.

On the other hand,

in a statically typed language, we do have this benefit that the type-checker

is going to tell us exactly which pattern matches are now not exhaustive.

As long as when we wrote the first version of program,

we didn't use things like wildcard patterns.

So that's the idea.

So you might imagine I've done this for you.

So let me show you this.

Let's do the easy things first.

Let's add a new operation,noNegConstants.

All I did was go down here to borrow my file,, although I could have done anywhere

after the data type definition, and added this recursive procedure that take in

expression e,and says that if it's an iterger.

It's excuse me.

I misspoke on what i want noNegContants to do.

I actually want this to be an expression of type (exp->exp) that preprocess

the expression to remove all negative constants by making a different

expression.

So let me walk through what that does.

If you have an integer I, and that I is less than 0,

then replace the expression nth of I with negate of int of the negation of I.

So that will replace the negative constant with a positive constant by adding

a negation expression.

Otherwise, just return the expression itself.

And then for Negate,

just recursively remove all negative constants from the subexpression.

For Add, remove them from the two subexpressions.

And after we add multiplication, we'll need a case for multiplication as well.

So that's the exp -> exp.

Think of this as a preprocessor that gets rid of all negative constants in our

little program, okay?

So that was adding no neg constants, and we did this in this localized way,

didn't affect anybody else.

But now, if we go and add a mult constructor like this,

before we make any other changes, if we go to recompile our program,

we'll find out that we broke all of our existing operations because eval,

two string and has zero were not expecting multiplications.

So we would have to go back and add those.

We would have to go out to eval and change it to add Mult.

We would have to go back to tostring to add Mult, and

we'd have to go back to hasZero to add Mult.

And assuming we did noNegConstants first, we'd have to add one there.

And that is adding a new kind of data to a program written in a functional style.

So now let's flip this around and do objects.

As you might imagine it's the exact opposite.

Adding a new operation like Mult will be very easy.

We can do it in a local way.

And all of our existing classes will continue to work.

In fact because of the dynamic dispatch they went and

add calls eval on a sub-expression,

it's fine if that sub-expression is now

an instance of the new class mult to add a new case.

In a statically typed language, like Java which is optional and

I will show you briefly.

We actually get the same help from our type checker for the difficult case,

in this case no neg constants.

What we do is in a super class we say that all sub classes need

a no neg constants method.

And then since our existing subclasses in add and negate don't have one yet.

We get the same kind of to do list from the tie checker telling us what

needs to change.

That we got in ML showing us were our missing cases were.

So, let me show you the Ruby Code.