## syntax problem ?

Expand Messages
• Hi All, ... open Printf;; let bau () = let a = ref 0 in let f x = a := x in begin printf %d n !a; f 1 end;; bau ();; (* prints 0 *) bau ();; (* prints 0 *)
Message 1 of 12 , Sep 29, 2004
Hi All,

I don't understand why these two code pieces behave differently:

--- begin piece A ---
open Printf;;

let bau () =
let a = ref 0 in
let f x = a := x in
begin
printf "%d\n" !a;
f 1
end;;
bau ();; (* prints 0 *)
bau ();; (* prints 0 *)
--- end piece A ---

This code behaves as I expected. However, the following one is beyond
my current comprehension :)

--- begin piece B ---
open Printf;;

let bau =
let a = ref 0 in
let f x = a := x in
function () ->
begin
printf "%d\n" !a;
f 1
end;;
bau ();; (* prints 0 *)
bau ();; (* prints 1 !!! Why? *)
--- end piece B ---

The same happens if instead of "function ()" you have a "real"
pattern matching.

regards,

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages!
http://promotions.yahoo.com/new_mail
• ... In the above code, you create a fresh reference to 0 each time the function is called. So the let f x = a := x and f 1 have no effect - they can be
Message 2 of 12 , Sep 29, 2004
On Wed, Sep 29, 2004 at 09:04:40AM -0700, Radu Grigore wrote:
> I don't understand why these two code pieces behave differently:
>
> --- begin piece A ---
> open Printf;;
>
> let bau () =
> let a = ref 0 in
> let f x = a := x in
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 0 *)
> --- end piece A ---

In the above code, you create a fresh reference to 0 each time the
function is called. So the 'let f x = a := x' and 'f 1' have no
effect - they can be removed.

The equivalent in C would be something like:

bau ()
{
int a = 0;
printf ("%d", a);
a = 1;
}

> --- begin piece B ---
> open Printf;;
>
> let bau =
> let a = ref 0 in
> let f x = a := x in
> function () ->
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 1 !!! Why? *)
> --- end piece B ---

This is quite different. One reference to 0 is created when the
program first starts up. It is named 'a'. After the function is
called first time, the reference is updated to 1, so the second time
the function is called, it prints 1.

The equivalent in C would be:

bau ()
{
static int a = 0;
printf ("%d", a);
a = 1;
}

Here's something clever:

let errors = ref [] in
let add_error msg = errors := msg :: !errors in
let get_errors () = let r = List.rev !errors in errors := []; r in

- : unit = ()
- : unit = ()
# get_errors ();;
- : string list = ["hello"; "goodbye"]
- : unit = ()
# get_errors ();;
- : string list = ["another thing"]

Notice how the implementation of the two functions is hidden, and
could be changed without affecting callers in any way. It's a sort of
very lightweight abstract datatype.

Rich.

--
Richard Jones. http://www.annexia.org/ http://www.j-london.com/
Merjis Ltd. http://www.merjis.com/ - improving website return on investment
Learning Objective CAML for C, C++, Perl and Java programmers:
http://www.merjis.com/richj/computers/ocaml/tutorial/

[Non-text portions of this message have been removed]
• ... This is because of when things get evaluated, most specifically, when the lines: let a = ref 0 in let f x = a := x in ... get evaluated. In the first
Message 3 of 12 , Sep 29, 2004
On Wed, 29 Sep 2004, Radu Grigore wrote:

>
> Hi All,
>
> I don't understand why these two code pieces behave differently:
>
> --- begin piece A ---
> open Printf;;
>
> let bau () =
> let a = ref 0 in
> let f x = a := x in
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 0 *)
> --- end piece A ---
>
> This code behaves as I expected. However, the following one is beyond
> my current comprehension :)
>
> --- begin piece B ---
> open Printf;;
>
> let bau =
> let a = ref 0 in
> let f x = a := x in
> function () ->
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 1 !!! Why? *)
> --- end piece B ---
>

This is because of when things get evaluated, most specifically, when the
lines:
let a = ref 0 in
let f x = a := x in
...

get evaluated. In the first case, they get re-evaluated every time you
call the function bau. In the second case they only get called once- when
the value of bau is calculated (to be a function). In other words, in the
first case, every call to bau has a different a and a different f, in the
second case all calls to bau share the same a and f.

