Reputation: 629
Scala allows function parameters to be call-by-name using the '=>
' syntax. For example, the boolean and
function can be defined as:
def and(x: Boolean, y: => Boolean): Boolean =
if (x) y else false
The second parameter is call-by-name. This ensures the expected "short-circuiting" behaviour – if x
is false
, y
will not be evaluated at all.
In general, this is useful for functions where a parameter might not be used at all.
How can this be done in OCaml?
I am aware that OCaml has constructs for lazy evaluation, but it is not clear to me if and how these could be used for call-by-name parameter passing.
Upvotes: 1
Views: 283
Reputation: 4441
First of all, by construction, boolean operators are lazy:
# false || (print_endline "second"; true);;
second
- : bool = true
# true || (print_endline "second"; true);;
- : bool = true
# true && (print_endline "second"; false);;
second
- : bool = false
# false && (print_endline "second"; false);;
- : bool = false
Then, for more custom functions, you should indeed use lazy (with the huge benefit that lazy values are memoised after being evaluated):
let fib n =
let rec aux n b a =
Printf.printf "%d %d %d\n" n b a;
if n <= 0 then a else aux (n - 1) (a + b) b
in
aux n 1 0
let f a b = if b > 0 then Lazy.force a + 1 else b
(* val f : int lazy_t -> int -> int = <fun> *)
let () =
let r = lazy (fib 10) in
let r2 = lazy (fib 1000000) in
Printf.printf "%d\n" (f r 1 + f r 2 + f r2 0)
The result will be:
10 1 0
9 1 1
8 2 1
7 3 2
6 5 3
5 8 5
4 13 8
3 21 13
2 34 21
1 55 34
0 89 55
112
r
has only be evaluated once and r2
has never been evaluated.
Upvotes: 2