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)`

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!

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:

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

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*.

`cs2041.org`