caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re:  Constructor/reference bug?
@ 1999-08-12 12:05 Damien Doligez
  0 siblings, 0 replies; 6+ messages in thread
From: Damien Doligez @ 1999-08-12 12:05 UTC (permalink / raw)
  To: caml-list, skaller

>From: John Skaller <skaller@maxtal.com.au>

>let g x = 
>let lineno = ref (1,"") in
>let rec f x' = match x' with
>| NEWLINE p :: t -> lineno := p; f t
>| COLON :: t     -> CTRL !lineno :: f t
>| h :: t -> h :: f t
>| [] -> []
>in f x;;
>
>The code doesn't work as I expected: every
>CTRL value refers to the same lineno, the last one.
>If I change the COLON line to read:
>
>| COLON :: t -> let x = !lineno in CTRL x :: f t
>
>the code works as expected -- the CTRL refers to the
>value of lineno at the time the last NEWLINE was processed.
>
>What's happening? Are coproduct constructors lazy?


You have to be careful because f is a function with side effects.

In the line

    | COLON :: t     -> CTRL !lineno :: f t

the subexpression "!lineno" is not guaranteed to be evaluated before
"f t".  The current implementation happens to evaluate "f t" first.
Using "let x = !lineno in ..." is the right way to write your
function.

-- Damien




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Constructor/reference bug?
  1999-08-11  8:05 John Skaller
                   ` (2 preceding siblings ...)
  1999-08-12 11:25 ` Andreas Rossberg
@ 1999-08-12 12:16 ` Markus Mottl
  3 siblings, 0 replies; 6+ messages in thread
From: Markus Mottl @ 1999-08-12 12:16 UTC (permalink / raw)
  To: John Skaller; +Cc: OCAML

> let g x = 
> let lineno = ref (1,"") in
> let rec f x' = match x' with
> | NEWLINE p :: t -> lineno := p; f t
> | COLON :: t     -> CTRL !lineno :: f t
> | h :: t -> h :: f t
> | [] -> []
> in f x;;
> 
> The code doesn't work as I expected: every
> CTRL value refers to the same lineno, the last one.
> If I change the COLON line to read:
> 
> | COLON :: t -> let x = !lineno in CTRL x :: f t
> 
> the code works as expected -- the CTRL refers to the
> value of lineno at the time the last NEWLINE was processed.
> 
> What's happening? Are coproduct constructors lazy?

No, but OCaml evaluates all kind of expressions right-to-left which is
probably not very intuitive for people who are used to read from left
to right...

Regards,
Markus Mottl

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Constructor/reference bug?
  1999-08-11  8:05 John Skaller
  1999-08-12 10:51 ` Nicolas Ollinger
  1999-08-12 11:22 ` Jean-Christophe Filliatre
@ 1999-08-12 11:25 ` Andreas Rossberg
  1999-08-12 12:16 ` Markus Mottl
  3 siblings, 0 replies; 6+ messages in thread
From: Andreas Rossberg @ 1999-08-12 11:25 UTC (permalink / raw)
  To: John Skaller; +Cc: caml-list

John Skaller wrote:
> 
> let g x =
> let lineno = ref (1,"") in
> let rec f x' = match x' with
> | NEWLINE p :: t -> lineno := p; f t
> | COLON :: t     -> CTRL !lineno :: f t
> | h :: t -> h :: f t
> | [] -> []
> in f x;;
> 
> The code doesn't work as I expected: every
> CTRL value refers to the same lineno, the last one.

Evaluation order of application is not specified in OCaml: arguments may
be evaluated in any order (in fact, byte code does it right-to-left,
native code left-to-right, if I remember correctly). That seems to be
what's happening here: (f t), the second argument to ::, is evaluated
before (CTRL !lineno). Using let eliminates this problem.

HTH,

	- Andreas


-- 
Andreas Rossberg, rossberg@ps.uni-sb.de

:: be declarative. be functional. just be. ::




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Constructor/reference bug?
  1999-08-11  8:05 John Skaller
  1999-08-12 10:51 ` Nicolas Ollinger