This is more easily demonstrated:

# let foo1 = fun x y -> let _ = print_string "Got here!\n" in x + y;;
val foo1 : int -> int -> int = <fun>
# foo1;;
- : int -> int -> int = <fun>
# foo1 2 3 ;;
Got here!
- : int = 5
# let foo2 = let _ = print_string "Got here!\n" in fun x y -> x + y;;
Got here!
val foo2 : int -> int -> int = <fun>
# foo2;;
- : int -> int -> int = <fun>
# foo2 2 3;;
- : int = 5
# fun x y -> x + y;;
- : int -> int -> int = <fun>
#

--
"Usenet is like a herd of performing elephants with diarrhea -- massive,
difficult to redirect, awe-inspiring, entertaining, and a source of
mind-boggling amounts of excrement when you least expect it."
- Gene Spafford
Brian
• ... Let s see if I have understood. First, these two lines of code are equivalent: let a = ;; let a = fun - ;; Second, for this
Message 4 of 12 , Sep 29, 2004
--- Brian Hurt <bhurt@...> wrote:
> This is because of when things get evaluated,

Let's see if I have understood.
First, these two lines of code are equivalent:
let a <args> = <expr>;;
let a = fun <args> -> <expr>;;

Second, for this binding:
let a = let u = <eu> in let v = <ev> in <args>
-> let x = <ex> in let y = <ey> in <ea>;;

there are two times when expressions get evaluated:
1. definition time: <eu> and <ev>
2. application of a: <ex>, <ey>, and <ea>

Now, what about partial applications of a? Let's say we have:

let a = let u = <eu> in fun x -> let v = <ev> in
(fun y z -> let w = <ew> in <ea>);;

In this case:
1. at definition time <eu> gets evaluated
2. when you apply a to the first argument <ev> gets evaluated
3. if you apply it to two more, then <ew> and <ea> get evaluated.

I guess that in this case if you apply a to two arguments <ew> will
get evaluated but not <ea>. Is this correct? And, another question,
if the paranthesis are dropped in the above definition do the
semantics remain unchanged?

regards,

__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
• ... So let s keep it simple. These two expressions are indeed equivalent: let a = ;; let a = fun - ;; BUT ... what you ve actually
Message 5 of 12 , Sep 29, 2004
On Wed, Sep 29, 2004 at 11:32:10AM -0700, Radu Grigore wrote:
>
> --- Brian Hurt <bhurt@...> wrote:
> > This is because of when things get evaluated,
>
> Let's see if I have understood.
> First, these two lines of code are equivalent:
> let a <args> = <expr>;;
> let a = fun <args> -> <expr>;;

So let's keep it simple. These two expressions are indeed equivalent:

let a <args> = <expr>;;
let a = fun <args> -> <expr>;;

BUT ... what you've actually got is:

let a <args> = <expr>;;
^
|
something here

vs:

let a = fun <args> -> <expr>;;
^
|
something here

and this is where the difference arises. Think about the simpler
expression:

let a = <expr>;;

