caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Re: Undefined evaluation order
@ 2000-10-10 18:55 John R Harrison
  0 siblings, 0 replies; 27+ messages in thread
From: John R Harrison @ 2000-10-10 18:55 UTC (permalink / raw)
  To: caml-list; +Cc: John Harrison


In the old ML compiler used in Cambridge LCF and HOL88 (which I guess was
a kind of ur-CAML), the order of evaluation was genuinely changeable, e.g:

   #let f x y = (x,y);;
   f = - : (* -> ** -> (* # **))

   #f (print_int 1;100) (print_int 2;200);;
   21(100, 200) : (int # int)

   #(I f) (print_int 1;100) (print_int 2;200);;
   12(100, 200) : (int # int)

We just ended up saying in HOL's DESCRIPTION manual:

   "Due to optimizations in the ML compiler, the order of evaluation
    may vary."

Gerard Huet might have been responsible for the optimizations that led to
this behaviour, so perhaps he knows more...

Cheers,

John.



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: Undefined evaluation order
@ 2000-10-20 14:59 Gerard Huet
  0 siblings, 0 replies; 27+ messages in thread
From: Gerard Huet @ 2000-10-20 14:59 UTC (permalink / raw)
  To: caml-list

At 22:35 11/10/00 +0200, Pierre Weis wrote:
>I would like to report the most difficult example I know to confuse students 
> [...]
>map add [1; 2; 3];;
>argument 3
>argument 2
>argument 1
>- : int list = [2; 3; 4]
Your students are not happy.
> [...]
>Pierre Weis

So, maybe it is time to write a course on programming in ML that will put
things up front so that people don't get bitten unexpectedly later on. 

I'll be glad to contribute to the first course. The intended style is like
FAQ,
code interspersed with comments. It is intended to teachers of ML beginners.
______________________________________________________________________________

Programming in ML - Course 1

1. Hello to the class.

You start the class by greeting everyone, telling them that it is a
programming
language class, that there is no prerequisite except knowing how to access a
computer account and using an editor, and you give them 3 informations :
a - how to login on their course account
b - what is the calling sequence to the ML top-level
c - what is the calling sequence to emacs configured with tuareg and stuff

and then you tell them a little bit of history, in fairy tale style (once upon
a time, there was LISP, there was LCF, there was (Edinburgh LCF) ML, blabla...
In this course we shall use as backend a modern implementation of ML called
Objective Caml V3.0, abbreviated Ocaml, and as front end a better syntax
defined with the Camlp4 preprocessor. 

2. Hello to the world.

This is the first programming example in any programming language : how to
print stuff on your terminal. If you do not know how to do that, you are
condemned to stay within a shallow shell, some read-eval loop interpreter, but
you do not have access to the wonderful world of your file system, operating
system, and the world wide web on Internet. So here it is :

value hello_world_in_Ocaml =
let the_inverting_demon _ = () in 
     the_inverting_demon(print_string "World!",
                         print_string "Hello ");

At this point students should react with various questions:

Question 1. Why are the two string "World!" and "Hello " written in the wrong
order ?

Answer. Look at the answer computed by ML for the value of
hello_world_in_Ocaml
and you will see that "Hello World!" gets printed, and thus the strings are
written in the right order, it is just that calling the function
the_inverting_demon executes the two print statements in reverse. 

Question 2. I do not understand how the_inverting_demon works. What is this
crazy notation ? If I type in "();" it tells me "- : unit = ()", and if I type
in "_" it tells me "Parse error", I am confused.

Answer. "()" is the unique value of data type unit, like "True" and "False"
are
the two values of data type bool. We use the dummy value "()" as the value of
statements, that is expressions which are used only for their effect, but this
way statements may be accommodated within the syntax as expressions. Thus if
you type in "print_string;" you see that print_string is a function of type
"string -> unit", and thus "print_string (print_string "Hello");" does not
print anything, since the type checker verifies that the inner expression has
type unit instead of the expected type string, and so you get a typing error
and the compilation aborts. Whereas "_" is not the representation of a value,
but of a pattern, it is the pattern that matches any value. Patterns can
appear
only in the contexts where formal parameters are expected, so you get a
parsing
error. 

Question 3. If _ matches any value, what is its type ?

Answer. If you bring the inside let expression as a top value declaration:
value the_inverting_demon _ = ();
then you see its type :
the_inverting_demon : 'a -> unit = <fun>
indicating that it takes a value of any type, since 'a is a type variable
(read
as alpha) which may be instanciated by any concrete type, and thus you may
call
the_inverting_demon ();
the_inverting_demon True;
the_inverting_demon "Hello"
and it always just returns the dummy value ().

Question 4. If it does nothing, why do you put it in the code of hello_world ?

Answer. If I remove it, I get a bug:
value buggy_hello_world_in_Ocaml = 
  (print_string "World!" print_string "Hello ");
I get "World!Hello " printed, this does not obey the spec of hello_world.

Question 5 (smart student). Why don't you write:
value hello_world = 
  (print_string "Hello " print_string "World!");

Answer. You may indeed. This is correct, and it will work not just in
Ocaml, but
in other dialects of ML, modulo adjustement of syntax. A program specification
admits many different solutions, we should not expect to have
non-redundancy in
programming; indeed there are many ways to program a task, some are more
efficient, some are more elegant, some have code that is better to understand
and maintain. 

Question 6 (dumb student). Why did you not give us hello_world in the first
place ?

Answer. Because I wanted to teach you the inverting effect of calling this
function on its two arguments, so that you understand the difference between
the_inverting_demon (print_string "World!", print_string "Hello ");
which prints "Hello World!" and 
the_inverting_demon (print_string "World!" print_string "Hello ");
which prints "World!Hello ".

[you may expect some students to leave the room at this point and look for
alternative programming courses in Java or C++]. A few brave and/or curious
students will keep asking questions as to why "," means right to left while ""
means left to right, until either a very smart student asks the following
question, or you yourself declare that the proper question to ask first is:

Question 7. Why does 
the_inverting_demon (print_string "Foo Bar");
print anything in the first place, since the_inverting_demon does not even
look
at its argument ?

Answer. Ah Ah ! This is because ML uses a strict evaluation regime: when you
call a function foo with an argument expression bar, which may be written
in ML
"foo bar" or "foo(bar)" or "(foo)bar" or "(foo bar)" or "(foo)(bar)" etc, what
happens is that first "foo" is evaluated to its (functional) value, that is a
so-called closure which encapsulates a piece of code with a representation of
the environment in which its global variables are bound to their values, then
bar is evaluated to a value, and finally we execute the code in the extended
environment. This is in contrast with other dialects of ML, such as Haskell,
which use a lazy evaluation regime, where 
the_inverting_demon (print_string "Foo Bar");
would return imediately value () without evaluating the argument to
the_inverting_demon since it is not needed, and thus without any printing
effect. Another terminology tells that Ocaml uses "call by value" whereas
Haskell uses "call by need". 

Question 8 (bright student). I still do not see why the arguments to
the_inverting_demon get evaluated from the right to the left.

Answer. Ah Ah! This is because Ocaml happens to evaluate multiple arguments
to a
function in a right to left manner. This has nothing to do with
the_inverting_demon, I just fooled you all along with a crazy name, but names
don't matter in a program, calling you functions "bug_free" or
"spec_certified"
does not help, only the program text matters. There are other dialects of ML,
such as SML, which use strict evaluation, but with left to right evaluation of
their arguments. Actually, you may test the evaluation regime of ML dialects
with the help of the following ML_tester, where we see another control
structure for programming exceptional effects:

value ML_tester () = 
let null _ = ()
in try (null(raise Left, raise Right); print_string "Haskell!")
    with [ Left -> print_string "SML!"
         | Right -> print_string "Ocaml!"
         ];

Question 9. Why did the implementers of Ocaml make this choice ?

Answer. Actually, they did not commit themselves to any particular order.
It is
more convenient to evaluate arguments from right to left in the bytecode
interpreter, as we shall see in a more advanced lesson, but the Ocaml manual
says that the order of evaluation of arguments is not specified, so that your
programs should not depend on it. And so maybe one day, after enough debate
proves conclusively that right to left has more inconvenients than advantages,
the Ocaml implementers will change their minds, and we shall change slightly
this introductory lesson.

Many questions from excited students speaking all together:
* How do you program Hello World in Haskell ?
* I typed in "(0,1);" to Ocaml and it returned the pair "(0,1)" and not the
pair "(1,0)", is this a bug ?

OK, now the course is over, see you to-morrow.













^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: Undefined evaluation order
@ 2000-10-14  1:42 David McClain
  0 siblings, 0 replies; 27+ messages in thread
From: David McClain @ 2000-10-14  1:42 UTC (permalink / raw)
  To: caml-list

Dave Berry writes:

> Are you saying that if (a * b) would result in a NaN
>then you always want (a * b * 0.0) to return a NaN, so that you are aware
> of the potential problem?

Yes! That is indeed the case. This is what the IEEE floating point spec
calls for. There are two kinds of Nan's -- signaling and non-signaling. The
signaling ones can potentially raise an exception, while the non-signaling
ones simply represent "Not-A-Number" values. One might use signaling Nan's
to initialize arrays, in some languages (i.e., Fortran) so that one could
catch the use of uninitialized variables...

I don't really distinguish the two in most of my work... Indeed, on the
Alpha architecture, you have to explicitly check for such errors by
inserting trap barrier instructions into the instruction stream. Hence, all
you can know is whether or not an exception has occured since the last time
you checked. The IEEE floating point spec allows for this kind of behavior
in the readily available FPU architectures as well (i.e., Pentium)

Most of my work involves signal and image processing on vast collections of
numbers, frequently in real-time environments. While the numerical analysts
might like to know about Nan signaling to help them write more sophisticated
(mathematical) function evaluators, nearly all of my math routines have to
be quick and not so exacting. In physics and measurement environments we
rarely have more than 3 significant digits in our data. Of course the work
of Prof. William Kahan, UC Berkeley, shows the need to carry many more
significant digits during intermediate calculations, but mathematical
refinement is not generally our concern. As I mentioned previously, if an
anomalous computation occurs in one or a few cases out of the billions that
we stream then we just drop it (them) on the floor and keep running...

- DM





^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: Undefined evaluation order
@ 2000-10-13 13:56 Dave Berry
  0 siblings, 0 replies; 27+ messages in thread
From: Dave Berry @ 2000-10-13 13:56 UTC (permalink / raw)
  To: Pierre Weis

David,

Thanks for your reply.  Are you saying that if (a * b) would result in a NaN
then you always want (a * b * 0.0) to return a NaN, so that you are aware of
the potential problem? 

Dave.

> -----Original Message-----
> From: David McClain [mailto:dmcclain@azstarnet.com]
> Sent: Thursday, October 12, 2000 6:06 PM
> To: caml-list@inria.fr
> Subject: Re: Undefined evaluation order
> 
> 
> ... but the same would be true the other way too... (0.0 * a * b).  I am a
> numeric programmer and these things are unavoidable no matter how you
choose
> to order the evaluations.
> 
> If (a * b) raises a NaN then what would be the value of 0.0 times that?
The
> IEEE spec would say the result would have to continue to be a NaN.
> 
> I normally perform all arithmetic with exception processing supressed or
> deferred. The only time an exception is useful to me is if there is some
> remedial action that could be taken. I want my NaN's and INF's to appear
in
> my answers. In particular, if something should go awry at one point out of
> millions I don't want that one point to hose my entire calculation. (Note
> that I do not look kindly at the Fortran way of aborting an entire program
> for one bad point...) In signal and image processing, especially in a
> real-time environment, you just drop the bad points on the floor and
> continue running.
> 
> - DM



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: Undefined evaluation order
@ 2000-10-12 17:06 David McClain
  0 siblings, 0 replies; 27+ messages in thread
From: David McClain @ 2000-10-12 17:06 UTC (permalink / raw)
  To: caml-list

... but the same would be true the other way too... (0.0 * a * b).  I am a
numeric programmer and these things are unavoidable no matter how you choose
to order the evaluations.

If (a * b) raises a NaN then what would be the value of 0.0 times that? The
IEEE spec would say the result would have to continue to be a NaN.

I normally perform all arithmetic with exception processing supressed or
deferred. The only time an exception is useful to me is if there is some
remedial action that could be taken. I want my NaN's and INF's to appear in
my answers. In particular, if something should go awry at one point out of
millions I don't want that one point to hose my entire calculation. (Note
that I do not look kindly at the Fortran way of aborting an entire program
for one bad point...) In signal and image processing, especially in a
real-time environment, you just drop the bad points on the floor and
continue running.

- DM

-----Original Message-----
From: Dave Berry <dave@kal.com>
To: Greg Morrisett <jgm@cs.cornell.edu>; caml-list@inria.fr
<caml-list@inria.fr>
Date: Thursday, October 12, 2000 4:53 AM
Subject: RE: Undefined evaluation order


>May I toss in a possible complication?   I'm thinking of numeric code, and
>the possibilities of optimisation.  To take a simple example, (a * b * 0.0)
>should always be zero.  Except that (a * b) could raise an exception or
>return a NaN.  I imagine there exist more complex numeric optimisations
that
>a compiler may wish to perform.
>
>So my question is whether numeric operations might be hampered by requiring
>a defined evaluation order, even in the case that changing the order has a
>visible (and desired!) effect.  I'm not a numeric programmer, and I know
>there are some numeric programmers on the list, so perhaps they would care
>to comment.
>
>Perhaps an alternative would be to specify the evaluation order, but allow
>the compiler to modify the evaluation order to reduce the possibilities of
>NaN results or numeric exceptions.  It wouldn't be as elegant as a
universal
>rule, but might be more practical.
>
>Dave.
>
>
>-----Original Message-----
>From: Greg Morrisett [mailto:jgm@cs.cornell.edu]
>Sent: Wednesday, October 11, 2000 1:23 PM
>To: 'Hendrik Tews'
>Cc: caml-list@inria.fr
>Subject: RE: Undefined evaluation order
>
>
>> I would like to vote for leaving the evaluation order
>> unspecified (implicitly repeating all suitable arguments from
>> previous postings). The specification should only regulate the
>> necessary things not more.
>
>I don't see why.  As far as I can tell, the only reason
>to not specify the order is for performance.  I've never
>seen a systematic study that significant performance
>gains are achievable across a range of applications.
>Most compilers only do very local re-orderings, and
>these can typically be achieved with local effects
>analysis (at least for languages like ML that are
>relatively effect free.)
>
>We've heard promises of expression-level parallelism
>since the dawn of Fortran and Lisp.  But for 40 years,
>they speedups have yet to be realized because the granularity
>is always too small to do the necessary synchronization
>for multi-processors, and the granularity is too large
>for instruction-level parallelism (i.e., other hazards
>manifest.)  If you truly believe that magic compilers
>will someday come along and parallelize things, then
>why are you worried that these compilers will be stopped
>by a specified evaluation order?
>
>IMHO, there are compelling reasons to at least specify
>an evaluation order, if not to standardize on left-to-
>right.  In spite of the fact that programmer's *should*
>realize that expressions could be evaluated in any order,
>they tend to assume the order that the current compiler
>uses.  Then when someone else ports the code, or the
>compiler changes, things break.
>
>As I mentioned earlier, when teaching, it's nice for
>a language to be simple and uniform.  Explaining to
>a student why:
>
> let x = input() in
> let y = input() in
> (x,y)
>
>is not equivalent to:
>
> (input(), input())
>
>is one more thing that confuses them -- especially when
>we emphasize that the whole point of anonymous functions
>is to avoid naming things that need not be named!
>
>A standard trick for Scheme coders is, as someone suggested,
>to randomize the order of evaluation in the hopes of
>tripping across such bugs.  Ugh.  Maybe the type-checker
>should just randomly type-check a few expressions too :-)
>
>If you're going to have an unspecified order of evaluation,
>then I think you realistically need an effects analysis
>in order to warn the programmer that what they are writing
>is dependent upon the order.  Unfortunately, either the
>analysis would need to be global (to get rid of all the
>false positives) or else you'd have to augment function
>types with effects information, add in polymorphic effects,
>etc.  In other words, you're buying into a whole ball of wax.
>Neither option seems all that wonderful.
>
>-Greg
>



^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: Undefined evaluation order
@ 2000-10-12 11:32 Greg Morrisett
  0 siblings, 0 replies; 27+ messages in thread
From: Greg Morrisett @ 2000-10-12 11:32 UTC (permalink / raw)
  To: 'Dave Berry', caml-list

> May I toss in a possible complication?   I'm thinking of 
> numeric code, and
> the possibilities of optimisation.  

I'm not saying that you can't get better performance
if you leave things unspecified.  Rather, a programmer
might like to know whether they'll get 0 or NaN (or
an exception) rather than "I'll get one of those things
real fast" :-)

Perhaps a practical solution would be to have a flag
controlling whether or not evaluation order is fixed.
Speed demons can turn the flag off, teachers can leave
the flag on.  

It wouldn't be that hard to implement, either -- leave
the compiler largely alone, but do an A-normalization
pass introducing explicit let-expressions to force
the evaluation order.  

-Greg



^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: Undefined evaluation order
@ 2000-10-12  9:53 Dave Berry
  0 siblings, 0 replies; 27+ messages in thread
From: Dave Berry @ 2000-10-12  9:53 UTC (permalink / raw)
  To: Greg Morrisett, caml-list

May I toss in a possible complication?   I'm thinking of numeric code, and
the possibilities of optimisation.  To take a simple example, (a * b * 0.0)
should always be zero.  Except that (a * b) could raise an exception or
return a NaN.  I imagine there exist more complex numeric optimisations that
a compiler may wish to perform.

So my question is whether numeric operations might be hampered by requiring
a defined evaluation order, even in the case that changing the order has a
visible (and desired!) effect.  I'm not a numeric programmer, and I know
there are some numeric programmers on the list, so perhaps they would care
to comment.

Perhaps an alternative would be to specify the evaluation order, but allow
the compiler to modify the evaluation order to reduce the possibilities of
NaN results or numeric exceptions.  It wouldn't be as elegant as a universal
rule, but might be more practical.

Dave.


-----Original Message-----
From: Greg Morrisett [mailto:jgm@cs.cornell.edu]
Sent: Wednesday, October 11, 2000 1:23 PM
To: 'Hendrik Tews'
Cc: caml-list@inria.fr
Subject: RE: Undefined evaluation order


> I would like to vote for leaving the evaluation order
> unspecified (implicitly repeating all suitable arguments from
> previous postings). The specification should only regulate the
> necessary things not more.

I don't see why.  As far as I can tell, the only reason
to not specify the order is for performance.  I've never
seen a systematic study that significant performance
gains are achievable across a range of applications.
Most compilers only do very local re-orderings, and
these can typically be achieved with local effects 
analysis (at least for languages like ML that are 
relatively effect free.)  

We've heard promises of expression-level parallelism 
since the dawn of Fortran and Lisp.  But for 40 years,
they speedups have yet to be realized because the granularity 
is always too small to do the necessary synchronization
for multi-processors, and the granularity is too large
for instruction-level parallelism (i.e., other hazards
manifest.)  If you truly believe that magic compilers
will someday come along and parallelize things, then
why are you worried that these compilers will be stopped
by a specified evaluation order?  

IMHO, there are compelling reasons to at least specify
an evaluation order, if not to standardize on left-to-
right.  In spite of the fact that programmer's *should*
realize that expressions could be evaluated in any order,
they tend to assume the order that the current compiler
uses.  Then when someone else ports the code, or the
compiler changes, things break.  

As I mentioned earlier, when teaching, it's nice for 
a language to be simple and uniform.  Explaining to
a student why:

	let x = input() in
	let y = input() in
	(x,y)

is not equivalent to:

	(input(), input())

is one more thing that confuses them -- especially when
we emphasize that the whole point of anonymous functions
is to avoid naming things that need not be named!

A standard trick for Scheme coders is, as someone suggested,
to randomize the order of evaluation in the hopes of
tripping across such bugs.  Ugh.  Maybe the type-checker
should just randomly type-check a few expressions too :-)