@ 1999-08-12 11:22 ` Jean-Christophe Filliatre
  1999-08-12 11:25 ` Andreas Rossberg
  1999-08-12 12:16 ` Markus Mottl
  3 siblings, 0 replies; 6+ messages in thread
From: Jean-Christophe Filliatre @ 1999-08-12 11:22 UTC (permalink / raw)
  To: John Skaller; +Cc: caml-list


> | COLON :: t     -> CTRL !lineno :: f t
>
> The code doesn't work as I expected: every
> CTRL value refers to the same lineno, the last one.
> If I change the COLON line to read:

That is only because the second argument is evaluated before the first
one in a cons (::). Indeed, you can try 

======================================================================
# print_int 1 :: print_int 2 :: [];;
======================================================================

and you will get 

======================================================================
21- : unit list = [(); ()]
======================================================================

It explains  your problem. As you  can read it in  the ocaml reference
manual,  the  order  of  evaluation  of tuples  elements  in  the  not
specified :

======================================================================
Products

The expression expr1 ,..., exprn evaluates to the n-tuple of the values of expressions expr1 to exprn. The
evaluation order for the subexpressions is not specified.

Variants

The expression ncconstr expr evaluates to the variant value whose constructor is ncconstr, and whose argument
is the value of expr.
======================================================================

so your second code with a "let in" should be used. 

> | COLON :: t -> let x = !lineno in CTRL x :: f t

Best regards,
-- 
Jean-Christophe FILLIATRE
  mailto:Jean-Christophe.Filliatre@lri.fr
  http://www.lri.fr/~filliatr




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Constructor/reference bug?
  1999-08-11  8:05 John Skaller
@ 1999-08-12 10:51 ` Nicolas Ollinger
  1999-08-12 11:22 ` Jean-Christophe Filliatre
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Nicolas Ollinger @ 1999-08-12 10:51 UTC (permalink / raw)
  To: John Skaller; +Cc: caml-list

On Wed, 11 Aug 1999, John Skaller wrote:

> I have some code like:

(snip)

> What's happening? Are coproduct constructors lazy?
> 
> [I tested some simpler samples by hand and my tests
> worked as expected, so I'm confused]

here is a simpler sample :

let blob = ref 0 in
let rec f = function
| true::t -> incr blob; f t 
| false::t -> (!blob)::(f t)
| [] -> []
in f [true;false;false;false;true;true;false];;

the result is : [3; 3; 3; 3].

But this is not a bug... this is normal!
And of course if you write let tmp = !blob in tmp::(f t) the
result will be  [1; 1; 1; 3].

You don't see why it is so because there is a mix of infix and prefix
operators there. But remember that the order of arguments evaluation is
not specified in Caml. And precisely, OCaml do it from right to left.
Then, the text:
(!blob)::(f t)

Is translated into something like:
let arg2 = f t
and arg1 = !blob in
arg1::arg2

It calls f before computing !blob.

In hope this will help you,
N.
--





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Constructor/reference bug?
@ 1999-08-11  8:05 John Skaller
  1999-08-12 10:51 ` Nicolas Ollinger
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: John Skaller @ 1999-08-11  8:05 UTC (permalink / raw)
  To: caml-list

I have some code like:

let g x = 
let lineno = ref (1,"") in
let rec f x' = match x' with
| NEWLINE p :: t -> lineno := p; f t
| COLON :: t     -> CTRL !lineno :: f t
| h :: t -> h :: f t
| [] -> []
in f x;;

The code doesn't work as I expected: every
CTRL value refers to the same lineno, the last one.
If I change the COLON line to read:

| COLON :: t -> let x = !lineno in CTRL x :: f t

the code works as expected -- the CTRL refers to the
value of lineno at the time the last NEWLINE was processed.

What's happening? Are coproduct constructors lazy?

[I tested some simpler samples by hand and my tests
worked as expected, so I'm confused]


-------------------------------------------------------
John Skaller    email: skaller@maxtal.com.au
		http://www.maxtal.com.au/~skaller
		phone: 61-2-96600850
		snail: 10/1 Toxteth Rd, Glebe NSW 2037, Australia





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~1999-08-12 14:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-08-12 12:05 Constructor/reference bug? Damien Doligez
  -- strict thread matches above, loose matches on Subject: below --
1999-08-11  8:05 John Skaller
1999-08-12 10:51 ` Nicolas Ollinger
1999-08-12 11:22 ` Jean-Christophe Filliatre
1999-08-12 11:25 ` Andreas Rossberg
1999-08-12 12:16 ` Markus Mottl

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).