Then in our functional decomposition, we have one function for
each column of the grid.
We have an eval function, a toString function, and a hasZero function.
And then in those functions we use case expressions to have one branch for
each row, for each square in this column.
That's how we decompose our program.
If multiple of your squares can be implemented in the same way then you can
use wild card patterns or something like that, but fundamentally you're decomposing
it in terms of for each operation which is a function, what are the various branches?
So let me make this very concrete because
we're going to build on this in upcoming segments.
Here is the ML code that does exactly that.
Here is our data type expression that says what the rows of our table are.
And we have one function for each operation.
So here is the eval function.
Takes in an expression e, it's an integer, just returns the expression.
If it's a negate, it recursively evaluates.
Make sure it gets an Int out and it negates it, otherwise,
it raises an exception.
And then I have one more case for that last row of the eval column,
which is to in addition recursively evaluate e1 and e2.
And because of where this is going in future segments I'm using a helper
function here, add_values, which is right up here.
Helper functions are fine.
And all this does is make sure that both values are integers,
in which case it returns a new integer that adds them together,
otherwise it raises an exception.
That is only one column of my grid, the next column,
toString, is right here, and I have one case for each branch.
So an Int, I just call the Int.toString function in ML.
For Negate I have some recursion here.
For Add I have two recursive calls and so on.
And then a column for the hasZero function that again has one branch for
each row of the table.
So those are my three columns.
Okay, that is functional programming.
Now let's look at OOP.
In OOP the way we would approach this in OOP style
is we would define a class that describes the idea of expression.
Now you don't actually have to do this in Ruby because it's a dynamically typed
language, but I'm going to present it that way.
And think of Int, Add and Negate as all sub classes of that super class.
You could just define Int, Add and
Negate as classes that weren't sub classes of anything other than objects.
But let's think of it as having a class x within sub class Int, Add, and Negate.
So then what we do is to fill out our table, we have one class for each row.
We have the Int class, and the the Add class, and the Negate class.
And then we fill in the entries of that row by Int having an eval method,
a toString method, and a hasZero method,
Add having the same three methods, Negate having the same three methods.
And those methods say, this is how a Negation converts it self to a string.
So, we are sensationally filling out the exact same table.
Organizing our code into rows instead of into columns.
As you might Imagine, I've done exactly that, over here in the Ruby file.
So, again i have this class Exp, which I don't really need in Ruby.
In fact, I'm even going to have a separate super class for
values in my language which currently are only int expressions.
This is similar to the sort of thing you will do on your homework,
which is why I have it, but it is overkill in this example.
So now I have one class for each row.
So here is my Int class, and if I look further down, here is my Negate class.
If I look further down, here is my Add class.
Now, inside of each of these classes I fill out the row, all right?
So I have a little bit of stuff for how to initialize an integer,
which has one instance variable for the underlie in itself.
But then I do have a method for eval, a method for toString, and
a method for hasZero.
So evaling an integer just returns the object itself.
This is the same thing as in functional programming in the branch of eval
where the int evaluates to the entire Int.
This object, when you call eval on it, returns self,
it returns the entire object.
For toString let’s just call the to_s method on the underlying instance
variable that holds the number, and for hasZero let’s see if i==0.
These three entries in our table are exactly