Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at ocaml.org.

Browse thread
Strange evaluation order
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2002-05-19 (09:27)
From: Michel Quercia <michel.quercia@p...>
Subject: Re: "ocaml_beginners"::[] Strange evaluation order
Le Sun, 19 May 2002 19:21:57 +0200
Nicolas Barbulesco <nbarbulesco@y...> écrivit :

> Hi,

Hello,

> 
> I wanted to test Caml's laziness in parameter evaluation... I explain
> what kind of laziness I am speaking about. (Generally, not
> Caml-specifically.) I have the function called first which takes two
> integers and returns the first one. If I call first(sin(4), sin(9)), the
> language will not calculate the sine of 9, will calculate the sine of 4,
> and will return it.

(math. note : none of sin(4), sin(9) are integers)

> So I wanted to test if Caml was thus-lazy (the answer seems to be no, by
> the way).

It's not. The argument in a function call is always evaluated before the
code of the function is triggered. This may or may not be in the reference
manual, I don't have it handy, but it is a well known fact.

> But I was very surprised that Caml evaluates the parameters from the
> right to the left.

The manual says or should say that order of evaluation is unspecified,
except in case of boolean operations :

if a then b else c -> a is evaluated first, then one of b or c is
evaluated, the other one is not.

> # let firstOfTheCouple = function
> (a,b) -> a ;;
> val firstOfTheCouple : 'a * 'b -> 'a = <fun>
> # firstOfTheCouple (double 5, double 6) ;;
> double 6
> double 5

Note that firstOfTheCouple takes _one_ argument, a pair, and thus this
pair must be fully evaluated before applying firstOfTheCouple (Ocaml has
no "half pairs"). The components of the pair are evaluated from right to
left ... but this is unspecified in the language.

> # let firstOfTheTwo = function
> a -> function
> b -> a ;;
> val firstOfTheTwo : 'a -> 'b -> 'a = <fun>
> # firstOfTheTwo (double 5) (double 6) ;;
> double 6
> double 5

You can force a left-to-right evaluation order by stating it explicitely :

# let f = firstOfTheTwo (double 5) in f(double 6) ;;
double 5
double 6
- : int = 10
# 

You can also get lazy evaluation with the "lazy" construct (see the ref.
man) :

# let lazyfun a b = let aval = Lazy.force a in if aval > 0 then aval else
Lazy.force b;;
val lazyfun : int Lazy.t -> int Lazy.t -> int = <fun>
# lazyfun (lazy(double 3)) (lazy(double 4));;
double 3
- : int = 6
# lazyfun (lazy(double (-3))) (lazy(double 4));;
double -3
double 4
- : int = 8
# 

Regards,
-- 
Michel Quercia
23 rue de Montchapet, 21000 Dijon
http://michel.quercia.free.fr (maths)
http://pauillac.inria.fr/~quercia (informatique)
mailto:michel.quercia@p...