Should && and || translate to short-circuiting andalso and orelse?
To Reproduce
- Create a file
main.mlwith
let print_int number = Io.format "~0tp~n" [ number ]
let print_and_return_true number =
print_int number ;
true
let main _ =
print_int 0 ;
false && print_and_return_true 1 ;
true || print_and_return_true 2 ;
print_int 3
- Run command
caramel compile main.ml && escript main.erl - See result:
0
1
2
3
Expected behavior If the operators should be short-circuiting, the correct result would be:
0
3
just like when running this ocaml file:
(* let print_int number = Io.format "~0tp~n" [ number ] *)
let print_and_return_true number =
print_int number ;
true ;;
let main _ =
print_int 0 ;
false && print_and_return_true 1 ;
true || print_and_return_true 2 ;
print_int 3 ;;
main ()
$ ocaml main.ml
0
3
If the operators should be short-circuiting, I think the correct Erlang to generate here might be:
-spec main(_) -> ok.
main(_) ->
print_int(0),
false andalso print_and_return_true(1),
true orelse print_and_return_true(2),
print_int(3).
Environment (please complete the following information):
- OS: Ubuntu Linux 18.04
- Caramel version: 0.1
- Erlang version: 23.2.2
I am not super sure about the short-circuit operators semantics in OCaml, I found this issue that confuses me more than helps: https://stackoverflow.com/questions/23833221/order-of-evaluation-for-short-circuit-operators-and-let-in-ocaml
But in general, OCaml stdlib documentation says they should be short-circuiting, so I think they should translate to andalso and orelse as noted above.
I looked into fixing this and it seems that the way the code generation currently works, it would be easiest to have additional functions in caramel_runtime because andalso and orelse are not functions exported from the erlang module. I am honestly surprised the other operators are. I think there's no guarantee that it will stay this way as they are not documented there.
Should I send a PR that adds those functions to the runtime module? I think ideally all operators would get inlined without additional function calls but I understand this would complicate supporting passing them as arguments to higher order functions.
edit: but then, if these would work through a function call, they would no longer be short-circuiting anymore I think (?)
edit: comment moved to https://github.com/AbstractMachinesLab/caramel/issues/70