Both achieve the same thing
# let x = fun () -> begin print_endline "Hello"; 1 end;;
val x : unit -> int = <fun>
# x ();;
Hello
- : int = 1
# let y = lazy begin print_endline "World"; 2 end;;
val y : int lazy_t = <lazy>
# Lazy.force y;;
World
- : int = 2
Is there any reason one should be preferred over the other? Which one is more efficient?
First of all, they do not behave the same, try to do Lazy.force y yet another time, and you will notice the difference, the "World" message is no longer printed, so the computation is not repeated, as the result was remembered in the lazy value.
This is the main difference between lazy computations and thunks. They both defer the computation until the time when they are forced. But the thunk will evaluate its body every time, where the lazy value will be evaluated once, and the result of the computation will be memoized.
Underneath the hood, the lazy value is implemented as a thunk object with a special flag. When runtime first calls the lazy value, it substitutes the body of the thunk with the result of computation. So, after the first call to Lazy.force y, the y object actually became an integer 2. So the consequent calls to Lazy.force do nothing.
Lazy.force returns the same value again without recomputing it.
Exemple
let ra = ref 0 ;;
let y = lazy (ra:= !ra+1);;
Lazy.force y;;
# Lazy.force y;;
- : unit = ()
# !ra;;
- : int = 1
# Lazy.force y;;
- : unit = ()
# !ra;;
- : int = 1
Related
If I have this function:
let x = print_endline "foo" in x,x;;
it has this signature: unit * unit = ((), ())
and evaluates to foo
I dont understand why it prints foo once.
On the other hand: let x () = print_endline "foo" in x(),x();; will print foo twice and has the signature:
unit * unit = ((), ())
can someone explain the principle behind this and how it works in this specific example?
OCaml is an eager language unless directed otherwise. To create lazy values we use the lazy keyword, e.g., lazy (print_endline "foo") will create a lazy value of type unit Lazy.t that will print foo, once it is forced with Lazy.force.
All other values in OCaml are eager and are evaluated immediately. You got confused with the let .. in ... syntactic form.
The syntactic form
let <var> = <expr1> in <expr2>
first evaluates <expr1> and then evaluates <expr2> with the value of <expr1> bound to <var>. Finally, the result of <expr2> becomes the value of the whole form.
So when you say, let x = 2 in x + x you first evaluate 2 and bind it to x and then evaluate x + x with x=2, which is 4, so the value of the expression let x = 2 in x + x in 4. This is a pure expression, it doesn't define any functions and doesn't bind x in the global context.
Going back to your example,
let x = print_endline "foo" in x, x
we first evaluate <expr1>, which is print_endline "foo" that has the side effect of printing foo and returns the value () of type unit. Next, () is bound to x and the <expr2> is evaluated, which x,x, and which is equal to (),().
Your second example,
let x () = print_endline "foo" in x (), x ()
binds x to the function fun () -> print_endline "foo" since
let f x = <expr>
is the syntactic sugar for
let f = fun x -> <expr>
i.e., to a definition of a function.
Therefore, your expression first evaluates <expr1>, which is now fun () -> print_endline "foo" and binds it to x. Now you evaluate x (), x () and calls x () twice, both calls return ().
Finally, you said in your question that,
If I have this function: let x = print_endline "foo" in x,x;;
You don't have any functions there. Much like in let x = 2 in x + x, you are not defining any functions but just evaluate x+x with x bound to 2. After it is evaluated, there are no leftovers, x is not bound to anything. In C-like syntax, it is the same as
{
int x = 2;
x + x;
}
So if you want to define a function, you have to use the syntax
let <name> <params> =
<expr>
Where <expr> is the body of the function that is evaluated in a context where each parameter is substituted with its actual value (argument).
E.g.,
let print_foo () =
print_endline "foo"
or,
let sum_twice x y =
let z = x + y in
2 * z
I would suggest reading the OCaml Tutorial to get a better idea of OCaml syntax.
There is no lazy evaluation involved in this code at all. It would be more the other way around: lazy code (in OCaml) often involves having a function of the form () -> 'a instead of a value 'a, but this doesn't mean that any function of this form has to do with lazy evaluation.
In the first snippet, let x = print_endline "foo" in x, x, you are binding x to a value, the result of print_endline "foo", and then returning x, x. However, by doing so you must call print_endline "foo", which will print foo. At this point, x : unit = (). Then, you return x, x, that is, (), ().
In the second snippet, let x () = print_endline "foo" in x (), x (), you are defining a function x. That form is syntax sugar for let x = fun () -> print_endline "foo" in x (), x (). For this reason, before the evaluation of x (), x (), you have x : unit -> unit = <fun>. Then, you call that function twice, each time printing foo, and returning ().
Note that, when you write something like let x () = ..., you could also be writing let x (y: unit) = ..., except that since the type unit has a single constructor (()), OCaml allows you to deconstruct it directly in the function declaration. Which is why you are allowed to write let x () = ....
I want to make a function in which the parameter is mutable.
I'm familiar with let a = ref 0 but how can i make "a" be a parameter for my function?
If you ask Ocaml nicely, it will infer the right type for you:
let incr x = x:= !x + 1
val incr : int ref -> unit = < fun >
How can I write a function in OCaml in which one or more argument are optional?
let foo x y z = if(x+y > z) then true else false;;
If foo do not receive the z argument it uses 0 as z.
foo 3 3 2 -> true
foo 3 3 10 -> false
foo 2 1 -> true
Is there any OCaml feature to achieve this?
OCaml has optional arguments, but it's quite a bit trickier than you would expect because OCaml functions fundamentally have exactly one argument. In your case, foo is a function that expects an int and returns a function.
If you leave off trailing arguments, normally this means that you're interested in the function that will be returned; this is sometimes called partial application.
The result is that trailing optional arguments (as you are asking for) do not work.
Optional arguments are always associated with a name, which is used to tell whether the argument is being supplied or not.
If you make z the first argument of your function rather than the last, you can get something like the following:
# let foo ?(z = 0) x y = x + y > z;;
val foo : ?z:int -> int -> int -> bool = <fun>
# foo 3 3 ~z: 2;;
- : bool = true
# foo 3 3 ~z: 10;;
- : bool = false
# foo 2 1;;
- : bool = true
In general I'd say that optional (and named) arguments in OCaml don't solve the same problems as in some other languages.
I personally never define functions with optional arguments; so, there may be better ways to achieve what you're asking for.
OCaml doesn't have optional arguments like you'd find in Java or C#. Since functions can be partially applied, optional arguments can make it hard to tell when you're done passing arguments and would like the function to be evaluated. However, OCaml does have labeled arguments with default values, which can be used to the same effect.
The usual caveats of labeled arguments apply. Note that labeled arguments can't appear at the end of the argument list since the function is evaluated as soon as it has everything it needs:
let foo x y ?z_name:(z=0) = (x + y) > z;;
Characters 12-39:
let foo x y ?z_name:(z=0) = (x + y) > z;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 16: this optional argument cannot be erased.
val foo : int -> int -> ?z_name:int -> bool = <fun>
Other parts of the argument list are fine:
# let foo ?z:(z=0) x y = (x + y) > z;;
val foo : ?z:int -> int -> int -> bool = <fun>
# foo 1 1;;
- : bool = true
# foo (-1) (-1);;
- : bool = false
# foo ~z:(-42) (-1) (-1);;
- : bool = true
In the same fashion as above, you lose the ability to supply the optional argument once you 'move past' it in the argument list:
# foo 1;;
- : int -> bool = <fun>
I defined a higher-order function like this:
val func : int -> string -> unit
I would like to use this function in two ways:
other_func (func 5)
some_other_func (fun x -> func x "abc")
i.e., by making functions with one of the arguments already defined. However, the second usage is less concise and readable than the first one. Is there a more readable way to pass the second argument to make another function?
In Haskell, there's a function flip for this. You can define it yourself:
let flip f x y = f y x
Then you can say:
other_func (func 5)
third_func (flip func "abc")
Flip is defined in Jane Street Core as Fn.flip. It's defined in OCaml Batteries Included as BatPervasives.flip. (In other words, everybody agrees this is a useful function.)
The question posed in the headline "change order of parameters" is already answered. But I am reading your description as "how do I write a new function with the second parameter fixed". So I will answer this simple question with an ocaml toplevel protocol:
# let func i s = if i < 1 then print_endline "Counter error."
else for ix = 1 to i do print_endline s done;;
val func : int -> string -> unit = <fun>
# func 3 "hi";;
hi
hi
hi
- : unit = ()
# let f1 n = func n "curried second param";;
val f1 : int -> unit = <fun>
# f1 4;;
curried second param
curried second param
curried second param
curried second param
- : unit = ()
#
Suppose a function g is defined as follows.
utop # let g ~y ~x = x + y ;;
val g : y:int -> x:int -> int = <fun>
utop # g ~x:1 ;;
- : y:int -> int = <fun>
utop # g ~y:2 ;;
- : x:int -> int = <fun>
utop # g ~x:1 ~y:2 ;;
- : int = 3
utop # g ~y:2 ~x:1 ;;
- : int = 3
Now there is another function foo
utop # let foobar (f: x:int -> y:int -> int) = f ~x:1 ~y:2 ;;
val foobar : (x:int -> y:int -> int) -> int = <fun>
Sadly when I try to provide g as the parameter of foobar, it complains:
utop # foobar g ;;
Error: This expression has type y:int -> x:int -> int
but an expression was expected of type x:int -> y:int -> int
This is quite surprising as I can successfully currify g but cannot pass it as the parameter. I googled and found this article which doesn't help much. I guess this is related to the underlying type system of OCaml (e.g. subtyping rules of labeled arrow types).
So is it possible to pass g as the parameter to foobar by any means in OCaml? If not, why is it not allowed? Any supporting articles/books/papers would be sufficient.
The key is that labels do not exist at runtime. A function of type X:int -> y:float -> int is really a function whose first argument is an int and whose second argument is a float.
Calling g ~y:123 means that we store the second argument 123 somewhere (in a closure) and we will use it automatically later when the original function g is finally called with all its arguments.
Now consider a higher-order function such as foobar:
let foobar (f : y:float -> x:int -> int) = f ~x:1 ~y:2.
(* which is the same as: *)
let foobar (f : y:float -> x:int -> int) = f 2. 1
The function f passed to foobar takes two arguments, and the float must be the first argument, at runtime.
Maybe it would be possible to support your wish, but it would add some overhead. In order for the following to work:
let g ~x ~y = x + truncate y;;
foobar g (* rejected *)
the compiler would have to create an extra closure. Instead you are required to do it yourself, as follows:
let g ~x ~y = x + truncate y;;
foobar (fun ~y ~x -> g ~x ~y)
In general, the OCaml compiler is very straightforward and won't perform this kind of hard-to-guess code insertion for you.
(I'm not a type theorist either)
Think instead of the types x:int -> y:float -> int and y:float -> x:int -> int. I claim these are not the same type because you can call them without labels if you like. When you do this, the first requires an int as its first parameter and a float as the second. The second type requires them in the reverse order.
# let f ~x ~y = x + int_of_float y;;
val f : x:int -> y:float -> int = <fun>
# f 3 2.5;;
- : int = 5
# f 2.5 3;;
Error: This expression has type float but an expression was
expected of type intÂ
Another complication is that functions can have some labelled and some unlabelled parameters.
As a result, the labeled parameters of a function are treated as a sequence (in a particular order) rather than a set (without an inherent order).
Possibly if you required all parameters to be labelled and removed the capability of calling without labels, you could make things work the way you expect.
(Disclaimer: I'm not a type theorist, though I wish I was.)
This pitfall of labels in OCaml is described in detail in the Labels and type inference subsection of the OCaml manual, giving an example similar to yours.
If I remember correctly, some type systems for labels lift that restriction, but at the cost of additional overall complexity that was judged "not worth it" for the OCaml language itself. Labels can be rearranged automatically at first-order application sites, but not when abstracting over labelled functions (or using such abstractions).
You can have your example accepted by manually eta-expanding the labelled function to make a reorderable application appear (a type-theorist would say this is a retyping eta-conversion):
# let f ~x ~y = x+y;;
val f : x:int -> y:int -> int = <fun>
# let yx f = f ~y:0 ~x:1;;
val yx : (y:int -> x:int -> 'a) -> 'a = <fun>
# yx f;;
Error: This expression has type x:int -> y:int -> int
but an expression was expected of type y:int -> x:int -> 'a
# yx (fun ~y ~x -> f ~y ~x);;
- : int = 1