ocaml

# Question about partial application in OCaml

I have a question about OCaml: Assume the following function declarations:

``````let secret x y =
let secret' x y z = x + y - z in
let z = if x mod 2 = 0 then y else x - y
in secret' x z ;;

``````
``````print_int (secret 3 2 (-5));;
``````

The output will be 9.

Why is the result 9?

Is this the way its calculations are performed?

``````let secret 3 2 =
let secret' 3 2 z = 3 + 2 - z in
let z = if 3 mod 2 = 0 then 2 else 3 - 2
in secret' 3 1
``````

Why doesn't it stop at secret' 3 1 but instead comes up with the result 9? Computes it secret' 3 1 (-5) = 3 + 1 -(-5) ? Why?

Solution

• First, let's fix the indentation, as it's quite misleading right now.

``````let secret x y =
let secret' x y z = x + y - z in
let z = if x mod 2 = 0 then y else x - y in
secret' x z ;;
``````

Same function, but doesn't imply that the local `z` is related to the `secret'` function. Second, let's remove some of the variable shadowing, because you're calling `secret'` with a derived `y` (which you call `z` in another place but which is different from `z` in `secret'`), so for the sake of clarity, let's rename those variables.

``````let secret x y =
let secret' a b c = a + b - c in
let z = if x mod 2 = 0 then y else x - y in
secret' x z ;;
``````

Now we make the call

``````secret 3 2 (-5)
``````

We have a definition for `secret x y`. So we can forget about the third argument for now and just call this function.

``````(secret 3 2) (-5)
``````

Replace with definition.

``````((let secret' a b c = a + b - c in let z = if x mod 2 = 0 then y else x - y in secret' x z) 3 2) (-5)
``````

Substitute `3` for `x` and `2` for `y`.

``````(let secret' a b c = a + b - c in let z = if 3 mod 2 = 0 then 2 else 3 - 2 in secret' 3 z) (-5)
``````

Simplify `z`, since we know its value.

``````(let secret' a b c = a + b - c in secret' 3 1) (-5)
``````

Now we can partially apply `secret'`. We don't have a value for `c` yet (we do in the outer expression, but we're not looking there right now). The above is equivalent to

``````(let secret' a b = fun c -> a + b - c in secret' 3 1) (-5)
``````

Oh look! Suddenly the function takes two arguments. And we have two arguments. Let's apply it. Substitute `3` for `a` and `1` for `b`.

``````(fun c -> 3 + 1 - c) (-5)
``````

Hey, look! A function of one argument being applied to one argument. Substitute `-5` for `c`.

``````3 + 1 - (-5)
``````

and simplify the arithmetic

``````9
``````