If you're going to have an unspecified order of evaluation,
then I think you realistically need an effects analysis
in order to warn the programmer that what they are writing
is dependent upon the order.  Unfortunately, either the
analysis would need to be global (to get rid of all the
false positives) or else you'd have to augment function 
types with effects information, add in polymorphic effects,
etc.  In other words, you're buying into a whole ball of wax.  
Neither option seems all that wonderful.  

-Greg



^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: Undefined evaluation order
@ 2000-10-11 12:22 Greg Morrisett
  2000-10-11 20:35 ` Pierre Weis
  0 siblings, 1 reply; 27+ messages in thread
From: Greg Morrisett @ 2000-10-11 12:22 UTC (permalink / raw)
  To: 'Hendrik Tews'; +Cc: caml-list

> I would like to vote for leaving the evaluation order
> unspecified (implicitly repeating all suitable arguments from
> previous postings). The specification should only regulate the
> necessary things not more.

I don't see why.  As far as I can tell, the only reason
to not specify the order is for performance.  I've never
seen a systematic study that significant performance
gains are achievable across a range of applications.
Most compilers only do very local re-orderings, and
these can typically be achieved with local effects 
analysis (at least for languages like ML that are 
relatively effect free.)  

We've heard promises of expression-level parallelism 
since the dawn of Fortran and Lisp.  But for 40 years,
they speedups have yet to be realized because the granularity 
is always too small to do the necessary synchronization
for multi-processors, and the granularity is too large
for instruction-level parallelism (i.e., other hazards
manifest.)  If you truly believe that magic compilers
will someday come along and parallelize things, then
why are you worried that these compilers will be stopped
by a specified evaluation order?  

IMHO, there are compelling reasons to at least specify
an evaluation order, if not to standardize on left-to-
right.  In spite of the fact that programmer's *should*
realize that expressions could be evaluated in any order,
they tend to assume the order that the current compiler
uses.  Then when someone else ports the code, or the
compiler changes, things break.  

As I mentioned earlier, when teaching, it's nice for 
a language to be simple and uniform.  Explaining to
a student why:

	let x = input() in
	let y = input() in
	(x,y)

is not equivalent to:

	(input(), input())

is one more thing that confuses them -- especially when
we emphasize that the whole point of anonymous functions
is to avoid naming things that need not be named!

A standard trick for Scheme coders is, as someone suggested,
to randomize the order of evaluation in the hopes of
tripping across such bugs.  Ugh.  Maybe the type-checker
should just randomly type-check a few expressions too :-)

If you're going to have an unspecified order of evaluation,
then I think you realistically need an effects analysis
in order to warn the programmer that what they are writing
is dependent upon the order.  Unfortunately, either the
analysis would need to be global (to get rid of all the
false positives) or else you'd have to augment function 
types with effects information, add in polymorphic effects,
etc.  In other words, you're buying into a whole ball of wax.  
Neither option seems all that wonderful.  

-Greg



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Re: Undefined evaluation order
@ 2000-10-10 19:23 David McClain
  0 siblings, 0 replies; 27+ messages in thread
From: David McClain @ 2000-10-10 19:23 UTC (permalink / raw)
  To: caml-list

I second this opinion overall... I cut my teeth with respect to this when
writing C back about 20 years ago. Each individual statement in a program
carries with it the (implicit) assumption of simultaneous evaluation, unless
care is taken to indicate otherwise (e.g., Lisp (LET ...) vs (LET* ...) ).
Hence depending on a particular order of evaluation is seemingly dangerous,
not to mention confusing when switching between many different languages as
I must do... (Lately, with a mix of OCaml, SmallTalk, Dylan, and Lisp I have
even been getting confused about operator precedence!).

I think it is probably wrong for too many assumptions to be made in the
design and use of a language. Lisp is stellar in this regard, simply because
only one assumption is made - first operand is a function all the rest are
args. When one must switch between languages, it is horribly confusing to
have to get back into the mindset of the crowd that fancies their particular
language as the one and only...

Just my 2c...

- DM

-----Original Message-----
From: Thorsten Ohl <ohl@hep.tu-darmstadt.de>
To: caml-list@inria.fr <caml-list@inria.fr>
Date: Tuesday, October 10, 2000 10:08 AM
Subject: Re: Undefined evaluation order


>Brian Rogoff <bpr@best.com> writes:
>
>> For OCaml it appears that the perspective adopted is that the
>> programmer must make the temporal dependencies explicit. [...] it is
>> mentioned that this usually leads to clearer programs.  I'm sure the
>> bytecode compiler argument is valid, but not the code clarity one
>
>Maybe I have ben brainwashed by too much Fortran, but depending on
>side effects in the evaluation of function arguments that change the
>result according to the evaluation order is not good style, IMHO.
>Explicit `let' bindings are clear and improve the likelihood that the
>author will still be able to understand his/her code a few year later
>significantly.
>
>I agree that leaving this important chunk of the semantics unspecified
>is not nice, but closing the door on parallelism forever would be much
>worse, IMHO.
>
>(Only half-joking) There should be an option in the compiler
>randomizing evaluation order for debugging ...
>--
>Thorsten Ohl, Physics Department, TU Darmstadt -- ohl@hep.tu-darmstadt.de
>http://heplix.ikp.physik.tu-darmstadt.de/~ohl/ [<=== PGP public key here]
>



^ permalink raw reply	[flat|nested] 27+ messages in thread
* RE: Undefined evaluation order
@ 2000-10-10 12:46 Greg Morrisett
  0 siblings, 0 replies; 27+ messages in thread
From: Greg Morrisett @ 2000-10-10 12:46 UTC (permalink / raw)
  To: caml-list

> In retrospect, perhaps we should have considered introducing "let"
> bindings automatically to preserve left-to-right semantics within the
> push-enter model (like Moscow ML does, I think), although this entails
> a performance hit for the bytecode interpreter.

Let me put in a vote for left-to-right ordering.  I've also
been bitten by the evaluation order (with almost exactly the
same kind of code -- reading a record's values from some file).
But more importantly, the primary reasons I chose SML over 
O'Caml for my class this semester is that the evaluation 
model of SML is more uniform.  Left-to-right in O'Caml might
well change my mind.  

On this note, I find the discussion of syntax very interesting.
Teaching either variant of ML to a group of students raised
on Visual Basic, Java, and Javascript is not easy, and today's
ML implementations are not very student-friendly when it comes
to either parse- or type-error messages...

-Greg



^ permalink raw reply	[flat|nested] 27+ messages in thread
* Undefined evaluation order
@ 2000-10-05 18:14 Brian Rogoff
  2000-10-06  2:02 ` Ken Wakita
                   ` (2 more replies)
  0 siblings, 3 replies; 27+ messages in thread
From: Brian Rogoff @ 2000-10-05 18:14 UTC (permalink / raw)
  To: caml-list

Hi,
    It is well known that OCaml has undefined evaluation orders and that
it uses right-to-left ordering. What is the rationale for that decision? 
I remember some discussion of this but I couldn't find it in the Caml list
archives. 

    Besides being surprising for lots of people, it is actually a little
ugly to have to write explicit let bindings to force the order and when
reading files which consist of long records; for instance I much prefer 

type date =
  { year : int
  ; month : int
  ; day : int
  ; hour : int
  ; minute : int
  ; second : int 
  }

let input_date igds =
  { year = input_word igds
  ; month = input_word igds
  ; day = input_word igds
  ; hour = input_word igds
  ; minute = input_word igds
  ; second = input_word igds
  }

to 

let input_date igds =
  let year = input_word igds in
  let month = input_word igds in
  let day = input_word igds in
  let hour = input_word igds in
  let minute = input_word igds in
  let second = input_word igds in
  {  year = year
   ; month = month
   ; day = day
   ; hour = hour
   ; minute = minute
   ; second = second
   }

or even with right-to-left where the order is exactly the opposite of the 
record definition (and of what most readers expect). 

-- Brian




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

end of thread, other threads:[~2000-10-21  7:51 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-10-10 18:55 Undefined evaluation order John R Harrison
  -- strict thread matches above, loose matches on Subject: below --
2000-10-20 14:59 Gerard Huet
2000-10-14  1:42 David McClain
2000-10-13 13:56 Dave Berry
2000-10-12 17:06 David McClain
2000-10-12 11:32 Greg Morrisett
2000-10-12  9:53 Dave Berry
2000-10-11 12:22 Greg Morrisett
2000-10-11 20:35 ` Pierre Weis
2000-10-13  7:05   ` Judicael Courant
2000-10-13 14:21     ` Markus Mottl
2000-10-16  8:38       ` Christophe Raffalli
2000-10-16 15:48         ` Brian Rogoff
2000-10-16 16:29           ` Christophe Raffalli
2000-10-17  9:19             ` Ralf Treinen
2000-10-10 19:23 David McClain
2000-10-10 12:46 Greg Morrisett
2000-10-05 18:14 Brian Rogoff
2000-10-06  2:02 ` Ken Wakita
2000-10-06 11:18   ` Pierpaolo BERNARDI
2000-10-07  6:46     ` Ken Wakita
2000-10-08 15:43 ` David Mentré
2000-10-08 22:47   ` Brian Rogoff
2000-10-10 12:47     ` Thorsten Ohl
2000-10-10 20:52       ` Brian Rogoff
2000-10-10 19:26     ` Stefan Monnier
2000-10-09 12:45 ` Xavier Leroy

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).