Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0006136OCamlOCaml documentationpublic2013-08-22 15:312014-07-24 20:20
Reporteryallop 
Assigned To 
PrioritynormalSeverityminorReproducibilityalways
StatusconfirmedResolutionopen 
PlatformOSOS Version
Product Version 
Target Versionafter-4.02.0Fixed in Version 
Summary0006136: Function call evaluation order varies more than manual allows
DescriptionThe manual says that OCaml application is multi-argument

   The expression expr argument1 … argumentn evaluates the expression expr and
   those appearing in argument1 to argumentn.

and that the order of evaluation of the arguments and the function is
unspecified:

   The order in which the expressions expr, argument1, …, argumentn are
   evaluated is not specified.

However, the time of the actual call is specified: it takes place after the
function expression and all the argument expressions have been evaluated:

   The expression expr must evaluate to a functional value f, which is then
   applied to the values of argument1, …, argumentn.

In practice, there's more variation in the behaviour; it shows up when a
function performs an effect after receiving arguments. Here's an example
showing the different behaviour between ocamlc and ocamlopt, and with known
and unknown functions:

First, the example. (The function syntactically takes two arguments, but its
type 'a -> 'b -> 'a allows more.)

   $ cat call.ml
   let f g x = ignore (failwith "called f"); g

   let g x = x

   let h = f g 2 (failwith "third argument")

With ocamlc the function is never called, since the evaluation of the third
argument raises an exception:

   $ ocamlc call.ml -o call && ./call
   Fatal error: exception Failure("third argument")

With ocamlopt the function is called before receiving all three arguments, so
the third argument is never evaluated:

   $ ocamlopt call.ml -o call && ./call
   Fatal error: exception Failure("called f")

Here's a variation of the example where f is no longer statically visible:

   $ cat call2.ml
   let f g x = ignore (failwith "called f"); g

   let g x = x

   let h f =
     f g 2 (failwith "third argument")

   let _ = h f

Now ocamlopt evaluates all three arguments before calling the function:

   $ ocamlopt call2.ml -o call2 && ./call2
   Fatal error: exception Failure("third argument")
TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0010228)
doligez (administrator)
2013-08-22 23:34

Simplifying the examples a little bit:

let pr x = Printf.printf "%s\n%!" x;;
let f = fun x -> ignore (pr "f"); fun y -> ();;
f (pr "1") (pr "2");;

With ocamlc, we get the expected "2 1 f"; with ocamlopt, we get "1 f 2".

- Issue History
Date Modified Username Field Change
2013-08-22 15:31 yallop New Issue
2013-08-22 23:34 doligez Note Added: 0010228
2013-08-22 23:34 doligez Status new => confirmed
2013-08-22 23:34 doligez Target Version => 4.01.1+dev
2014-05-25 20:20 doligez Target Version 4.01.1+dev => 4.02.0+dev
2014-07-24 20:20 doligez Target Version 4.02.0+dev => after-4.02.0


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker