views:

72

answers:

2

Coming to OCaml from Lisp, I find myself very confused about when functions return and when they don't. I miss my magic Quote! Thankfully, most of the time, OCaml appears to automagicly know when I want a function evaluated and when I don't. However, I frequently find myself trying to assign the return value of a function in a let expression, like the following.

let start = Sys.time in
(*
 * do something here
 *)
 ;
let ending = Sys.time in
Printf.printf "did something in %f seconds\n" (ending -. start)

but then ocamlc complains

Error: This Expression has type unit -> float
       but an expression was expected of type float

Telling me that start and end are bound to Sys.time, not the return value of Sys.time.

Is this behavior I'm trying to get not OCamly? Do I want to be doing things another way? Am I just missing something completely obvious?

+7  A: 

A function is evaluated when you apply it to an argument. I.e. when you do f, f never gets evaluated. When you do f x, f always gets evaluated. There's nothing magical about it.

As you correctly pointed out, Sys.time is a function (of type unit -> float) and let start = Sys.time just assigns that function to start.

To get the behavior you want simply do let start = Sys.time (), which applies the function Sys.time to the argument () (which is the only value of type unit).

sepp2k
+2  A: 

You cannot call a function just by writing its name. If you just write a function's name, you're returning the function itself, not its return value. That error is telling you that the function takes a unit argument — i.e., you should write Sys.time () to actually apply the function and get the resulting float value.

Chuck