## Evaluating Expressions

When OCaml (or `interpreter.ml`) evaluates an expression, eg:

``x + 7 * y``

It (generates code that) evaluates `x`, `y`,`7*val(y)`, and `val(x)+val(7*y)`

``if (n=0) then e1 else e2``

Evaluate `(n=0)`, then if true, evaluate `e1`, otherwise `e2`.

`let rec f n = if n=0 then 1 else n*(f (n-1))`
must be evaluated in this order!

# Evaluating Rewriting Expressions

Another way to think of evaluation: rewriting expressions (trees):

…until we reach a normal form expression that can’t be reduced.

Starting from

With `n=4` we eventually get to

How do we re-write `(f (n-1))`? Considering also “chained applications” like `((f g) h)` or `f (g h) n`

Answer: the “application” operator `@@`, defined by:

``let  (@@) f x = f x``

Now we need a rule for evaluating `f @@ e`.

There are two common rules for evaluating `e1 @@ e2`

Call by Value

• Evaluate `e2` to get value `v`
• Evaluate `e1` to get function body `f`
• Evaluate `f` with `param → v`

Call by Name

• Evaluate `e1` to get function body `f`
• evaluate `f` with `param → e2`

The main difference is when evaluating applications to applications:

`(fun y -> ... y ...) (g x)``( ... (g x) ...)`

Example: using these definitions

``````let rec range i n = if i>=n then [] else i::(range (i+1) n)
let rec take n lst = match (n,lst) with
| (0,_) | (_,[]) -> []
| (n,(h::t)) -> h::(take (n-1) t)``````

and evaluating the expression

``(take 2 (range 0 3)) ≡ (take @@ 2) @@ ((range @@ 0) @@ 3)``

by value:

``````(take 2 (0::(range 1 3)))
(take 2 (0::(1::(range 2 3))))
(take 2 (0::1::2::(range 3 3)))
(take 2 (0::1::2::[]))
0::(take 1 1::2::[])
0::1::(take 0 2::[])
0::1::[]``````

by name:

``````(take 2 (0::(range 1 3)))
0::(take 1 (range 1 3))
0::(take 1 (1::(range 2 3)))
0::1::(take 0 (range 2 3))
0::1::[]``````

Evaluation stops when a normal form, or value is reached:

• A constant belonging to a built-in type; or
• A constructor applied to the correct number of arguments; or
• A function applied to no arguments (i.e. `fun x -> e`)

Call-by-value is also called applicative order or eager evaluation, and is the more common eval rule. (used in Python, Java, C/C++, OCaml,…)

Call-by-name is also called lazy or normal-order evaluation.

The rules can lead to different behavior, e.g:

``````let rec f x y  = f y x in
let g z = "good!" in g (f 2 3)``````

# `cs2041.org`

// reveal.js plugins