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