In this case <expr> is evaluated when the program starts up. (To be
more precise, it's evaluated when the module containing 'a' is loaded,

So, the expression:

let a = fun <args> -> <expr>;;
^
|
something here

the 'something here' is evaluated when the program starts up, just
once. The 'something here' in your original example happens to be
some code which creates a reference and a function 'f' which sets the
reference.

Is that clearer?

Rich.

--
Richard Jones. http://www.annexia.org/ http://www.j-london.com/
Merjis Ltd. http://www.merjis.com/ - improving website return on investment
Perl4Caml lets you use any Perl library in your type-safe Objective
CAML programs. http://www.merjis.com/developers/perl4caml/

[Non-text portions of this message have been removed]
• in the first case, bau is defined as a function that takes an empty tuple and does various things (creating a reference, printing, assigning values etc).
Message 6 of 12 , Sep 29, 2004
in the first case, bau is defined as a function that takes an empty tuple
and does various things (creating a reference, printing, assigning values
etc). those things are done when the function is called.

in the second case, bau is assigned to the result of a series of commands.
a is created and a function that is defined that references a. so a
exists outside of the function (although you cannot access it apart from
via that function, because there is no other reference available). when
that function, which is bound to bau, is called, it modifies the value.

the key point is that in the second case a is *outside* the function bound
to bau. it has its own existence. in the first case, a is inside the
function, so is created again each time the function is called.

andrew

>
> Hi All,
>
> I don't understand why these two code pieces behave differently:
>
> --- begin piece A ---
> open Printf;;
>
> let bau () =
> let a = ref 0 in
> let f x = a := x in
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 0 *)
> --- end piece A ---
>
> This code behaves as I expected. However, the following one is beyond
> my current comprehension :)
>
> --- begin piece B ---
> open Printf;;
>
> let bau =
> let a = ref 0 in
> let f x = a := x in
> function () ->
> begin
> printf "%d\n" !a;
> f 1
> end;;
> bau ();; (* prints 0 *)
> bau ();; (* prints 1 !!! Why? *)
> --- end piece B ---
>
> The same happens if instead of "function ()" you have a "real"
> pattern matching.
>
> regards,
>
>
>
>
> __________________________________
> Do you Yahoo!?
> New and Improved Yahoo! Mail - Send 10MB messages!
> http://promotions.yahoo.com/new_mail
>
>
>
> Archives up to July 22, 2003 are also at
> http://www.connettivo.net/cntprojects/ocaml_beginners/ocaml_beginners_archive_220703/
> The archives of the very official ocaml list (the seniors' one) can be
> found at http://caml.inria.fr
> Attachments are banned and you're asked to be polite, avoid flames etc.
> etc.p://caml.inria.fr
> Attachments are banned and you're asked to be polite, avoid flames etc.
> etc.
>
>
>
>
>
>
>
>

--
` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
/ _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
\__,_\__\___/\___/_\_\___| list: http://www.acooke.org/andrew/compute.html
• ... Yes. ... Yes. u and v are semi-globals. In that all calls to a share the same variables, but no one else can see them. ... By jove, I think he s got it!
Message 7 of 12 , Sep 29, 2004
On Wed, 29 Sep 2004, Radu Grigore wrote:

>
> --- Brian Hurt <bhurt@...> wrote:
> > This is because of when things get evaluated,
>
> Let's see if I have understood.
> First, these two lines of code are equivalent:
> let a <args> = <expr>;;
> let a = fun <args> -> <expr>;;

Yes.

>
> Second, for this binding:
> let a = let u = <eu> in let v = <ev> in <args>
> -> let x = <ex> in let y = <ey> in <ea>;;
>
> there are two times when expressions get evaluated:
> 1. definition time: <eu> and <ev>
> 2. application of a: <ex>, <ey>, and <ea>

Yes. u and v are semi-globals. In that all calls to a share the same
variables, but no one else can see them.

>
> Now, what about partial applications of a? Let's say we have:
>
> let a = let u = <eu> in fun x -> let v = <ev> in
> (fun y z -> let w = <ew> in <ea>);;
>
> In this case:
> 1. at definition time <eu> gets evaluated
> 2. when you apply a to the first argument <ev> gets evaluated
> 3. if you apply it to two more, then <ew> and <ea> get evaluated.

By jove, I think he's got it!

Yep. This is exactly how this works. And it's simple enough to
demonstrate:
# let f =
let _ = print_string "Point 1\n" in
fun x ->
let _ = print_string "Point 2\n" in
fun y ->
let _ = print_string "Point 3\n" in
x + y
;;
Point 1
val f : int -> int -> int = <fun>
# f 1;;
Point 2
- : int -> int = <fun>
# let g = f 1;;
Point 2
val g : int -> int = <fun>
# g 2;;
Point 3
- : int = 3
# f 1 2;;
Point 2
Point 3
- : int = 3
#

> I guess that in this case if you apply a to two arguments <ew> will
> get evaluated but not <ea>. Is this correct? And, another question,
> if the paranthesis are dropped in the above definition do the
> semantics remain unchanged?

Yes. The semantic remain unchanged.

--
"Usenet is like a herd of performing elephants with diarrhea -- massive,
difficult to redirect, awe-inspiring, entertaining, and a source of
mind-boggling amounts of excrement when you least expect it."
- Gene Spafford
Brian
• ... What I ve got is let f x = let a = ref b in which according to my first observation is equivalent to let f = fun x - let a = ref b in which
Message 8 of 12 , Sep 29, 2004
--- Richard Jones <rich@...> wrote:

> On Wed, Sep 29, 2004 at 11:32:10AM -0700, Radu Grigore wrote:
> >
> > --- Brian Hurt <bhurt@...> wrote:
> > > This is because of when things get evaluated,
> >
> > Let's see if I have understood.
> > First, these two lines of code are equivalent:
> > let a <args> = <expr>;;
> > let a = fun <args> -> <expr>;;
>
> So let's keep it simple. These two expressions are indeed
> equivalent:
>
> let a <args> = <expr>;;
> let a = fun <args> -> <expr>;;
>
> BUT ... what you've actually got is:

What I've got is
let f x = let a = ref b in <expr>

which according to my first observation is equivalent to
let f = fun x -> let a = ref b in <expr>

which can be analysed according to my second observation.

regards,

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - Send 10MB messages!
http://promotions.yahoo.com/new_mail
• ... No, these two are not equivalent. Rich. -- Richard Jones. http://www.annexia.org/ http://www.j-london.com/ Merjis Ltd. http://www.merjis.com/ - improving
Message 9 of 12 , Sep 30, 2004
On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
> What I've got is
> let f x = let a = ref b in <expr>
>
> which according to my first observation is equivalent to
> let f = fun x -> let a = ref b in <expr>

No, these two are not equivalent.

Rich.

--
Richard Jones. http://www.annexia.org/ http://www.j-london.com/
Merjis Ltd. http://www.merjis.com/ - improving website return on investment
Learning Objective CAML for C, C++, Perl and Java programmers:
http://www.merjis.com/richj/computers/ocaml/tutorial/

[Non-text portions of this message have been removed]
• ... You must have been thinking about something else, because I see no semantical difference here. Frédéric.
Message 10 of 12 , Sep 30, 2004
Richard Jones wrote:
>
> On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
> > What I've got is
> > let f x = let a = ref b in <expr>
> >
> > which according to my first observation is equivalent to
> > let f = fun x -> let a = ref b in <expr>
>
> No, these two are not equivalent.
>
> Rich.

You must have been thinking about something else,
because I see no semantical difference here.

Frédéric.
• ... [begin note] The function was something like (irrelevant parts omitted): let a = fun x - fun y z - let w = in [end note] Another equivalence to
Message 11 of 12 , Sep 30, 2004
--- Brian Hurt <bhurt@...> wrote:
> By jove, I think he's got it!

:) Well, thanks again.

But I have made one error in my post:

> > I guess that in this case if you apply a to two arguments
> > <ew> will get evaluated but not <ea>.

[begin note]
The function was something like (irrelevant parts omitted):
let a = fun x -> fun y z -> let w = <ew> in <ea>
[end note]

Another equivalence to keep in mind:
fun x y z ->
fun x -> fun y -> fun z ->

It follows that a applied to two parameters does _not_ evaluate <ew>.

regards,

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail
• ... Sorry yes, I was mistaken. What I meant was the following aren t equivalent, which is related (I think) to the original topic: let f x = let a = ref b in
Message 12 of 12 , Sep 30, 2004
On Thu, Sep 30, 2004 at 08:20:38AM +0000, Frederic van der Plancke wrote:
>
>
> Richard Jones wrote:
> >
> > On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
> > > What I've got is
> > > let f x = let a = ref b in <expr>
> > >
> > > which according to my first observation is equivalent to
> > > let f = fun x -> let a = ref b in <expr>
> >
> > No, these two are not equivalent.
> >
> > Rich.
>
> You must have been thinking about something else,
> because I see no semantical difference here.

Sorry yes, I was mistaken. What I meant was the following aren't
equivalent, which is related (I think) to the original topic:

let f x = let a = ref b in <expr>
let f = let a = ref b in fun x -> <expr>

Rich.

--
Richard Jones. http://www.annexia.org/ http://www.j-london.com/
Merjis Ltd. http://www.merjis.com/ - improving website return on investment
Learning Objective CAML for C, C++, Perl and Java programmers:
http://www.merjis.com/richj/computers/ocaml/tutorial/

[Non-text portions of this message have been removed]
Your message has been successfully submitted and would be delivered to recipients shortly.