Guaranteed assignment of function return value in OCaml

Getting started with Lisp's OCaml, I'm very confused when functions return and when not. I miss my magic quote! Fortunately, most of the time, OCaml seems to automatically know when I want the function to be evaluated, and when not. However, I often try to assign the return value of a function in a let expression, as shown below.

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 

Tell us that the start and end are tied to Sys.time , and not to the return value of Sys.time .

Is this behavior I'm trying to get non OCamly? I want to do something different? Did I just miss something completely obvious?

+6
variable-assignment functional-programming ocaml
source share
3 answers

A function is evaluated when you apply it to an argument. That is, when you execute f , f never evaluated. When you execute fx , f always evaluated. There is nothing magical about it.

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

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

+10
source share

You cannot call a function simply by writing its name. If you simply write the name of the function, you are returning the function directly, not its return value. This error tells you that the function takes a unit argument, i.e. You have to write Sys.time () to actually apply this function and get the resulting float value.

+3
source share

To help people using Lisp, I would say that in OCAML there are only two evaluation rules:

  • Deferred valuation rule . The value of a function, for example fun x -> body , if it does not apply to any argument, will no longer be evaluated. (The evaluation of the body of the function is "delayed.") Instead, the expression "body" is compiled into computer code. This computer code is the real "value" of the function expression, and the code will be executed whenever the function is applied to the argument.
  • Bright rule of assessment . When evaluating fx , the argument x is first evaluated. (Functions "tend to evaluate their arguments.") Then, the expression of the function f calculated, which usually gives the value of the function, such as fun x -> body . (Here, body is not evaluated yet, it is only estimated that we get the value of the fun x -> body function. For example, f can be a complex expression that gives such a function value as the result.) Finally, the body of the resulting function is applied to the actually calculated value of the argument (i.e. body is evaluated using x , replaced by the calculated value of the argument).

For this reason, you can implement a β€œquote” in OCAML if you want to defer evaluation of some expression by just placing it in the body of the function expression. For example, if you previously calculated f on let f = fun x->x+1 , and now you want to postpone the evaluation of f 3 , you can put this f 3 in the body of the function:

  let delay_f () = f 3;; 

Now you will get 4 only when evaluating delay_f () . You can pass the delay_f value delay_f another function, and f 3 will remain unchanged until someone evaluates delay_f () .

0
source share

All Articles