Nicholas Weston
Nicholas Weston

Reputation: 629

Does OCaml support call-by-name parameter passing?

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

Answers (1)

Lhooq
Lhooq

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

Related Questions