* 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
* 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
* 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
* 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
@ 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
` (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
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