f



order of evaluation?

Given the expression (foo (bar 3) baz (bing 8)), what is the order
of evaluation? I can see some interpreters that will parse the tree
to the lowest element/atom, start puting the values on some stack,
and work backwards:

8 <-
-> bing
baz <-
3 <-
-> foo

I can also see this expression:

(if (= foo 1) (bar 3) (baz 4))

that is is more efficient to evalute the '(=', then evaluate the
'(if', and let the if evaluate the selected expression.

Which way is it done?

Mike
1
mikee (687)
9/30/2004 7:15:53 PM
comp.lang.scheme 4781 articles. 0 followers. Post Follow

390 Replies
1745 Views

Similar Articles

[PageSpeed] 14

Mike wrote:
> Given the expression (foo (bar 3) baz (bing 8)), what is the order
> of evaluation? I can see some interpreters that will parse the tree
> to the lowest element/atom, start puting the values on some stack,
> and work backwards:
>
> 8 <-
> -> bing
> baz <-
> 3 <-
> -> foo
>
> I can also see this expression:
>
> (if (= foo 1) (bar 3) (baz 4))
>
> that is is more efficient to evalute the '(=', then evaluate the
> '(if', and let the if evaluate the selected expression.
>
> Which way is it done?

There are a few related questions implicit above...

> (foo (bar 3) baz (bing 8))

Scheme calls ordinary functions using a call-by-value approach, in which all
a function's arguments are evaluated before a function is ever called, so if
foo is an ordinary function (as opposed to e.g. a macro), you know that (bar
3), baz, and (bing 8) will all be evaluated before foo is called.

However, the order in which these arguments are evaluated happens is not
specified in R5RS, and varies between Scheme implementations.  Some do it
left to right, some do it right to left, and other orders are possible.  A
parallel implementation of Scheme might even evaluate the arguments
concurrently.  This means that if you want to write Scheme code that's at
all portable, you should avoid depending on order of evalutation within
ordinary expressions.  If you need to specify an order of evaluation, you
should use an appropriate form such as LET* or BEGIN, which sequences its
contents.

> (if (= foo 1) (bar 3) (baz 4))
>
> that is is more efficient to evalute the '(=', then evaluate the
> '(if', and let the if evaluate the selected expression.

The IF construct in Scheme is not an ordinary function.  In a call-by-value
language like Scheme, using an ordinary function for IF would mean that both
its branches would have to be evaluated, even though the result of only one
is used.  Aside from performance issues, this could cause problems if the
unneeded branch has side effects.  To address this, IF is built-in syntax in
Scheme, and it works as you say: the condition is evaluated first, and then
either the consequent or the antecedent is evaluated, depending on the
result of the condition.

In general, if you need to define operations in Scheme which don't use call
by value, you can do it by defining a macro.  IF behaves like a macro,
although whether it's actually implemented as one depends on the Scheme
implementation.  (It's possible to implement IF as a macro in terms of COND,
or vice versa, but usually one or the other, or some other means of making a
choice, is needed at a primitive level.)

Anton


1
anton58 (1240)
9/30/2004 8:48:57 PM
In article <Zi_6d.5610$ls6.1752@newsread3.news.atl.earthlink.net>, Anton van Straaten wrote:
> Mike wrote:
>> Given the expression (foo (bar 3) baz (bing 8)), what is the order
>> of evaluation? I can see some interpreters that will parse the tree
>> to the lowest element/atom, start puting the values on some stack,
>> and work backwards:
>>
>> 8 <-
>> -> bing
>> baz <-
>> 3 <-
>> -> foo
>>
>> I can also see this expression:
>>
>> (if (= foo 1) (bar 3) (baz 4))
>>
>> that is is more efficient to evalute the '(=', then evaluate the
>> '(if', and let the if evaluate the selected expression.
>>
>> Which way is it done?
> 
> There are a few related questions implicit above...
> 
>> (foo (bar 3) baz (bing 8))
> 
> Scheme calls ordinary functions using a call-by-value approach, in which all
> a function's arguments are evaluated before a function is ever called, so if
> foo is an ordinary function (as opposed to e.g. a macro), you know that (bar
> 3), baz, and (bing 8) will all be evaluated before foo is called.
> 
> However, the order in which these arguments are evaluated happens is not
> specified in R5RS, and varies between Scheme implementations.  Some do it
> left to right, some do it right to left, and other orders are possible.  A
> parallel implementation of Scheme might even evaluate the arguments
> concurrently.  This means that if you want to write Scheme code that's at
> all portable, you should avoid depending on order of evalutation within
> ordinary expressions.  If you need to specify an order of evaluation, you
> should use an appropriate form such as LET* or BEGIN, which sequences its
> contents.
> 
>> (if (= foo 1) (bar 3) (baz 4))
>>
>> that is is more efficient to evalute the '(=', then evaluate the
>> '(if', and let the if evaluate the selected expression.
> 
> The IF construct in Scheme is not an ordinary function.  In a call-by-value
> language like Scheme, using an ordinary function for IF would mean that both
> its branches would have to be evaluated, even though the result of only one
> is used.  Aside from performance issues, this could cause problems if the
> unneeded branch has side effects.  To address this, IF is built-in syntax in
> Scheme, and it works as you say: the condition is evaluated first, and then
> either the consequent or the antecedent is evaluated, depending on the
> result of the condition.
> 
> In general, if you need to define operations in Scheme which don't use call
> by value, you can do it by defining a macro.  IF behaves like a macro,
> although whether it's actually implemented as one depends on the Scheme
> implementation.  (It's possible to implement IF as a macro in terms of COND,
> or vice versa, but usually one or the other, or some other means of making a
> choice, is needed at a primitive level.)
> 
> Anton
> 
> 

Wonderful explanation and just what I was asking for.

Mike
1
mikee (687)
9/30/2004 11:26:45 PM
Is there any utility to the order of evaluation being unspecified?  
Is it :
 a) that a fixed order would produce some unwanted theoretical effect?
 b) to discourage some programming methods?
 c) because the choice of the order of evaluation would be arbitrary?
 d) because no consensus have been reached regarding this issue?
 e) something else?

I'm no scheme expert, far from it, but I use it everyday, and I
wondered : is this ambiguity responsible for the only circumstances
where one can look at valid R5RS scheme code, and not be able to
predict the result of the evaluation ?

Thanks, M.P.
1
10/1/2004 10:40:01 PM
mathieu.paradis@logik3d.com (M. Paradis) writes:

> Is there any utility to the order of evaluation being unspecified?  
> Is it :
>  a) that a fixed order would produce some unwanted theoretical effect?
>  b) to discourage some programming methods?
>  c) because the choice of the order of evaluation would be arbitrary?
>  d) because no consensus have been reached regarding this issue?
>  e) something else?
> 
> I'm no scheme expert, far from it, but I use it everyday, and I
> wondered : is this ambiguity responsible for the only circumstances
> where one can look at valid R5RS scheme code, and not be able to
> predict the result of the evaluation ?

I think the point is that you are supposed to write code that does not
depend on any one order of evaluation, so your code will always
execute the same no matter what Scheme you're using. 

This is quite a common requirement in high level languages, or at
least it used to be. Others that follow this are:

C, BCPL, Ada and Pascal I seem to remember

Maybe this is Algol's fault.


AFAIK the reason for this is that it frees compiler implementors to
pursue different compilation strategys. For example, with Scheme it
can be quite efficient to evaluate function call arguments from right
to left (ie: backwards to the way westerners read code).

Having said that, IMHO the time for such efficiencies is past and
Scheme should be speced as evaling from left to right.

One of the practical things that makes Java popular is that the order
of eval is speced left to right. It does make it simpler for the
programmer.


-- 
Nic Ferrier
http://www.tapsellferrier.co.uk
1
nferrier (66)
10/1/2004 11:06:41 PM
M. Paradis wrote:
> Is there any utility to the order of evaluation being unspecified?  
> Is it :
>  a) that a fixed order would produce some unwanted theoretical effect?
>  b) to discourage some programming methods?
>  c) because the choice of the order of evaluation would be arbitrary?
>  d) because no consensus have been reached regarding this issue?
>  e) something else?

I think it's mostly (d), because there were right-to-left
and left-to-right schemes when that spec was first written,
and still are.  But it stays in the standard too, because

f) by choosing an arbitrary order of evaluation, a compiler
can often find optimizations that cut as much as 10% off the
time required to evaluate an expression.

				Bear

1
bear (1219)
10/1/2004 11:53:13 PM
Ray Dillinger wrote:

{stuff deleted}

still are.  But it stays in the standard too, because
> 
> f) by choosing an arbitrary order of evaluation, a compiler
> can often find optimizations that cut as much as 10% off the
> time required to evaluate an expression.

Citation? I strongly suspect this really is no longer the case on modern 
out-of order RISC machines with lots of registers.


1
danwang74 (207)
10/2/2004 12:40:15 AM
Daniel C. Wang wrote:
> Ray Dillinger wrote:
> 
> {stuff deleted}
> 
> still are.  But it stays in the standard too, because
> 
>>
>> f) by choosing an arbitrary order of evaluation, a compiler
>> can often find optimizations that cut as much as 10% off the
>> time required to evaluate an expression.
> 
> 
> Citation? I strongly suspect this really is no longer the case on modern 
> out-of order RISC machines with lots of registers.
> 
> 
Ack, I sense a repeated flame fest beginning.  Please read the thread 
starting at:

http://groups.google.com/groups?selm=br0fjn%245bl%245%40hood.uits.indiana.edu

.... before beginning.

	Scott
1
scgmille (240)
10/2/2004 3:04:25 AM
* Nic Ferrier (nferrier@tapsellferrier.co.uk)
....
[Argument evaluation order]
> 
> This is quite a common requirement in high level languages, or at
> least it used to be. Others that follow this are:
> 
> C, BCPL, Ada and Pascal I seem to remember
> 
Actually C does not even require the arguments to be evaluated
one at a time. In (the C equivalent of)

  (e (d (a)) (c (b)))

the functions may be invoked in alphabetical order. Is that
allowed in Scheme, too?

Andreas

-- 
np: 4'33
1
yyx-nospam (22)
10/2/2004 8:24:55 AM
mathieu.paradis@logik3d.com (M. Paradis) writes:

> Is there any utility to the order of evaluation being unspecified?  
> Is it :
>  a) that a fixed order would produce some unwanted theoretical effect?

Depends on what you want.  (The answer is "yes" if, e.g., you don't
like unambiguous semantics.)

In any case, as I have said many times before: Every program that is
legal and correct under unspecified evaluation order is obviously
legal and correct under a specified order.  The opposite is not true,
and it is difficult to establish trough testing which programs are the
ones that make up the difference.  (That's because most
implementations actually do implement some fixed order, so it is
difficult to test other legal schedules which your compiler happens to
not use.)

>  b) to discourage some programming methods?

Supposedly, according to some.  I don't believe it one second, though.
(I'm NOT going to again about this again!  Bradd, did you hear me?)

>  c) because the choice of the order of evaluation would be arbitrary?

Many other things are "arbitrary", too.

>  d) because no consensus have been reached regarding this issue?

That's definitely a large part of the story.

>  e) something else?

Some compilers can squeeze out some extra performance from some
programs.

> I'm no scheme expert, far from it, but I use it everyday, and I
> wondered : is this ambiguity responsible for the only circumstances
> where one can look at valid R5RS scheme code, and not be able to
> predict the result of the evaluation ?

Note quite, but arguably it is the most serious reason.

Matthias
1
find19 (1244)
10/4/2004 2:58:42 PM
Matthias Blume <find@my.address.elsewhere> writes:

> (I'm NOT going to again about this again!  Bradd, did you hear me?)
                   s/again/argue/
1
find19 (1244)
10/4/2004 3:00:57 PM
In article <m1brfi4jj1.fsf@tti5.uchicago.edu>,
Matthias Blume  <find@my.address.elsewhere> wrote:
>(That's because most
>implementations actually do implement some fixed order, so it is
>difficult to test other legal schedules which your compiler happens to
>not use.)

The Gambit compiler processes function arguments in reverse order.  This has
the effect of causing each build of the system from the Scheme source to
reverse the order arguments are processed in the interpreter---first
left-to-right, then right-to-left, etc.

I did use this once to find some places where I should have used a let*
instead of a let.  (The let looked something like:

(let ((a (read ...))
      (b (read ...))
      (c (read ...)))
  (     )

so you can see what the problem was.)

Brad







1
bjl (76)
10/4/2004 4:02:38 PM
M. Paradis wrote:
> Is there any utility to the order of evaluation being unspecified?
> Is it :
>  a) that a fixed order would produce some unwanted theoretical effect?
>  b) to discourage some programming methods?
>  c) because the choice of the order of evaluation would be arbitrary?
>  d) because no consensus have been reached regarding this issue?
>  e) something else?

The above omits (f), which is "some combination of all of the above,
depending on the observer's perspective".

However, there's only one underlying reason to leave evaluation order
unspecified: it allows the distinction between code which depends on
evaluation order, and code which is not intended to depend on a specific
evaluation order, to be expressed in a language.

Being able to express this distinction has at least two broad consequences:
it allows tools like compilers to treat the two types of code differently;
and it communicates information to human readers of the code.

Fixing evaluation order, without otherwise changing the language, removes
the ability to express this distinction, resulting in a less expressive
language.

One confusing point which tends to feed the occasional flamewars on this
topic is that the type of expressivity in question doesn't affect the
behavior of the program with respect to its "primary" specification -- the
program's behavior doesn't change due to fixing evaluation order (unless
possible performance changes are considered significant).

Matthias Blume expressed this by saying "every program that is legal and
correct under unspecified evaluation order is obviously legal and correct
under a specified order."  However, "legal and correct" are not the only
requirements that real-world programs have.  There are plenty of legal and
correct but entirely obfuscated programs, for example.  There is no strictly
semantic argument you can make against such programs, yet they are not
considered desirable or even acceptable in real-world environments.
Real-world programs have to be maintained, often by a changing group of
people over time, and in such environments, the ability of a language to
express more information is usually advantageous.

In programs which are written in a largely functional style, the majority of
a program may not depend on an order of evaluation, and in those pieces that
do, it can be important to be aware of that.  Having a language treat all
code as though it depends on a specific order of evaluation can thus remove
a large amount of information from a program, information which can be
useful when maintaining code.

As so often happens in programming languages, available languages offer us
two extremes in this area, neither of which is an ideal solution.  On the
one hand, unspecified evaluation order creates theoretically ambiguous
semantics, and in general is a rather unsatisfactory way of asserting a
property of programs.  On the other hand, languages with fixed evaluation
order deal with this unsatisfactoriness in a naive King Solomon-like way, by
simply removing a certain kind of expressivity from the language.

(Wise King Solomon threatened to cut a disputed baby in half, to determine
who the real mother was.  Naive King Solomon would actually cut the baby in
half.  In this case, perhaps it's really just a matter of a few fingers and
toes.)

In an ideal world, with ideal programmers, we could perhaps all just use a
language with fixed evaluation order, but agree to only depend on that order
in certain constructs such as (in Scheme) LET*, BEGIN, etc., and perhaps a
few more to satisfy some of the other reasonable requirements for
order-dependence.  But in practice, being able to rely on fixed evaluation
order anywhere in a program means that at least some people will do just
that.  This has a severe negative impact on the ability to use such a
convention to encode information.  The bogeyman of unpredictable results,
a.k.a. ambiguous semantics, is just the easiest way, under the
circumstances, to "enforce" the convention, even though violations may only
be detected and reported in one of the most capricious ways imaginable, e.g.
with unpredictable results which usually occur only when switching
compilers.

> I'm no scheme expert, far from it, but I use it everyday, and I
> wondered : is this ambiguity responsible for the only circumstances
> where one can look at valid R5RS scheme code, and not be able to
> predict the result of the evaluation ?

Code for which evaluation has unpredictable results is only "valid" if its
specification says that the results of evaluation should be unpredictable.
Since this kind of unpredictability is not usually part of a program's
specification, what the above quote really says is that there are some buggy
programs which R5RS doesn't consider invalid.  However, the same is true for
many other kinds of program bugs.

Anton


1
anton58 (1240)
10/4/2004 6:43:00 PM
Anton van Straaten wrote:

[...bunch o' stuff...]

Everything Anton van Straaten said that might be interpreted as a 
defense of leaving the order of evaluation of function arguments 
unspecified has been addressed (and in my not-so-objective opinion, 
thoroughly refuted) in a previous thread already referenced.

-thant

1
thant (332)
10/4/2004 8:21:37 PM
Thant Tessman <thant@acm.org> wrote:
> Anton van Straaten wrote:
>
> [...bunch o' stuff...]
>
> Everything Anton van Straaten said that might be interpreted as a
> defense of leaving the order of evaluation of function arguments
> unspecified has been addressed (and in my not-so-objective opinion,
> thoroughly refuted) in a previous thread already referenced.

"Refuted" is an unsupportable claim in this context, at least by any
evidence provided thus far.  In the end, in the absence of a solution which
addresses all concerns satisfactorily, it comes down to subjective
perspectives and priorities.  In the prior thread, such perspectives were
expressed by statements such as your own:

"I just don't believe for a moment that being able to rearrange argument
evaluation is anywhere near as
important to someone maintaining code than knowing that the order of
evaluation is fixed."

I assume you recognize that such statements of belief don't qualify as
refutations.  If you'd like to point out any actual refutations, as opposed
to subjective opinions, please do so.  Failing that, it must be acknowledged
that there are in fact valid arguments on both sides of this issue, no
matter how much you may not like some of them, and no matter what weights
you might personally assign to some of them.

Anton


1
anton58 (1240)
10/4/2004 8:53:43 PM
bjl@cs.purdue.edu (Bradley J Lucier) writes:

> In article <m1brfi4jj1.fsf@tti5.uchicago.edu>,
> Matthias Blume  <find@my.address.elsewhere> wrote:
> >(That's because most
> >implementations actually do implement some fixed order, so it is
> >difficult to test other legal schedules which your compiler happens to
> >not use.)
> 
> The Gambit compiler processes function arguments in reverse order.  This has
> the effect of causing each build of the system from the Scheme source to
> reverse the order arguments are processed in the interpreter---first
> left-to-right, then right-to-left, etc.
> 
> I did use this once to find some places where I should have used a let*
> instead of a let.  (The let looked something like:
> 
> (let ((a (read ...))
>       (b (read ...))
>       (c (read ...)))
>   (     )
> 
> so you can see what the problem was.)

Yes.  I guess I should have said "a small number of fixed orders".

Also, there are systems (and if there aren't they would be relatively
easy to produce) that arrange for exhaustively searching through all
possible schedules.  I doubt that an exhaustive search would be very
practical.  Of course, most actual problems can probably be discovered
with just a few (e.g., 2) schedules -- if those schedules differ in
the right place.

Matthias
1
find19 (1244)
10/4/2004 10:24:14 PM
FWIW, here's my take on this.

IMHO:

1) One of the central principles of good programming language design is 
the principle of least surprise.

2) Most people are surprised when a single program in an ostensibly 
deterministic language with no external interactions behaves in two 
different ways on two different occasions.

3) Leaving order of evaluation unspecified in a language that also has 
side effects makes such an occurrence all but inevitable.

Therefore, unspecified order of evaluation by default is a poor design 
choice.  A better choice would be to introduce language syntax that 
allows a programmer to specify that order of evaluation doesn't matter, 
e.g.:

(with-arguments-evaluated-in-any-order . forms)

or

(call-with-arguments-evaluated-in-any-order thunk . argforms)

which could, of course, have suitable abbreviations.

Also, even if OoE were specified, nothing would prevent the compiler 
from rearranging the OoE (or parallelizing it) in situations where it 
could prove that the resulting semantics are equivalent to the specified 
fixed OoE, which would be the case for all programs written in a purely 
functional style.  (As a consequence of this one might confidently 
predict that with-arguments-evaluated-in-any-order, if it existed, would 
seldom be used.)

rg
1
rNOSPAMon (1927)
10/4/2004 10:36:35 PM
Anton van Straaten wrote:

> [...]  If you'd like to point out any actual refutations, as opposed
> to subjective opinions, please do so.  [...]

The statement in your post that goaded me into referencing the previous 
thread was this one:

"In programs which are written in a largely functional style, the 
majority of
a program may not depend on an order of evaluation, and in those pieces that
do, it can be important to be aware of that.  Having a language treat all
code as though it depends on a specific order of evaluation can thus remove
a large amount of information from a program, information which can be
useful when maintaining code."

There is no "information" being conveyed by the fact that 
function-argument order-of-evaluation is unspecified. There are only 
assumptions on the part of compilers and maintainers that may or may not 
be valid. Maybe the code writer was trying to convey their intention 
that order of evaluation was deliberately unspecified, or maybe they 
didn't care. Maybe they did care but the code is buggy and has 
order-of-evaluation dependency bugs anyway. If you want OofE to be 
irrelevant, use a language in which functional style is enforced. If you 
want to mix functional and imperative styles, use a language in which 
the functional sections can be demarked by way of a type system. If you 
want to deliberately specify that OofE is unspecified, as one might in 
the case of a threading mechanism of some sort, introduce an explicit 
construct for that.  Beyond that, this claim that information useful 
when maintaining code is somehow lost when order of evaluation is 
specified is total nonsense. It was never really there to begin with--at 
least not in any sense that isn't outdone by a simple comment.

-thant

1
thant (332)
10/4/2004 10:38:08 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> Therefore, unspecified order of evaluation by default is a poor
> design choice. A better choice would be to introduce language syntax
> that allows a programmer to specify that order of evaluation doesn't
> matter,

The problem is that almost nobody would use it if it would be longer
than the default.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
1
qrczak (1266)
10/4/2004 11:21:22 PM
Marcin 'Qrczak' Kowalczyk wrote:
> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> 
>>Therefore, unspecified order of evaluation by default is a poor
>>design choice. A better choice would be to introduce language syntax
>>that allows a programmer to specify that order of evaluation doesn't
>>matter,
> 
> 
> The problem is that almost nobody would use it if it would be longer
> than the default.

Which should be a pretty big clue about how important it really is in 
practice.

-thant

0
thant (332)
10/4/2004 11:24:27 PM
In article <rNOSPAMon-2F811C.15363504102004@nntp1.jpl.nasa.gov>,
Ron Garret  <rNOSPAMon@flownet.com> wrote:
>1) One of the central principles of good programming language design is 
>the principle of least surprise.

In my experience, the "principle of least surprise" almost always means
"I personally was surprised that such and such happened, so it shouldn't have
happened."  Which immediately raises the question, was it reasonable for that
person to be surprised?  So I usually find this "principle" to be of no use
at all.

Brad
0
bjl (76)
10/4/2004 11:37:58 PM
Bradley J Lucier wrote:
> In article <rNOSPAMon-2F811C.15363504102004@nntp1.jpl.nasa.gov>,
> Ron Garret  <rNOSPAMon@flownet.com> wrote:
> 
>>1) One of the central principles of good programming language design is 
>>the principle of least surprise.
> 
> 
> In my experience, the "principle of least surprise" almost always means
> "I personally was surprised that such and such happened, so it shouldn't have
> happened."  Which immediately raises the question, was it reasonable for that
> person to be surprised?  So I usually find this "principle" to be of no use
> at all.

Imposing order of evaluation cannot surprise someone not expecting it. 
So in this case the argument is asymmetrical.

-thant

0
thant (332)
10/5/2004 12:02:47 AM
Thant Tessman <thant@acm.org> wrote:

> There is no "information" being conveyed by the fact that
> function-argument order-of-evaluation is unspecified.

Of course there is.  The information exists by definition, in that there are
some parts of the code for which order of evaluation is unspecified, and
other parts for which it is specified, with the distinction in semantics
indicated by syntax.  What allows you to distinguish those two types of code
merely by syntactic inspection, is the information present in the program -
information that is lost from every program if you eliminate that
distinction in the language.

Removing this information for every function call and other non-sequencing
expression in a program "can thus remove a large amount of information from
a program," to quote my original statement.  So you were incorrect in being
goaded to a response by my statement.  ;)

Of course, I think what you're really getting at is whether that information
is useful.  You're also attempting to deprecate its usefulness to the point
where eliminating it is no loss, in other words, arguing about whether the
information "can be useful when maintaining code," as I claimed.  That, as
I've said, is subjective, in the sense that some people consider it useful,
and others deny that usefulness, and in order to do either, you have to
assign subjective values to the issues under consideration.

> Beyond that, this claim that information *useful* when
> maintaining code is somehow lost when order of evaluation
> is specified is total nonsense.

I emphasized your "useful" above, just to underscore what I wrote above.
Now all I have to do is refute your claim of "total nonsense".

> There are only assumptions on the part of compilers and
> maintainers that may or may not be valid. Maybe the code
> writer was trying to convey their intention that order of
> evaluation was deliberately unspecified, or maybe they
> didn't care. Maybe they did care but the code is buggy
> and has order-of-evaluation dependency bugs anyway.

Many of these "maybes" can be clarified with reference to the context in
which the code is being examined.  Given that context, information about
code having unspecified evaluation order can become useful.  For example,
what tests have been run against the program?  If you're modifying some
code, and have reason to believe that it's been well-tested for eval order
issues, then there are many safe rearrangements of terms which can be
performed in parts of the code with unspecified eval order.  That
possibility alone refutes the "total nonsense" claim, and now we're back to
subjective values.

Note that given the ability to express the distinction between specified and
unspecified order, it becomes possible to test for eval order issues, e.g.
by running test suites under different eval orders.  This demonstrates both
that the presence of the distinction adds information to a program, and also
demonstrates a concrete potential benefit - since it's not possible to test
fixed-eval-order code for unintended eval order dependencies.  Although a
fixed-eval-order language cannot express the two distinct types of code, the
distinction nevertheless exists, and code with unintended eval order
dependencies can affect programs in such languages.

Context is a key issue here.  The strongest versions of your claims rely on
a context-free scenario, in which no testing for eval order issues has been
or will be performed, and in which no other outside knowledge is available -
for example, if a bug is being investigated, was the code recently modified?
How well was the program working previously?  Was a new compiler used?  Were
terms in some expression recently rearranged?  Or, have you just noticed an
order dependency in a piece of code with unspecified evaluation order?

It's easy to simplify this issue out of existence if you restrict your focus
sufficiently, but all that means is that the restricted world you create has
the properties you created it to have, it says nothing about the broader
world beyond that.

> If you want to mix functional and imperative styles, use a
> language in which the functional sections can be demarked
> by way of a type system.

This at least acknowledges the underlying issue, and goes so far as to
allocate an entire class of programming languages to address it.  That's
most generous, but would you mind enumerating some of the languages in this
class?  In any case, Scheme is a language in which mixing functional and
imperative styles is accepted practice, and its type system isn't up to the
task you've set it.  There are also non-pure functional languages with rich
type systems, like OCaml, which don't fix evaluation order in their language
specification.  (Presumably, you consider this a mistake on the part of the
language designers.)

What this should all tell you is that this is not a settled issue, no matter
how much you would like it to be.  You'll notice that my original post
didn't argue that the current situation in Scheme (and C, C++, OCaml etc.)
is perfect - far from it, I used strong language against it: "ambiguous
semantics", "unsatisfactory", "capricious".  You seem to be arguing for
perfect solutions, which is admirable, and I'm all for that, but I was
answering the OP's question of whether there is "any utility to the order of
evaluation being unspecified" in Scheme.  The Scheme standard doesn't
currently specify an evaluation order, and in this context, effectively
saying "if you want to do that, use some other language" is part of an
entirely different discussion.

> [The information] was never really there to begin with--at
> least not in any sense that isn't outdone by a simple comment.

Again, you're implicitly acknowledging the presence of the information in
question, while at the same time attempting to brush it under the rug.  It
certainly makes no sense to provide comments for every occurrence of eval
order independence - any normal program, even an imperative one, would be
dominated by such comments.  It would make more sense to comment areas where
eval order is depended on.  But there's no need to do this within sequencing
constructs like LET* and BEGIN.  So are you suggesting the "simple comments"
be placed outside sequencing constructs, wherever eval order is depended on?
I addressed that in my original post: "in practice, being able to rely on
fixed evaluation
order anywhere in a program means that at least some people will do just
that.  This has a severe negative impact on the ability to use such a
convention to encode information."

Anton


0
anton58 (1240)
10/5/2004 4:47:07 AM
Ron Garret <rNOSPAMon@flownet.com> wrote:
>
> FWIW, here's my take on this.
>
> IMHO:
>
> 1) One of the central principles of good programming language design is
> the principle of least surprise.

Although it's often touted in informal contexts, that's a controversial
principle, mainly because it's too vague.  You certainly won't find it in
many semantics texts!

> 2) Most people are surprised when a single program in an ostensibly
> deterministic language with no external interactions behaves in two
> different ways on two different occasions.

If that's not the expected behavior, then you're describing a buggy program.
That's nothing to do with principle of least surprise - bugs happen, they
get reported, and fixed.

> 3) Leaving order of evaluation unspecified in a language that also has
> side effects makes such an occurrence all but inevitable.

Having side effects at all makes an entire class of otherwise avoidable bugs
inevitable, yet we still tolerate them for some reason, even in languages
like SML/NJ.

> Therefore, unspecified order of evaluation by default is a poor design
> choice.

I think the premises need work before a "therefore" can be inserted.  ;)

> A better choice would be to introduce language syntax that
> allows a programmer to specify that order of evaluation doesn't matter,
> e.g.:
>
> (with-arguments-evaluated-in-any-order . forms)
>
> or
>
> (call-with-arguments-evaluated-in-any-order thunk . argforms)
>
> which could, of course, have suitable abbreviations.

Syntax like that would dominate any normal program, even an imperative one.
Even in traditional imperative languages, most function call argument lists
and most expressions don't depend on order of evaluation.  The software
world would be in far worse shape if that weren't the case.

It would be better to switch the default around, and provide forms to
support sequencing, when required.  Which, of course, is the situation in
Scheme.

> Also, even if OoE were specified, nothing would prevent the compiler
> from rearranging the OoE (or parallelizing it) in situations where it
> could prove that the resulting semantics are equivalent to the specified
> fixed OoE, which would be the case for all programs written in a purely
> functional style.  (As a consequence of this one might confidently
> predict that with-arguments-evaluated-in-any-order, if it existed, would
> seldom be used.)

That might be true if the only beneficiary of OoE information was the
compiler.  However, humans have to work with code too, and in fact their
needs are usually considered paramount.  If your smart compiler were to
annotate the source code, or highlight it in an IDE, to allow the two to be
distinguished reliably without any human effort, that would be a step
forward.  But in general, it's difficult to do that, across e.g. module
boundaries, especially in a latently-typed language like Scheme.

In any case, none of these speculative possibilities addresses the question
asked by the OP, "Is there any utility to the order of evaluation being
unspecified?"  My response to that was that the answer is yes, there is
utility in it, although opinions differ as to exactly how much.  The
responses I've received so far merely underscore my answer.  :)

Anton


0
anton58 (1240)
10/5/2004 4:51:06 AM
"Anton van Straaten" <anton@appsolutions.com> writes:

> [ ... ] it's not possible to test
> fixed-eval-order code for unintended eval order dependencies.

False.  You can run all the same tests.  Maybe you find that they fail
more often because, as you say yourself, people might actually take
advantage of the language guarantees.  But to say that you can't run
the tests is nonsense.  And if your convention is to encode the
information using certain coding conventions (as questionable a
practice as this may be), then those tests will point out where the
conventions were violated.

> I addressed that in my original post: "in practice, being able to
> rely on fixed evaluation order anywhere in a program means that at
> least some people will do just that.  This has a severe negative
> impact on the ability to use such a convention to encode
> information."

And that's a good thing.  It is an extremely clumsy and brittle way of
encoding this type of information.  I can't believe anyone can
possibly defend it and keep a straight face.

Matthias
0
find19 (1244)
10/5/2004 5:27:21 AM
"Anton van Straaten" <anton@appsolutions.com> writes:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> >
> > FWIW, here's my take on this.
> >
> > IMHO:
> >
> > 1) One of the central principles of good programming language design is
> > the principle of least surprise.
> 
> Although it's often touted in informal contexts, that's a controversial
> principle, mainly because it's too vague.  You certainly won't find it in
> many semantics texts!

.... because that's not the appropriate place for it.  A text on
language design would be more like it.

> > 2) Most people are surprised when a single program in an ostensibly
> > deterministic language with no external interactions behaves in two
> > different ways on two different occasions.
> 
> If that's not the expected behavior, then you're describing a buggy program.
> That's nothing to do with principle of least surprise - bugs happen, they
> get reported, and fixed.

We are arguing about different language semantics.  The program is
buggy only with respect to one such semantics, with respect to another
it might be correct.  And that was Ron's point.

It's like a winding mountain road without a guard rail.  You basically
say that falling down the cliff is the motorists fault because he
should have driven more slowly and more carefully, fully knowing the
danger.  And strictly speaking you are right -- but your answer is
completely besides the point if the question was whether it would have
been better to have a guard rail in place.

> > 3) Leaving order of evaluation unspecified in a language that also has
> > side effects makes such an occurrence all but inevitable.
> 
> Having side effects at all makes an entire class of otherwise avoidable bugs
> inevitable, yet we still tolerate them for some reason, even in languages
> like SML/NJ.

So just because we tolerate one source of bugs we are now required to
tolerate many others as well?  The difference is that imperative
language features unquestionably have their utility, while not fixing
the evaluation order does not.

> > Therefore, unspecified order of evaluation by default is a poor design
> > choice.
> 
> I think the premises need work before a "therefore" can be inserted.  ;)

Let me try again:

    Unspecified order of evaluation by default is a poor design choice.

Better?

> Syntax like that would dominate any normal program, even an imperative one.
> Even in traditional imperative languages, most function call argument lists
> and most expressions don't depend on order of evaluation.  The software
> world would be in far worse shape if that weren't the case.

Moreover, for most of these function argument lists it is completely
*obvious* even to unsophisticated compilers that this is the case.
Function arguments tend to be simple: literals, variables, simple
arithmetic expressions, etc.  Only when they are not we might have
some problems.  Those cases are rare (in my experience).

> That might be true if the only beneficiary of OoE information was the
> compiler.  However, humans have to work with code too, and in fact their
> needs are usually considered paramount.  If your smart compiler were to
> annotate the source code, or highlight it in an IDE, to allow the two to be
> distinguished reliably without any human effort, that would be a step
> forward.  But in general, it's difficult to do that, across e.g. module
> boundaries, especially in a latently-typed language like Scheme.

Again, in the common case I expect there to be absolutely no problem.
What's obvious to the compiler (in the above sense) is also obvious to
the programmer.

In general, you are *way* overstating the problem.  I can't remember a
single time when I asked myself "gee, I wonder which parts of this
argument list can be legally reordered without changing the semantics"
where the answer was so difficult that I needed help from a tool, or
worse, couldn't figure it out at all.

In the unlikely case that I can't get the answer easily, I would be
extremely nervous about the code being correct to begin with.  And
this feeling would be even worse if evaluation order was not specified
by the language -- simply because then there are so many more ways in
which a complicated piece of code could go wrong.

In other words, I would not trust the programmer just because she
chose to use a function call rather than a LET*.  That could have been
just a mistake. The only thing to calm me down in such a situation
would be a detailed comment with a proof sketch of why the code is
correct (or, if not a proof, then *explicit* reassurance that the
programmer was confident about this being correct).

> In any case, none of these speculative possibilities addresses the question
> asked by the OP, "Is there any utility to the order of evaluation being
> unspecified?"  My response to that was that the answer is yes, there is
> utility in it, although opinions differ as to exactly how much.

It (the utility) is pretty much indistinguishable from zero.  To
understand why I think so, see above.

(The cost, however, is definitely not zero.)

Matthias
0
find19 (1244)
10/5/2004 6:00:02 AM
Thant Tessman wrote:

> Imposing order of evaluation cannot surprise someone not expecting it.
> So in this case the argument is asymmetrical.

Not when writing code, that is true.  Your suprise may vary when  
reading someone else's code.  And you may be constantly and unpleasantly 
surprised when refactoring such code.  

Ron Garrett wrote:

> Therefore, unspecified order of evaluation by default is a poor design 
> choice.  A better choice would be to introduce language syntax that 
> allows a programmer to specify that order of evaluation doesn't matter, 
> e.g.:
>
> (with-arguments-evaluated-in-any-order . forms)

.... except that this imposes an extra syntactic burden for the most common
case where order really does not matter, whereas the current status quo 
reserves that burden, via let*, etc., for the more uncommon case.

A.
0
andre9567 (120)
10/5/2004 1:19:46 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> FWIW, here's my take on this.
>
> IMHO:
>
> 1) One of the central principles of good programming language design
>    is the principle of least surprise.

Let's take this as an axiom.

> 2) Most people are surprised when a single program in an ostensibly
>    deterministic language with no external interactions behaves in
>    two different ways on two different occasions.

Ok.

> 3) Leaving order of evaluation unspecified in a language that also has 
>     side effects makes such an occurrence all but inevitable.

Ok.

> Therefore, unspecified order of evaluation by default is a poor design 
> choice.  

Whoops!  You left off an antecedent:

  4) Specifying the order of evaluation will reduce the surprise.   

Unfortunately, that isn't always true.  It is possible to have
order-of-evaluation bugs in languages that specify a deterministic
order of evaluation.  Surprising, no?

So specifying the order of evaluation 
  a) doesn't fix the problem
  b) leads to more surprises


> Therefore, unspecified order of evaluation by default is a poor design 
> choice.  

I agree, but I argue that specifying the order of evaluation by
default is *also* a poor design choice, and is no better than leaving
it unspecified.
0
jrm (1310)
10/5/2004 2:10:37 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

>   4) Specifying the order of evaluation will reduce the surprise.   
> 
> Unfortunately, that isn't always true.  It is possible to have
> order-of-evaluation bugs in languages that specify a deterministic
> order of evaluation.  Surprising, no?

Could you give an example?

> So specifying the order of evaluation 
>   a) doesn't fix the problem
>   b) leads to more surprises


Claim b) is obviously false because all surprise-free programs under
unspecified order are also surprise-free under specified order.

> > Therefore, unspecified order of evaluation by default is a poor design 
> > choice.  
> 
> I agree, but I argue that specifying the order of evaluation by
> default is *also* a poor design choice, and is no better than leaving
> it unspecified.

<scratching head>       
Hmm.  Sounds like Zen to me.  The opposite of a great thruth is also a
thruth...
</scratching head>
0
find19 (1244)
10/5/2004 2:23:58 PM
Matthias Blume <find@my.address.elsewhere> writes:

> <scratching head>       
> Hmm.  Sounds like Zen to me.  The opposite of a great thruth is also a
> thruth...
> </scratching head>

Ith works bethther witouth te authomathic TH-reflex... :-)

   s/thruth/truth/g
0
find19 (1244)
10/5/2004 2:26:00 PM
In article <_Kp8d.3634$Vm1.2292@newsread3.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> >
> > FWIW, here's my take on this.
> >
> > IMHO:
> >
> > 1) One of the central principles of good programming language design is
> > the principle of least surprise.
> 
> Although it's often touted in informal contexts, that's a controversial
> principle, mainly because it's too vague.  You certainly won't find it in
> many semantics texts!

I won't find it many physics texts either.  And your point would be...?

> > 2) Most people are surprised when a single program in an ostensibly
> > deterministic language with no external interactions behaves in two
> > different ways on two different occasions.
> 
> If that's not the expected behavior, then you're describing a buggy program.
> That's nothing to do with principle of least surprise - bugs happen, they
> get reported, and fixed.

Do they?  How can I tell if I have a Scheme program whose semantics 
depend on OoE?  If I have a Scheme program which accepts no input from 
the outside and has worked correctly on 99 runs, how can I be sure it 
will work correctly on the 100th run?

> > 3) Leaving order of evaluation unspecified in a language that also has
> > side effects makes such an occurrence all but inevitable.
> 
> Having side effects at all makes an entire class of otherwise avoidable bugs
> inevitable, yet we still tolerate them for some reason, even in languages
> like SML/NJ.

We tolerate side effects because they are useful.  The whole point of 
having high level programming languages at all is to create a better 
"impedance match" between the kinds of information that computers 
process and the kinds of information human brains process.  If we could 
rely on programmers to follow conventions, recognize errors, RTFM, etc. 
there would be no utility to high level languages at all.  But they 
don't, so there is.  And for some reason, most people find it easier to 
think in terms of side effects when they sit down to solve certain 
classes of problems.  That's just the way that the human brain seems to 
be wired.

[Off-topic rant: I have mostly stayed out of the Bill Richter wars, 
except to celebrate his temporary departure and quietly lament his 
return.  The main reason I find everything Bill writes to be utterly 
irrelevant is that I reject his central tacit premise, that mathematics 
has value above all else in CS.  It doesn't.  The study of programming 
languages has as much to do with psychology, economics, and politics as 
it does with math, a fact that lamentably few of its practitioners seem 
to recognize.]

> > Therefore, unspecified order of evaluation by default is a poor design
> > choice.
> 
> I think the premises need work before a "therefore" can be inserted.  ;)
> 
> > A better choice would be to introduce language syntax that
> > allows a programmer to specify that order of evaluation doesn't matter,
> > e.g.:
> >
> > (with-arguments-evaluated-in-any-order . forms)
> >
> > or
> >
> > (call-with-arguments-evaluated-in-any-order thunk . argforms)
> >
> > which could, of course, have suitable abbreviations.
> 
> Syntax like that would dominate any normal program, even an imperative one.

I doubt that very much.

> Even in traditional imperative languages, most function call argument lists
> and most expressions don't depend on order of evaluation.  The software
> world would be in far worse shape if that weren't the case.

It is true that most expressions etc. don't depend on OoE, but that is 
simply a mathematical fact, and so it is nonsensical to speculate what 
the consequences would be if it weren't true.  What we are talking about 
is how to treat those cases where it *does* (or might) matter.

(This is a rather crucial point, and I am beginning to wonder if those 
who support unspecified OoE have simply missed it.)

> > Also, even if OoE were specified, nothing would prevent the compiler
> > from rearranging the OoE (or parallelizing it) in situations where it
> > could prove that the resulting semantics are equivalent to the specified
> > fixed OoE, which would be the case for all programs written in a purely
> > functional style.  (As a consequence of this one might confidently
> > predict that with-arguments-evaluated-in-any-order, if it existed, would
> > seldom be used.)
> 
> That might be true if the only beneficiary of OoE information was the
> compiler.  However, humans have to work with code too, and in fact their
> needs are usually considered paramount.  If your smart compiler were to
> annotate the source code, or highlight it in an IDE, to allow the two to be
> distinguished reliably without any human effort, that would be a step
> forward.  But in general, it's difficult to do that, across e.g. module
> boundaries, especially in a latently-typed language like Scheme.

So what?  I'm arguing that the principle of least surprise dictates that 
the program semantics ought to be by default *as if* there were a fixed 
OoE, not that it *actually* have a fixed OoE.

> In any case, none of these speculative possibilities addresses the question
> asked by the OP, "Is there any utility to the order of evaluation being
> unspecified?"  My response to that was that the answer is yes, there is
> utility in it, although opinions differ as to exactly how much.  The
> responses I've received so far merely underscore my answer.  :)

I do not dispute that there is utility in having an unspecified OoE.  
What I am arguing against is making this the case by default.

rg
0
rNOSPAMon (1927)
10/5/2004 4:54:00 PM
"Anton van Straaten" <anton@appsolutions.com> wrote in message news:<fHp8d.3632$Vm1.2561@newsread3.news.atl.earthlink.net>...
> Thant Tessman <thant@acm.org> wrote:
> 
> > There is no "information" being conveyed by the fact that
> > function-argument order-of-evaluation is unspecified.
> 
> Of course there is.  The information exists by definition, in that there are
> some parts of the code for which order of evaluation is unspecified, and
> other parts for which it is specified, with the distinction in semantics
> indicated by syntax.  [...]

There is no information about the intention of the programmer or the
actual behavior of the code with respect to argument order of
evaluation conveyed by the fact that argument order of evaluation is
unspecified. You simply have no way of knowing (without the programmer
telling you directly) whether the programmer understood and
deliberately took into account this subtle and not universally
intuitive aspect of Scheme's semantics. And even if you confirmed they
did, you have no way of knowing (again, without examining the code
directly) that they didn't unintentionally introduce
order-of-evaluation bugs that simply aren't revealed by a particular
implementation at a particular time.

There is no information lost by fixing argument order of evaluation.

-thant
0
thant (332)
10/5/2004 5:05:47 PM
In article <41629F72.E0600C94@het.brown.edu>,
 Andre <andre@het.brown.edu> wrote:

> Ron Garrett wrote:
> 
> > Therefore, unspecified order of evaluation by default is a poor design 
> > choice.  A better choice would be to introduce language syntax that 
> > allows a programmer to specify that order of evaluation doesn't matter, 
> > e.g.:
> >
> > (with-arguments-evaluated-in-any-order . forms)
> 
> ... except that this imposes an extra syntactic burden for the most common
> case where order really does not matter, whereas the current status quo 
> reserves that burden, via let*, etc., for the more uncommon case.
> 
> A.

No.  I've made this point before, but I'll make it again: the mistake 
made by proponents of unspecified OoE is that they only distinguish two 
cases: where OoE matters, and where it does not.  But in fact there are 
*three* cases: 1) where OoE does not matter, 2) where OoE does matter, 
and 3) where OoE *might* matter but in fact does not due to external 
circumstances not manifested in the code.

Case 1 is indeed the most common, but it can further be broken down into 
two sub-cases: 1a) where the compiler can tell that OoE does not matter 
(i.e. in the case of a side-effect-free program) and 1b) where the 
compiler cannot tell.

The proponents of unspecified OoE focus on the fact that case 1 is the 
most common, which I will stipulate is correct.  But then I claim that 
case 1a is vastly more common than case 1b.  So the real issue here is 
the case where the compiler can't tell whether OoE matters.  I claim 
that in the vast majority of such cases, OoE does in fact matter.  
Furthermore, the cost of being wrong if you assume that OoE matters is a 
program that doesn't run as fast as it might.  The cost of being wrong 
if you assume that OoE doesn't matter is the constant risk that your 
program will one day do something different from what it has done 
before.  IMHO, the latter is a vastly higher price to pay, and in some 
lines of work (e.g. control software for nuclear power plants) it is in 
fact (or at least ought to be) a show stopper.

rg
0
rNOSPAMon (1927)
10/5/2004 6:31:45 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Joe Marshall <jrm@ccs.neu.edu> writes:
>
>>   4) Specifying the order of evaluation will reduce the surprise.   
>> 
>> Unfortunately, that isn't always true.  It is possible to have
>> order-of-evaluation bugs in languages that specify a deterministic
>> order of evaluation.  Surprising, no?
>
> Could you give an example?

Yes, but you won't like it.

I had a function that took three arguments, one caller had a hard time
computing the second argument.  The caller looked a bit like this:

   (foo (car baz)
        (cond ((null? bar) (append (mapcar (lambda () ...))...))
              ((vector? x) (vector->list (assq (reverse! ...))))
              ((not (pair? y)) (if (null? y) 
                                   '(some list)
                                   (use-default-y)))
              (else (call-with-current-continuation
                      (lambda (c)
                        (invoke-blah-blah c ...)))))
        (vector-ref quux 22))

It was hard to understand what was going on.  The natural thing to do
was to lift this out into a let statement:

   (let ((rather-hairy-thingy (cond ((null? bar) (append (mapcar (lambda () ...))...))
                                    ((vector? x) (vector->list (assq (reverse! ...))))
                                    ((not (pair? y)) (if (null? y) 
                                                         '(some list)
                                                         (use-default-y)))
                                    (else (call-with-current-continuation
                                           (lambda (c)
                                            (invoke-blah-blah c ...)))))))

      (foo (car baz) rather-hairy-thingy (vector-ref quux 22)))

And this *usually* worked, but sometimes failed.  The reason being
that one of the hairy subclauses called a function that caused a side
effect on BAZ.

I hadn't thought I was relying on order of evaluation, but I was, and
even though the order was specified as left-to-right (I was using
common lisp) I still got the bug.

>> So specifying the order of evaluation 
>>   a) doesn't fix the problem
>>   b) leads to more surprises
>
> Claim b) is obviously false because all surprise-free programs under
> unspecified order are also surprise-free under specified order.

It's a meta-claim.  If fixing the order of evaluation is supposed to
reduce surprise, then it is surprising that it fails to do so.

>> > Therefore, unspecified order of evaluation by default is a poor design 
>> > choice.  
>> 
>> I agree, but I argue that specifying the order of evaluation by
>> default is *also* a poor design choice, and is no better than leaving
>> it unspecified.
>
> <scratching head>       
> Hmm.  Sounds like Zen to me.  The opposite of a great thruth is also a
> thruth...
> </scratching head>

0
jrm (1310)
10/5/2004 8:51:44 PM
Andre <andre@het.brown.edu> wrote in message news:<41629F72.E0600C94@het.brown.edu>...
> Thant Tessman wrote:
> 
> > Imposing order of evaluation cannot surprise someone not expecting it.
> > So in this case the argument is asymmetrical.
> 
> Not when writing code, that is true.  Your suprise may vary when  
> reading someone else's code.  And you may be constantly and unpleasantly 
> surprised when refactoring such code.  

And this, as I pointed out in the previous thread, is the true
motivation behind the defense of unspecified argument order of
evaluation. Relying on OofE is not a bug in a language in which OofE
is specified. It is, however, according to some, really bad style--so
bad apparently that it must be punished. So important apparently is it
that this style of programming be punished, that even those whose
programs *unintentionally* depend on OofE must be penalized with
programs whose behavior is left unspecified and might change from one
implementation to the next, or even from one execution to the next.

[...]

-thant
0
thant (332)
10/5/2004 9:27:14 PM
Thant Tessman wrote:
> 
> Andre <andre@het.brown.edu> wrote in message news:<41629F72.E0600C94@het.brown.edu>...
> > Thant Tessman wrote:
> >
> > > Imposing order of evaluation cannot surprise someone not expecting it.
> > > So in this case the argument is asymmetrical.
> >
> > Not when writing code, that is true.  Your suprise may vary when
> > reading someone else's code.  And you may be constantly and unpleasantly
> > surprised when refactoring such code.
> 
> And this, as I pointed out in the previous thread, is the true
> motivation behind the defense of unspecified argument order of
> evaluation. Relying on OofE is not a bug in a language in which OofE
> is specified. It is, however, according to some, really bad style--so
> bad apparently that it must be punished. So important apparently is it
> that this style of programming be punished, that even those whose
> programs *unintentionally* depend on OofE must be penalized with
> programs whose behavior is left unspecified and might change from one
> implementation to the next, or even from one execution to the next.

You may have misunderstood my statement.  I was pointing out that 
*fixed* evaluation  order would *also* cause punishment.  
The argument was that if Scheme had fixed evaluation order, since 
more programs would then be written that actually depended on this fixed 
order of evaluation, such (correct) programs would cause punishment to those 
who have to read or refactor them.  It is certainly arguable how much
of a problem this is and which kind of punishment is worse, and there
is certainly a strong case for determinism, but I think 
everybody is motivated by a desire to *reduce* punishment, not
because anybody is secretly into S&M (not that there is anything wrong
with it).

A.
0
andre9567 (120)
10/5/2004 10:11:05 PM
Thant Tessman <thant@acm.org> schrieb:
> You simply have no way of knowing (without the programmer telling you
> directly) whether the programmer understood and deliberately took into
> account this subtle and not universally intuitive aspect of Scheme's
> semantics.

By this argument, no scheme program can ever convey any information.
Because maybe when the programmer wrote (define (foo bar) baz), she
meant to define a function, maybe she didn't -- clearly we can't assume
she read R5RS and knows what the heck she's doing. Maybe she was just
banging her head on the keyboard in frustration? Maybe these words I'm
typing right now *seem* to convey some information based on your
understanding of English, but in reality I'm speaking a different
language with the same syntax and completely different semantics, and
this post merely expounds on the innate beauty of belly-button fuzz.

I think what you're really saying is that some features of the spec are
more likely to be applied meaningfully than others, but whether the
particular feature of unspecified OoE is *so* unintuitive that *nobody*
could possibly use it on purpose, is certainly a matter of subjective
opinion.
0
adrian61 (83)
10/6/2004 12:10:25 AM
Joe Marshall wrote:


> And this *usually* worked, but sometimes failed.  The reason being
> that one of the hairy subclauses called a function that caused a side
> effect on BAZ.
> 
> I hadn't thought I was relying on order of evaluation, but I was, and
> even though the order was specified as left-to-right (I was using
> common lisp) I still got the bug.

There is a problem with this argument.

Having an unspecified order of evaluation would not have
saved you from this bug.

Whatever possible order of evaluation manifests your bug,
a language with an unspecified order of evaluation can
do it.

Having a specified order of evaluation, on the other hand,
gives at least one order of evaluation that correct code
can rely on.

Having a specified order of evaluation also gives consistent
behavior in the case of OofE bugs; with a fixed OofE, such
buggy code will not run correctly on *ANY* systems.  Because
of this consistency, it is easier to debug programs and
easier to be sure of their portability between
implementations.

				Bear


0
bear (1219)
10/6/2004 1:00:25 AM
Adrian Kubala <adrian@sixfingeredman.net> wrote in message news:<slrncm6dvh.4i5.adrian@sixfingeredman.net>...
> Thant Tessman <thant@acm.org> schrieb:
> > You simply have no way of knowing (without the programmer telling you
> > directly) whether the programmer understood and deliberately took into
> > account this subtle and not universally intuitive aspect of Scheme's
> > semantics.
> 
> By this argument, no scheme program can ever convey any information. [...]

Of course it's important to try to understand the intention of the
programmer. But it's more important to understand the actual behavior
of the program regardless of the intention of the programmer. My point
is that attempting to divine the intention of the programmer from a
program whose behavior is by definition undefined is silly.

-thant
0
thant (332)
10/6/2004 2:31:21 PM
Adrian Kubala <adrian@sixfingeredman.net> writes:
> Thant Tessman <thant@acm.org> schrieb:
> > You simply have no way of knowing (without the programmer telling you
> > directly) whether the programmer understood and deliberately took into
> > account this subtle and not universally intuitive aspect of Scheme's
> > semantics.
> 
> By this argument, no scheme program can ever convey any information.

But arguably a yak can convey one to the scary devil monastery where
one can learn to apreciate the true lambda-nature inherent in all the
vain strivings bound to these contours of illusion. In fact this was
the cover article of the July issue of the Nepalese Journal for
Deconstructionist Sociologists and Sheep-herders, the premier academic
journal of Himalayan computing (among other topics).

> Because maybe when the programmer wrote (define (foo bar) baz), she
> meant to define a function, maybe she didn't -- clearly we can't assume
> she read R5RS and knows what the heck she's doing. 

Such authoritarian appeals only demonstrate the lack of inner peace
that can only be acquired through a detailed study of mammalian
behaviors at altitude. It is clearly the case that nothing should be
assumed about the programmer's intention without a careful semiotic
analysis of the cultural factors implied by the development
process. Indeed careful attention should be paid in view of the
implied moral judgement conatined in the notion of development, when
in fact the whole corpus of instruction could simply be subject to
bit-rot.

> Maybe she was just
> banging her head on the keyboard in frustration? 

What is the sound of one forehead typing?

> Maybe these words I'm
> typing right now *seem* to convey some information based on your
> understanding of English, but in reality I'm speaking a different
> language with the same syntax and completely different semantics, and
> this post merely expounds on the innate beauty of belly-button fuzz.

This was a particularly cogent post right which we werre considering
reprinting in the Nepalese Journal right up until the point where you
began writing a different language that had English lexical and
syntactic structure, but seemed to be considering some completely
different subject domain. The relevant clause was reviewed by the entire
Editorial Collective and found to be full of inexcusably unarguable
content. Should you amend your post we would like to discuss an
on-going contract for a periodic column in the NJDSS. Anton
VonStraaten has been so busy lately...

> I think what you're really saying is that some features of the spec are
> more likely to be applied meaningfully than others, 

Implication is undoubtedly more important than application, no?

> but whether the
> particular feature of unspecified OoE is *so* unintuitive that *nobody*
> could possibly use it on purpose, is certainly a matter of subjective
> opinion.

And the whole subject/object relationship hasn't been adequately
explored in the Himalayan computing field (located 500 meters upslope
outside of our offices). It's entirely possible we could sponsor a
fellowship for advanced research if you would be so inclined...

The NJDSS Editorial Collective
-- 
There are no quality-control or safety standards for pedestrians
	-- P.J. O'Rourke
	   _An Argument in Favor of Automobiles Instead of Pedestrians_
0
10/6/2004 2:34:25 PM
Andre <andre@het.brown.edu> wrote in message news:<41631BF9.E28627A0@het.brown.edu>...

[...]

> You may have misunderstood my statement.  I was pointing out that 
> *fixed* evaluation  order would *also* cause punishment.  [...]

No, I didn't misunderstand your statement. I was merely trying to
point out that it's a different argument--although one that fails for
the same reason. Think about what kind of evidence one might use to
defend this argument. It would have to be an example of code that, due
to the fact that it deliberately relied on fixed OofE in a language
that specified fixed OofE, was somehow harder to understand or
refactor. No one has yet provided such an example in this forum (that
I've seen), but let's postulate the existence of one.

Here's the thing: That code example might be an example of bad style
in a language with fixed OofE, but it's simultaneously an example of
indeterminantly-busted code in a language with unspecified OofE. How
the latter is an improvement over the former has yet to be explained.

-thant
0
thant (332)
10/6/2004 4:09:34 PM
I apologize for following up on my own post, but this thought deserves 
finishing in order to preempt an anticipated response:

Thant Tessman wrote:

[...]

> Here's the thing: That code example might be an example of bad style
> in a language with fixed OofE, but it's simultaneously an example of
> indeterminantly-busted code in a language with unspecified OofE. How
> the latter is an improvement over the former has yet to be explained.

The difference between these two cases (already pointed out by both 
sides of this debate) is that while the latter is either unintentional 
or based on a misunderstanding of the language, the former might be 
intentional. That's why I described this argument about unspecified OofE 
as really being an argument about punishment of a thought crime.

-thant

0
thant (332)
10/6/2004 5:06:55 PM
NJDSS Editorial Collective <collective@njdss.org> wrote:
> But arguably a yak can convey one to the scary devil monastery where
> one can learn to apreciate the true lambda-nature inherent in all the
> vain strivings bound to these contours of illusion.

True.  As less enlightened authorities have written:

    If guns were outlawed, then only outlaws would have guns.

From which it follows that, if guns were not outlawed, having
guns would no longer be a conclusive indicator of outlawry.

What I'd like to know is: Would all the participants in this
thread be satisfied by a compromise in which guns are not
outlawed, but only outlaws have guns?

I'm serious about this.  I really want to know.  What I am
asking is:  Would you would be happy with a language in which
the language's semantics imposes a fixed deterministic order
of evaluation upon implementors, but programs that depend on
this order of evaluation are regarded as buggy?

An approximation to this situation can be achieved by using
an extremely arcane fixed order of evaluation, which is not
defined except in the fine print of a codicil that no sane
non-implementor would read, and by warning programmers that
TO DEPEND UPON THE FIXED ORDER OF EVALUATION IS UNIVERSALLY
REGARDED AS EXTREMELY BAD STYLE; PERPETRATORS OF THIS STYLE
SHOULD BE DRAWN AND QUARTERED.

Will
0
cesuraSPAM (401)
10/7/2004 12:16:30 AM
"William D Clinger" <cesuraSPAM@verizon.net> wrote

> I'm serious about this.  I really want to know.  What I am
> asking is:  Would you would be happy with a language in which
> the language's semantics imposes a fixed deterministic order
> of evaluation upon implementors, but programs that depend on
> this order of evaluation are regarded as buggy?
>
> An approximation to this situation can be achieved by using
> an extremely arcane fixed order of evaluation

A brilliant compromise, which should satisfy those who have valid concerns
about nondeterminism in critical software.  The order probably does not even
have
to be that arcane.  I personally think right to left should be sufficient to
discourage
most unintentional errors and instances of bad style.

Andre


0
email7695 (32)
10/7/2004 12:49:56 AM
"William D Clinger" <cesuraSPAM@verizon.net> wrote in message news:fb74251e.0410061616.4fd47535@posting.google.com...
> I'm serious about this.  I really want to know.  What I am
> asking is:  Would you would be happy with a language in which
> the language's semantics imposes a fixed deterministic order
> of evaluation upon implementors, but programs that depend on
> this order of evaluation are regarded as buggy?

I am curious what it means to declare a program "buggy" when
(1) the intended behaviour of the program is consistent with the
language definition's fixed order of evaluation and (2) implementations
which wish to be regarded as compliant with that language definition
are compelled to correctly execute that program.

> An approximation to this situation can be achieved by using
> an extremely arcane fixed order of evaluation

I would have trouble with a fixed order of evaluation, where the
actual order can not be defended logically except as an attempt
to confound those who would write (f (read) (read) (read)).

On a somewhat separate note:
To the degree that an unspecified order of evaluation is desirable
because a compiler may produce faster code by re-ordering the
evaluation of a function's arguments, I wonder what proportion of
those re-orderings would be done where the compiler could tell
that re-ordering would make no difference to program's behaviour
vs. cases where the compiler has no clue?

Jim




0
jim251 (34)
10/7/2004 4:24:01 AM
William D Clinger wrote:

> TO DEPEND UPON THE FIXED ORDER OF EVALUATION IS UNIVERSALLY
> REGARDED AS EXTREMELY BAD STYLE; PERPETRATORS OF THIS STYLE
> SHOULD BE DRAWN AND QUARTERED.

Is there a canonical reference that discusses pros and cons of such a 
style? (A paper, a textbook section, a wiki, whatever?)


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
0
costanza (1427)
10/7/2004 6:39:07 AM
Jim Bender <jim@benderweb.net> wrote:
> I would have trouble with a fixed order of evaluation, where the
> actual order can not be defended logically except as an attempt
> to confound those who would write (f (read) (read) (read)).

I don't really mean to pick on Jim, and I hope he will forgive me, but I
think that this discussion could be much more productive if some people
didn't try to paint it as so one-sided.  "Can not be defended logically" is
not just an overstatement of the case - it's simply false.

The logical defense is that there's value in being able to communicate that
certain code does not depend on an order of evaluation, and that other code
in the same program does.  The problem is, that's not an easy thing to do in
a way that addresses all the surrounding issues satisfactorily.

Some people complain that such an assertion is not statically checkable, and
even dynamic checkability is harder than usual to come by.  However, we
don't usually check types statically in Scheme, either; and in practice,
experience in Scheme, C, C++, and OCaml indicates that the issues resulting
from unspecified evaluation order are certainly no more problematic than
those that arise from unintentional order dependencies in language with
fixed evaluation order (and arguably, less so).  That's because evaluation
order issues can occur in any language with side effects, regardless of the
language's specified evaluation order.

Since examples such as (f (read) (read) (read)) are by far the exception,
rather than the rule, they could easily be dealt with by a convenient
special form.  Something like that could be implemented via a macro, and
perhaps specified in a SRFI.  It is much less easy to communicate
order-independence in these sorts of ways, because order-independent code in
argument lists and expressions dominates all useful programs, in most
languages.  The idea that only some subset of this order-independent code
needs to be marked as order-independent doesn't fly - order-dependence is
the exception, and that's what needs to be flagged as exceptional.

The problem with the opposing positions here tends to be that even when they
acknowledge any value in the ability to specify order independence, they all
seem to take the basic stance that this ability is worth sacrificing, in
exchange for unambiguous semantics.  No-one should be surprised that there's
opposition to this idea.  It offers unambiguous semantics only for a less
expressive language, a language that cannot express certain properties of
the programs written in it.

Suggest a credible alternative to this, and I'm sure everyone will listen.
Otherwise, we're left fighting over whose preferences might get stomped on
in a future standard, which makes for a lot of heat, and unusually little
light.

I find it disappointing that because this is a difficult and subtle issue to
deal with, many smart people are so willing to simply dismiss or ignore it
in favor of an easy way out.  Java did that.  It's a pragmatic choice, for
an industrial language.  It was also a pragmatic choice for SML.  SML made a
number of other pragmatic choices: things like LET being equivalent to
Scheme's LET*, for example.  In some of these kinds of ways, Scheme supports
the expression of finer distinctions in the programmer's intent than either
ML or even Haskell.  As R5RS says, "Scheme would still be useful as a
notation for expressing computational methods even in the absence of a
mechanical implementation."  Many papers have demonstrated this, and that
fine-grained ability to communicate the exact nature of a computation can be
useful.  Personally, I enjoy using it in my own programs, even though there
are many times when less precise expression would do.

In this context, simply fixing evaluation order, and removing any penalty
for relying on it anywhere, would be quite counter to the common situation
in the Scheme world, where much attention has historically been paid to
resolving minutiae satisfactorily.  Here Scheme is, in 2004 CE, about 30
years after its invention, without a standard module system, which almost
any other serious language has in some form or another.  The funny thing is,
if you truly understand Scheme, you are likely to be aware of *good* reasons
for why this is the case.  (Not that this situation shouldn't be corrected
in future.)

When Scheme gets a standard module system, it should be a good one.  It
won't be the ad-hoc conflation of otherwise orthogonal features that you see
in the industrial languages.  It will support staged computation (macros) in
ways that even advanced module systems in other functional languages do not.
Scheme has waited decades for this.  In dealing with evaluation order,
however that is eventually done, we should try to do justice to the
tradition of Scheme.

Anton


0
anton58 (1240)
10/7/2004 7:40:47 AM
William D Clinger wrote:
> What I'd like to know is: Would all the participants in this
> thread be satisfied by a compromise in which guns are not
> outlawed, but only outlaws have guns?
>
> I'm serious about this.  I really want to know.  What I am
> asking is:  Would you would be happy with a language in which
> the language's semantics imposes a fixed deterministic order
> of evaluation upon implementors, but programs that depend on
> this order of evaluation are regarded as buggy?

That seems acceptable to me.  The important point is that it should be
possible to distinguish between code which is "allowed" to depend on
evaluation order, and code which is not allowed to do so.  Aside from
communicating between humans, this also provides support for analysis by
tools.

> An approximation to this situation can be achieved by
> using an extremely arcane fixed order of evaluation

I agree with Andre, right-to-left order would be sufficiently arcane, and
has some precedent both in Scheme world (e.g. SISC and MIT) and elsewhere
(e.g. OCaml's implementation).

But I'd be concerned that along the way, this would get diluted into fixed
left-to-right order, leaving only the warning:

> TO DEPEND UPON THE FIXED ORDER OF EVALUATION IS
> UNIVERSALLY REGARDED AS EXTREMELY BAD STYLE;
> PERPETRATORS OF THIS STYLE SHOULD BE DRAWN
> AND QUARTERED.

The problem is that despite the "universally" claim, not everyone agrees
with this warning, and by itself, it would ultimately be ignored enough to
lose significant value.  In any case, for me, the point is not so much the
"punishment of thought crimes" that has been raised in this thread, but
rather that the ability to communicate order of evaluation dependency
distinctions in code becomes lost, if there is no "enforcement" mechanism
whatsoever.

Anton


0
anton58 (1240)
10/7/2004 7:58:09 AM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
>
> > [ ... ] it's not possible to test
> > fixed-eval-order code for unintended eval order dependencies.
>
> False.  You can run all the same tests.  Maybe you find that they fail
> more often because, as you say yourself, people might actually take
> advantage of the language guarantees.  But to say that you can't run
> the tests is nonsense.

The tests become worthless in practice when order is fixed, for the reason
you mention.  You lose the ability to distinguish which code is supposed to
be independent of evaluation order when people take advantage of the
language guarantees outside of explicit sequencing constructs.

> And if your convention is to encode the information using certain
> coding conventions (as questionable a practice as this may be),
> then those tests will point out where the conventions were violated.

The convention loses significant value if it's not universally followed.

> > I addressed that in my original post: "in practice, being able to
> > rely on fixed evaluation order anywhere in a program means that at
> > least some people will do just that.  This has a severe negative
> > impact on the ability to use such a convention to encode
> > information."
>
> And that's a good thing.  It is an extremely clumsy and brittle way
> of encoding this type of information.  I can't believe anyone can
> possibly defend it and keep a straight face.

My interest is in defending the ability to encode the information in
question, not in any specific technique for doing that.  However, good
techniques seem in short supply.  What alternative ways of encoding this
information do you suggest?  Keep in mind that suggesting future
possibilities doesn't actually address the issue today, and that Scheme
currently does succeed in enforcing it in a way which some people find
satisfactory, if not ideal.

Also, as long as we're offering "let them eat cake" solutions, anyone
writing papers involving the semantics of Scheme can point out that their
results are based on a left-to-right dialect (or whatever), and all the
equivalences you've pointed out between unspecified order and fixed order
apply.

See also my reply to Jim Bender, dated today.

Anton


0
anton58 (1240)
10/7/2004 8:11:28 AM
Ron Garret wrote:
> In article <_Kp8d.3634$Vm1.2292@newsread3.news.atl.earthlink.net>,
>  "Anton van Straaten" <anton@appsolutions.com> wrote:
>
> > Ron Garret <rNOSPAMon@flownet.com> wrote:
> > >
> > > FWIW, here's my take on this.
> > >
> > > IMHO:
> > >
> > > 1) One of the central principles of good programming language design
is
> > > the principle of least surprise.
> >
> > Although it's often touted in informal contexts, that's a controversial
> > principle, mainly because it's too vague.  You certainly won't find it
in
> > many semantics texts!
>
> I won't find it many physics texts either.  And your point would be...?

Let me come at that from the other direction.  Where can I read up on this
principle, so that I can understand it as something other than a way to
defend some of the quirkier features of scripting languages?

> > > 2) Most people are surprised when a single program in an ostensibly
> > > deterministic language with no external interactions behaves in two
> > > different ways on two different occasions.
> >
> > If that's not the expected behavior, then you're describing a buggy
program.
> > That's nothing to do with principle of least surprise - bugs happen,
they
> > get reported, and fixed.
>
> Do they?  How can I tell if I have a Scheme program whose semantics
> depend on OoE?  If I have a Scheme program which accepts no input from
> the outside and has worked correctly on 99 runs, how can I be sure it
> will work correctly on the 100th run?

You can use an implementation with fixed evaluation order to be sure of
that.  No-one (afaik) is suggesting that implementations should not be
allowed to offer fixed evaluation order.  We're talking about the
specification here.

> > > 3) Leaving order of evaluation unspecified in a language that also has
> > > side effects makes such an occurrence all but inevitable.
> >
> > Having side effects at all makes an entire class of otherwise avoidable
bugs
> > inevitable, yet we still tolerate them for some reason, even in
languages
> > like SML/NJ.
>
> We tolerate side effects because they are useful.

You mean "we tolerate the bugs which side effects cause because side effects
are useful."  The exact same argument applies to having the ability to
specify a distinction between code that depends on order of evaluation, and
code which does not.

> The whole point of
> having high level programming languages at all is to create a better
> "impedance match" between the kinds of information that computers
> process and the kinds of information human brains process.  If we could
> rely on programmers to follow conventions, recognize errors, RTFM, etc.
> there would be no utility to high level languages at all.  But they
> don't, so there is.  And for some reason, most people find it easier to
> think in terms of side effects when they sit down to solve certain
> classes of problems.  That's just the way that the human brain seems to
> be wired.

Oy.  I think this belongs in c.l.l.

> [Off-topic rant: I have mostly stayed out of the Bill Richter wars,
> except to celebrate his temporary departure and quietly lament his
> return.  The main reason I find everything Bill writes to be utterly
> irrelevant is that I reject his central tacit premise, that mathematics
> has value above all else in CS.  It doesn't.  The study of programming
> languages has as much to do with psychology, economics, and politics as
> it does with math, a fact that lamentably few of its practitioners seem
> to recognize.]

I agree that human factors are very important.  In fact, the human factors
are central to this issue.  The argument against "ambiguous semantics" is
primarily a semantic argument, not a human factors argument, and the
argument goes "we must restrict the language's expressivity in order to make
it tractable".  But that's theoreticaly tractability, not practical
tractability.  The argument can and has been made that fixed evaluation
order is less tractable in practice, because it leads to the masking of
fragile unintended order dependence.

> > > (call-with-arguments-evaluated-in-any-order thunk . argforms)
> > >
> > > which could, of course, have suitable abbreviations.
> >
> > Syntax like that would dominate any normal program, even an imperative
one.
>
> I doubt that very much.

Of course it would.  See below.

> > Even in traditional imperative languages, most function call argument
lists
> > and most expressions don't depend on order of evaluation.  The software
> > world would be in far worse shape if that weren't the case.
>
> It is true that most expressions etc. don't depend on OoE, but that is
> simply a mathematical fact, and so it is nonsensical to speculate what
> the consequences would be if it weren't true.  What we are talking about
> is how to treat those cases where it *does* (or might) matter.
>
> (This is a rather crucial point, and I am beginning to wonder if those
> who support unspecified OoE have simply missed it.)

The cases where it might matter include every function call whose argument
list itself contains a function call.  That's quite a large set, and that
alone makes the approach you're suggesting unpalatable.

[re the compiler rearranging OoE:]
> So what?  I'm arguing that the principle of least surprise dictates that
> the program semantics ought to be by default *as if* there were a fixed
> OoE, not that it *actually* have a fixed OoE.

My point was just that compiler optimizations are a secondary part of the
picture, which follow from having the ability in code to specify the
distinction between code that's order dependent and code that isn't.  Having
the compiler be aware of some subset of order independent code "even if OoE
were specified" doesn't address any of my concerns.

> > In any case, none of these speculative possibilities addresses the
question
> > asked by the OP, "Is there any utility to the order of evaluation being
> > unspecified?"  My response to that was that the answer is yes, there is
> > utility in it, although opinions differ as to exactly how much.  The
> > responses I've received so far merely underscore my answer.  :)
>
> I do not dispute that there is utility in having an unspecified OoE.
> What I am arguing against is making this the case by default.

That makes littel sense, given usage patterns in actual programs, including
imperative ones, and especially in a language in which everything other than
a macro/special form is a function call.

Anton


0
anton58 (1240)
10/7/2004 8:32:29 AM
"NJDSS Editorial Collective" <collective@njdss.org> wrote:
> Should you amend your post we would like to discuss an
> on-going contract for a periodic column in the NJDSS.
> Anton VonStraaten has been so busy lately...

True.  Of course, it would help if the Collective would send me my author's
stipend more regularly.

> And the whole subject/object relationship hasn't been adequately
> explored in the Himalayan computing field (located 500 meters
> upslope outside of our offices). It's entirely possible we could
> sponsor a fellowship for advanced research if you would be
> so inclined...

I find this most interesting, since my work on the evanescent nature of
objects would be legendary, if not for the fact that the work in question
self-referentially demonstrates its subject, and thus does not enjoy the
sort of "concrete existence" which unenlightened modernists appeal to so
thoughtlessly.

If telecommuting is a possibility, my signed acceptance papers will be on
the next available yak.

Anton


0
anton58 (1240)
10/7/2004 8:57:20 AM
In article <3q69d.6979$Vm1.1407@newsread3.news.atl.earthlink.net>, Anton van
Straaten wrote:
> 
> Some people complain that such an assertion is not statically checkable, and
> even dynamic checkability is harder than usual to come by.  However, we
> don't usually check types statically in Scheme, either; and in practice,
> experience in Scheme, C, C++, and OCaml indicates that the issues resulting
> from unspecified evaluation order are certainly no more problematic than
> those that arise from unintentional order dependencies in language with
> fixed evaluation order (and arguably, less so).  That's because evaluation
> order issues can occur in any language with side effects, regardless of the
> language's specified evaluation order.

That's not my experience. Every single order-of-evaluation-related bug
that I have ever had in a strict language has arisen when evaluation
was not left to right. (Not just in Scheme, but in Ocaml, too.) If you
fixed order of evaluation to left to right, I would never have ever
even seen a single instance of this kind of error.

I think there are some pretty good theoretical reasons for this, too.
If there is to be an isomorphism between the curried and uncurried
forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
strict setting, then you must have have left-to-right order of
evaluation.

> Since examples such as (f (read) (read) (read)) are by far the exception,
> rather than the rule, they could easily be dealt with by a convenient
> special form.  

No, this is literally the only source of order of evaluation bugs I've
ever had. I mean, I can see the pragmatic case not to declare a fixed
order -- it's not cool to declare solid, existing implementations
non-conforming -- but I don't think there's any principled case
against fixing the order of evaluation to left to right.

-- 
Neel Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
10/7/2004 2:02:05 PM
Neelakantan Krishnaswami wrote:

> I think there are some pretty good theoretical reasons for this, too.
> If there is to be an isomorphism between the curried and uncurried
> forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
> strict setting, then you must have have left-to-right order of
> evaluation.

That is actually a very solid reason.  I can feel myself being swayed.

> > Since examples such as (f (read) (read) (read)) are by far the exception,
> > rather than the rule, they could easily be dealt with by a convenient
> > special form.
> 
> No, this is literally the only source of order of evaluation bugs I've
> ever had. I mean, I can see the pragmatic case not to declare a fixed
> order -- it's not cool to declare solid, existing implementations
> non-conforming -- but I don't think there's any principled case
> against fixing the order of evaluation to left to right.

I can contribute a (somewhat esoteric) bug that I have had
in the context of the Filinski encoding of monads in Scheme.
See the thread

 http://groups.google.com/groups?selm=403B9327.A03773D9%40het.brown.edu

where the following expression in the list monad

   (reify (cons (reflect '(1 2)) 
                (reflect '(5 6))) 

would not give the correctly ordered answer.  

Andre.
0
andre9567 (120)
10/7/2004 2:49:48 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> The problem with the opposing positions here tends to be that even when they
> acknowledge any value in the ability to specify order independence, they all
> seem to take the basic stance that this ability is worth sacrificing, in
> exchange for unambiguous semantics.  No-one should be surprised that there's
> opposition to this idea.  It offers unambiguous semantics only for a less
> expressive language, a language that cannot express certain properties of
> the programs written in it.

Hear, hear!  Isn't that *precisely* the argument in favor of static
type systems?  Fewer programs are legal, so having a legal program
carries more information.  (The difference, of course, is that static
type systems are statically checkable, so the validity of the
information can be verified and does not have to be taken on faith.)

> Suggest a credible alternative to this, and I'm sure everyone will listen.

The alternative is to express this information some other way -- as
pragma annotations or something similar.  Such a solution does not
compromise the semantics but can still give hints to programmers and
lint tools.

(Personally, I am perfectly happy with the obvious third alternative:
fix the evaluation order.  That's because I personally consider the
loss of expressiveness so minor that I am constantly surprised how
people can get so worked up about this issue.)

> Otherwise, we're left fighting over whose preferences might get stomped on
> in a future standard, which makes for a lot of heat, and unusually little
> light.

Ok, just to make sure you realize that I do understand the issue, let
me put this whole thing a bit more formally:

Consider some programs p, p1, p2, ... and a correctness criterion C.
The correctness criterion depends on whether or not the language
specifies order of evaluation, so there really are two separate
criteria: Co and Cu (Ordered, Unordered).

The first question one certainly is interested in when considering
correctness is the basic one:

   Co(p) ?
   Cu(p) ?

I think we all agree that Cu(p) implies Co(p).  In other words, more
programs are correct under specified order, so writing correct
programs under these rules might be a bit easier -- it certainly is no
harder.

Lemma:  For all p, Cu(p) -> Co(p)

The second question, which captures the refactoring problem to some
extend, is this: Let there be two programs p1 and p2, perhaps related
in some way (e.g., p2 being a refactored version of p1).  Does
correctness of p1 imply correctness of p2?

   Co(p1) -> Co(p2)  ?
   Cu(p1) -> Cu(p2)  ?

Let's abbreviate Co(p1) -> Co(p2) as CRo(p1,p2) and Cu(p1) -> Cu(p2) as
CRu(p1,p2).

Without doubt, there are cases where CRu(p1,p2) does not imply
CRo(p1,p2).  This is what you are constantly arguing here: not
specifying the order makes fewer programs legal, therefore having a
legal program carries more information, and this extra information
might be the difference between being able to prove CRu(p1,p2) and not
being able to prove CRo(p1,p2).

There are at least two ways of arguing that this "advantage" might not
outweigh the advantage of Co(p) itself being strictly easier to
establish than Cu(p):

1.  In the general case, CRo(p1,p2) and CRu(p1,p2) are, in fact,
    unordered (i.e., neither implies the other).

    However, one can imagine that p2 is restricted to programs where all
    evaluation order is explicit (e.g., A-normal form), so by
    definition we would have Cu(p2) = Co(p2).  In this case, assuming
    Co(p1) -> Co(p2), using the Lemma, we get:

         Cu(p1) -> Co(p1) -> Co(p2) = Cu(p2)

    For an important class of problems, it is indeed the case that
    CRo(p1,p2) implies CRu(p1,p2).

    However, if p2 is restricted in the way described, the "advantage"
    for refactoring is lost after the first refactoring step.
    Subsequent additional refactoring steps benefit nothing.

2.  When actually refactoring code, I am not only interested whether
    CRx(p1,p2) holds, but ultimately whether Cx(p2) holds.  If all I
    know is CRx(p1,p2) I have to either independently establish Cx(p1)
    or Cx(p2).  But that, according to the Lemma, is easier when x = o.

> SML made a number of other pragmatic choices: things like LET being
> equivalent to Scheme's LET*, for example.

False.

SML's "let" can express both Scheme's "let" and Scheme's "let*"
(ignoring order-of-evaluation guarantees):

   let val x = ...                      works like Scheme's let*
       val y = ...


   let val x = ...                      works like Scheme's let
       and y = ...

Although this has nothing to do with the argument at hand, incorrect
claims like this do not reflect well on your reasoning and might be
construed as evidence for a blind, uncritical bias towards the way
Scheme does things right now.

Matthias
0
find19 (1244)
10/7/2004 2:56:23 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> [ ... ]but rather that the ability to communicate order of evaluation
> dependency distinctions in code becomes lost, if there is no
> "enforcement" mechanism whatsoever.

But in practice there currently is no enforcement mechanism.  That's
my whole point: establishing that I did not violate the rules is too
difficult in general.  That's why the rules are bad.
0
find19 (1244)
10/7/2004 3:00:04 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> The convention loses significant value if it's not universally followed.

It isn't now.

> However, good techniques seem in short supply.

Nonsense.  As I just wrote in a separate article, I can think of many
good ways of encoding this information.  The fact that it hasn't been
done already is an indication that the problem might not be so
important after all.

(Also, remember that the "technique" currently applied is particularly
bad.)

> What alternative ways of encoding this
> information do you suggest?  Keep in mind that suggesting future
> possibilities doesn't actually address the issue today, and that Scheme
> currently does succeed in enforcing it in a way which some people find
> satisfactory, if not ideal.

Oh, so we are supposed to come up with alternatives, but the
alternatives aren't allowed to change the languages in question in any
way?  We must come up with an encoding of a certain type of
information in such a way that all existing programs already correctly
use that encoding?  Are you serious?

0
find19 (1244)
10/7/2004 3:07:29 PM
Anton van Straaten wrote:

> [...] The argument against "ambiguous semantics" is
> primarily a semantic argument, not a human factors argument, and the
> argument goes "we must restrict the language's expressivity in order to make
> it tractable". 

No. The argument is that leaving argument OofE unspecified does nothing 
to make the language more expressive.


> [...] But that's theoreticaly tractability, not practical
> tractability.  The argument can and has been made that fixed evaluation
> order is less tractable in practice, because it leads to the masking of
> fragile unintended order dependence.

Except that no one has successfully argued how leaving OofE unspecified 
makes this less likely to happen. Any OofE rearrangement test is equally 
effective in either situation. The only difference is that in the case 
of a language with fixed OofE, it's possible that in some situations, 
you're merely a style cop, and not a bug hunter.

Elsewhere:

> The problem with the opposing positions here tends to be that even when they
> acknowledge any value in the ability to specify order independence, they all
> seem to take the basic stance that this ability is worth sacrificing, in
> exchange for unambiguous semantics. 

Again, no. I'm running out of ways to describe how silly this sounds. 
Say your housing development board member walks up to you and says 
"You're allowed to paint your house an unspecified color."

"Okay," you say, "I'll paint it light blue."

"No!" says the board member. "It must be an unspecified color."

The goal is to write code that avoids imperative style as much as 
practical. A side-effect (er, so to speak) of the persuit of that goal 
is that the order of argument evaluation becomes irrelevant. It does not 
follow that decreeing OofE irrelevant will automatically make code less 
imperative.


-thant

0
thant (332)
10/7/2004 4:14:16 PM
Thant Tessman <thant@acm.org> writes:
> Again, no. I'm running out of ways to describe how silly this sounds. Say your
> housing development board member walks up to you and says "You're allowed to
> paint your house an unspecified color."
> 
> "Okay," you say, "I'll paint it light blue."
> 
> "No!" says the board member. "It must be an unspecified color."

Exactly. Code that is correct for unspecified orders must be correct for any
particular order. 

So if we pick one (and what other than left-to-right since that is the text
order, allows currying, etc.) such code is no worse, and now people can safely
rely on it when needed.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/7/2004 4:31:09 PM
thant@acm.org (Thant Tessman) writes:

> Here's the thing: That code example might be an example of bad style
> in a language with fixed OofE, but it's simultaneously an example of
> indeterminantly-busted code in a language with unspecified OofE. How
> the latter is an improvement over the former has yet to be explained.

Under unspecified order of evaluation, this program transform:

(foo <expression0> <expression1> <expression2>)

  <=> (let ((var <expression1>))
        (foo <expression0> var <expression2>))

is legal for all *correct* programs.  That is, no correct program will
become incorrect after making that transformation. 

Under L2R or R2L order of evaluation, that transform can break a
correct program.
0
jrm (1310)
10/7/2004 4:37:38 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> thant@acm.org (Thant Tessman) writes:
> 
> > Here's the thing: That code example might be an example of bad style
> > in a language with fixed OofE, but it's simultaneously an example of
> > indeterminantly-busted code in a language with unspecified OofE. How
> > the latter is an improvement over the former has yet to be explained.
> 
> Under unspecified order of evaluation, this program transform:
> 
> (foo <expression0> <expression1> <expression2>)
> 
>   <=> (let ((var <expression1>))
>         (foo <expression0> var <expression2>))
> 
> is legal for all *correct* programs.  That is, no correct program will
> become incorrect after making that transformation. 
> 
> Under L2R or R2L order of evaluation, that transform can break a
> correct program.

True.  But so what?  The fact you are getting at is /obvious/ because
you rearranged the order of evaluation and order of evaluation matters
in languages with effects.  The correct (and easy) fix is to write:

   (let* ((var0 <expression0>)
          (var1 <expression1>))
      (foo var0 var1 <expression2>)))

How about this one:

  In the language definition, we summarily declare /every/ program
  incorrect.  The huge "advantage" of doing so is that now /every/
  program transformation on correct programs is correct.

See?  It obviously does not make sense when taken to the extreme.  The
remaining question is at which degree it stops making sense.  My claim
is that it stops making sense very early on.

Matthias
0
find19 (1244)
10/7/2004 4:46:27 PM
Ray Dillinger <bear@sonic.net> writes:

> Joe Marshall wrote:
>
>
>> And this *usually* worked, but sometimes failed.  The reason being
>> that one of the hairy subclauses called a function that caused a side
>> effect on BAZ.
>> I hadn't thought I was relying on order of evaluation, but I was, and
>> even though the order was specified as left-to-right (I was using
>> common lisp) I still got the bug.
>
> There is a problem with this argument.
>
> Having an unspecified order of evaluation would not have
> saved you from this bug.

Correct.  I assert that the existence of order of evaluation bugs has
nothing to do with whether the order is specified or not.

> Whatever possible order of evaluation manifests your bug,
> a language with an unspecified order of evaluation can
> do it.

Correct.

> Having a specified order of evaluation, on the other hand,
> gives at least one order of evaluation that correct code
> can rely on.

Since the code was buggy, this is irrelevant.

> Having a specified order of evaluation also gives consistent
> behavior in the case of OofE bugs; with a fixed OofE, such
> buggy code will not run correctly on *ANY* systems.  

In this example, since I was using Common Lisp and therefore had a
fixed order of evaluation, it is the case that it would exhibit the
same bug under all correct systems.  

It is true that there are Scheme programs that accidentally rely on
order of evaluation and produce the correct answer on some
implementations and the wrong answer on others.

> Because of this consistency, it is easier to debug programs and
> easier to be sure of their portability between implementations.

If your intent is to port buggy programs, then clearly a specified
order of evaluation is important.
0
jrm (1310)
10/7/2004 4:47:16 PM
cesuraSPAM@verizon.net (William D Clinger) writes:

> I'm serious about this.  I really want to know.  What I am
> asking is:  Would you would be happy with a language in which
> the language's semantics imposes a fixed deterministic order
> of evaluation upon implementors, but programs that depend on
> this order of evaluation are regarded as buggy?

Is depending upon order of evaluation a barrier to gun ownership?

> An approximation to this situation can be achieved by using
> an extremely arcane fixed order of evaluation, which is not
> defined except in the fine print of a codicil that no sane
> non-implementor would read, and by warning programmers that
> TO DEPEND UPON THE FIXED ORDER OF EVALUATION IS UNIVERSALLY
> REGARDED AS EXTREMELY BAD STYLE; PERPETRATORS OF THIS STYLE
> SHOULD BE DRAWN AND QUARTERED.

The people that argue in favor of a deterministic order of evaluation
generally use arguments that do not favor a *particular* order, but
rather argue that *any* specified order is better that none at all.

I suspect, though, that they are motivated solely out of a feeling of
distaste for leaving things unspecified rather than an objective
criterion.  I predict, therefore, that virtually *all* the proponents
of specifying an order have `left to right' in mind and will violently
object to any other specific order.  I also predict that they will
call this `natural' (as if progamming were a natural activity) and
`what people are used to' (as if Arabic numerals are uncommon in
programs).

So I propose that if the order is fixed, it should be this: number the
arguments from right to left starting with one (not zero), write the
numerals as English words and sort them lexicographically:

(f a)           => a, then f

(f a b)         => b, f, a

(f a b c)       => f, c, a, b

(f a b c d)     => f, a, d, b, c

(f a b c d e)   => a, b, e, f, c, d

(f a b c d e h) => b, c, h, f, a, d, e

Is this order better than leaving the order unspecified?  Is this
order worse than right to left?
0
jrm (1310)
10/7/2004 5:16:03 PM
Neelakantan Krishnaswami <neelk@cs.cmu.edu> writes:

> I think there are some pretty good theoretical reasons for this, too.
> If there is to be an isomorphism between the curried and uncurried
> forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
> strict setting, then you must have have left-to-right order of
> evaluation.

If you use left-to-right notation for currying in your math, then of
course it would be left-to-right.

>> Since examples such as (f (read) (read) (read)) are by far the exception,
>> rather than the rule, they could easily be dealt with by a convenient
>> special form.  
>
> No, this is literally the only source of order of evaluation bugs I've
> ever had. I mean, I can see the pragmatic case not to declare a fixed
> order -- it's not cool to declare solid, existing implementations
> non-conforming -- but I don't think there's any principled case
> against fixing the order of evaluation to left to right.

Is there a principled case against fixing the order right to left?
0
jrm (1310)
10/7/2004 5:19:22 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Hear, hear!  Isn't that *precisely* the argument in favor of static
> type systems?  Fewer programs are legal, so having a legal program
> carries more information.  (The difference, of course, is that static
> type systems are statically checkable, so the validity of the
> information can be verified and does not have to be taken on faith.)

So you'd be in favor of a language that required all identifiers to
have more than 20 characters each?  There would be fewer legal
programs (in the space of all strings), and it is statically checkable.
0
jrm (1310)
10/7/2004 5:21:05 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Hear, hear!  Isn't that *precisely* the argument in favor of static
> > type systems?  Fewer programs are legal, so having a legal program
> > carries more information.  (The difference, of course, is that static
> > type systems are statically checkable, so the validity of the
> > information can be verified and does not have to be taken on faith.)
> 
> So you'd be in favor of a language that required all identifiers to
> have more than 20 characters each?  There would be fewer legal
> programs (in the space of all strings), and it is statically checkable.

We usually consider programs equivalent if they are equal up to alpha
renaming, so there are equally many equivalence classes of correct
programs under the rule.  The rule just made id less convenient to
write correct instances.

But you have a point: I said that the "make fewer programs legal to
increase the information contained in legal programs" mantra is
suspect and needs to be taken with a huge grain of salt.  That grain
of salt, though, consists of more than "legality is checkable".
(Trivial extreme witness: "No program is correct" is checkable, too.)

Matthias
0
find19 (1244)
10/7/2004 5:27:22 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Joe Marshall <jrm@ccs.neu.edu> writes:
>>
>> Under unspecified order of evaluation, this program transform:
>> 
>> (foo <expression0> <expression1> <expression2>)
>> 
>>   <=> (let ((var <expression1>))
>>         (foo <expression0> var <expression2>))
>> 
>> is legal for all *correct* programs.  That is, no correct program will
>> become incorrect after making that transformation. 
>> 
>> Under L2R or R2L order of evaluation, that transform can break a
>> correct program.
>
> True.  But so what?  The fact you are getting at is /obvious/ because
> you rearranged the order of evaluation and order of evaluation matters
> in languages with effects.  The correct (and easy) fix is to write:
>
>    (let* ((var0 <expression0>)
>           (var1 <expression1>))
>       (foo var0 var1 <expression2>)))
>

I believe that the transform I wrote first is something that *many*
people have in their head as part of their intellectual tools for
understanding computer programs.  I believe the `easy fix' is not.
The reverse transform (from the LET to the flat expression) is rarely
encountered in the `easy fix' version, but rather common in the first.

> How about this one:
>
>   In the language definition, we summarily declare /every/ program
>   incorrect.  The huge "advantage" of doing so is that now /every/
>   program transformation on correct programs is correct.
>
> See?  It obviously does not make sense when taken to the extreme.  The
> remaining question is at which degree it stops making sense.  My claim
> is that it stops making sense very early on.

I don't often write programs in languages like that (although I
program in C++ on occasion).


0
jrm (1310)
10/7/2004 5:31:13 PM
In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> The people that argue in favor of a deterministic order of evaluation
> generally use arguments that do not favor a *particular* order, but
> rather argue that *any* specified order is better that none at all.

That's right.

> I suspect, though, that they are motivated solely out of a feeling of
> distaste for leaving things unspecified rather than an objective
> criterion.

That's wrong.

> I predict, therefore, that virtually *all* the proponents
> of specifying an order have `left to right' in mind and will violently
> object to any other specific order.

That does not follow.  There are objective arguments in favor of fixed 
OoE.  There are further, distinct objective arguments in favor of 
particular fixed OoE's over others.

> I also predict that they will
> call this `natural' (as if progamming were a natural activity) and
> `what people are used to' (as if Arabic numerals are uncommon in
> programs).

Perhaps.  So?

> So I propose that if the order is fixed, it should be this: number the
> arguments from right to left starting with one (not zero), write the
> numerals as English words and sort them lexicographically:
> 
> (f a)           => a, then f
> 
> (f a b)         => b, f, a
> 
> (f a b c)       => f, c, a, b
> 
> (f a b c d)     => f, a, d, b, c
> 
> (f a b c d e)   => a, b, e, f, c, d
> 
> (f a b c d e h) => b, c, h, f, a, d, e
> 
> Is this order better than leaving the order unspecified?

Yes.

> Is this order worse than right to left?

Of course.

rg
0
rNOSPAMon (1927)
10/7/2004 5:44:19 PM
"Joe Marshall" <jrm@ccs.neu.edu> wrote

> So I propose that if the order is fixed, it should be this: number the
> arguments from right to left starting with one (not zero), write the
> numerals as English words and sort them lexicographically:

I violently object to the cultural imperialism implicit in the choice of
English!
I propose either an extinct isolate, such as Etruscan, or a rare language
in dire need of revivial, such as the Khoisan group ;)

Andr�


0
email7695 (32)
10/7/2004 5:59:29 PM
In article <xa79d.6994$Vm1.1199@newsread3.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> Ron Garret wrote:
> > In article <_Kp8d.3634$Vm1.2292@newsread3.news.atl.earthlink.net>,
> >  "Anton van Straaten" <anton@appsolutions.com> wrote:
> >
> > > Ron Garret <rNOSPAMon@flownet.com> wrote:
> > > >
> > > > FWIW, here's my take on this.
> > > >
> > > > IMHO:
> > > >
> > > > 1) One of the central principles of good programming language design
> is
> > > > the principle of least surprise.
> > >
> > > Although it's often touted in informal contexts, that's a controversial
> > > principle, mainly because it's too vague.  You certainly won't find it
> in
> > > many semantics texts!
> >
> > I won't find it many physics texts either.  And your point would be...?
> 
> Let me come at that from the other direction.  Where can I read up on this
> principle, so that I can understand it as something other than a way to
> defend some of the quirkier features of scripting languages?

A Google search makes a good start.

> > > > 2) Most people are surprised when a single program in an ostensibly
> > > > deterministic language with no external interactions behaves in two
> > > > different ways on two different occasions.
> > >
> > > If that's not the expected behavior, then you're describing a buggy
> program.
> > > That's nothing to do with principle of least surprise - bugs happen,
> they
> > > get reported, and fixed.
> >
> > Do they?  How can I tell if I have a Scheme program whose semantics
> > depend on OoE?  If I have a Scheme program which accepts no input from
> > the outside and has worked correctly on 99 runs, how can I be sure it
> > will work correctly on the 100th run?
> 
> You can use an implementation with fixed evaluation order to be sure of
> that.  No-one (afaik) is suggesting that implementations should not be
> allowed to offer fixed evaluation order.  We're talking about the
> specification here.

That's right.  Under the specification it is impossible to know whether 
the behavior of a program is invariant with respect to the 
implementation it is running under except in certain special cases.  IMO 
that's a bad thing.

> > > > 3) Leaving order of evaluation unspecified in a language that also has
> > > > side effects makes such an occurrence all but inevitable.
> > >
> > > Having side effects at all makes an entire class of otherwise avoidable
> bugs
> > > inevitable, yet we still tolerate them for some reason, even in
> languages
> > > like SML/NJ.
> >
> > We tolerate side effects because they are useful.
> 
> You mean "we tolerate the bugs which side effects cause because side effects
> are useful."

That's right.

> The exact same argument applies to having the ability to
> specify a distinction between code that depends on order of evaluation, and
> code which does not.

Perhaps, but that's a red herring.  No one is arguing against the 
ability to specify such a distinction.  The argument is over *how* that 
distinction is specified.  I have no problem with leaving the OoE of LET 
clauses unspecified.

> > The whole point of
> > having high level programming languages at all is to create a better
> > "impedance match" between the kinds of information that computers
> > process and the kinds of information human brains process.  If we could
> > rely on programmers to follow conventions, recognize errors, RTFM, etc.
> > there would be no utility to high level languages at all.  But they
> > don't, so there is.  And for some reason, most people find it easier to
> > think in terms of side effects when they sit down to solve certain
> > classes of problems.  That's just the way that the human brain seems to
> > be wired.
> 
> Oy.  I think this belongs in c.l.l.

Really?  Why?  Do you believe that Scheme is just a mathematical toy and 
should not be used for real world applications?

> > [Off-topic rant: I have mostly stayed out of the Bill Richter wars,
> > except to celebrate his temporary departure and quietly lament his
> > return.  The main reason I find everything Bill writes to be utterly
> > irrelevant is that I reject his central tacit premise, that mathematics
> > has value above all else in CS.  It doesn't.  The study of programming
> > languages has as much to do with psychology, economics, and politics as
> > it does with math, a fact that lamentably few of its practitioners seem
> > to recognize.]
> 
> I agree that human factors are very important.

Then why do you want to banish me to c.l.l. just because I brought them 
up?

> In fact, the human factors
> are central to this issue.  The argument against "ambiguous semantics" is
> primarily a semantic argument, not a human factors argument, and the
> argument goes "we must restrict the language's expressivity in order to make
> it tractable".

No, at least that's not my argument.  My argument is that it would be 
beneficial to restrict the semantics of any language, not to make it 
tractable, but to make function calls deterministic.

> But that's theoreticaly tractability, not practical
> tractability.  The argument can and has been made that fixed evaluation
> order is less tractable in practice, because it leads to the masking of
> fragile unintended order dependence.

Maybe I don't understand what you mean by "tractable".  Fixed OoE 
doesn't mask unintended order dependence, it eliminates it.

> > > > (call-with-arguments-evaluated-in-any-order thunk . argforms)
> > > >
> > > > which could, of course, have suitable abbreviations.
> > >
> > > Syntax like that would dominate any normal program, even an imperative
> one.
> >
> > I doubt that very much.
> 
> Of course it would.  See below.

It occurred to me that call-with-arguments-evaluated-in-any-order is 
unnecessary.  LET suffices.

> > > Even in traditional imperative languages, most function call argument
> lists
> > > and most expressions don't depend on order of evaluation.  The software
> > > world would be in far worse shape if that weren't the case.
> >
> > It is true that most expressions etc. don't depend on OoE, but that is
> > simply a mathematical fact, and so it is nonsensical to speculate what
> > the consequences would be if it weren't true.  What we are talking about
> > is how to treat those cases where it *does* (or might) matter.
> >
> > (This is a rather crucial point, and I am beginning to wonder if those
> > who support unspecified OoE have simply missed it.)
> 
> The cases where it might matter include every function call whose argument
> list itself contains a function call.

No.  The cases where it might matter includes ONLY those function calls 
whose argument list contains MORE THAN ONE function call, at least one 
of which has side effects.

> My point was just that compiler optimizations are a secondary part of the
> picture, which follow from having the ability in code to specify the
> distinction between code that's order dependent and code that isn't.  Having
> the compiler be aware of some subset of order independent code "even if OoE
> were specified" doesn't address any of my concerns.

Fine.  Use LET for code where OoE doesn't matter.

> > > In any case, none of these speculative possibilities addresses the
> question
> > > asked by the OP, "Is there any utility to the order of evaluation being
> > > unspecified?"  My response to that was that the answer is yes, there is
> > > utility in it, although opinions differ as to exactly how much.  The
> > > responses I've received so far merely underscore my answer.  :)
> >
> > I do not dispute that there is utility in having an unspecified OoE.
> > What I am arguing against is making this the case by default.
> 
> That makes littel sense, given usage patterns in actual programs, including
> imperative ones, and especially in a language in which everything other than
> a macro/special form is a function call.

That made no sense to me at all.

rg
0
rNOSPAMon (1927)
10/7/2004 6:01:20 PM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
>
> > The convention loses significant value if it's not universally followed.
>
> It isn't now.

It is by all Scheme programs that attempt to be portable between
implementations.  It's only not followed by people who have picked, and plan
to stick to, a specific implementation or subset of implementations.
They're free to do that.  However, we're talking about what the standard
mandates, or doesn't mandate, for all implementations.

> > However, good techniques seem in short supply.
>
> Nonsense.  As I just wrote in a separate article, I can think of many
> good ways of encoding this information.  The fact that it hasn't been
> done already is an indication that the problem might not be so
> important after all.
>
> (Also, remember that the "technique" currently applied is particularly
> bad.)

This is a case of "a bird in the hand is worth two in the bush".  See below.

> > What alternative ways of encoding this
> > information do you suggest?  Keep in mind that suggesting future
> > possibilities doesn't actually address the issue today, and that Scheme
> > currently does succeed in enforcing it in a way which some people find
> > satisfactory, if not ideal.
>
> Oh, so we are supposed to come up with alternatives, but the
> alternatives aren't allowed to change the languages in question in any
> way?  We must come up with an encoding of a certain type of
> information in such a way that all existing programs already correctly
> use that encoding?

No to both.  What I'm saying is that waving your hands at possible future
ways of encoding the information doesn't then make it OK to remove the
current ability to express this distinction in the language.

However, I note that your latter two questions would be satisfied by Will
Clinger's suggested solution.

Anton


0
anton58 (1240)
10/7/2004 6:12:25 PM
In article <3q69d.6979$Vm1.1407@newsread3.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> The problem with the opposing positions here tends to be that even when they
> acknowledge any value in the ability to specify order independence, they all
> seem to take the basic stance that this ability is worth sacrificing, in
> exchange for unambiguous semantics.  No-one should be surprised that there's
> opposition to this idea.  It offers unambiguous semantics only for a less
> expressive language, a language that cannot express certain properties of
> the programs written in it.

Nonsense.  All we're arguing over is whether

(f (g) (h))

ought to mean:

(let ( (x (g))
       (y (h)) )
  (f x y))

or

(let* ( (x (g))
        (y (h)) )
  (f x y))

The expressiveness of the language is the same in either case.

The debate is really over who gets the more convenient syntax, those who 
want LET semantics or those who want LET* semantics.

The central issue is that if you're not sure whether you want LET or 
LET* then it is always safe to use LET*, in the sense that there can be 
no negative consequences of using LET* that you might not possibly have 
also obtained if you chose to use LET instead.  Contrariwise, it is 
dangerous to use LET if you really need LET* because, while LET might 
give you the correct results (because it might do the same thing as 
LET*), it also might not.

The debate is: in those cases where programmers are lazy and don't think 
hard enough about whether they really need LET*, should they be *forced* 
to think hard about this by making the more dangerous case the default?  
IMO the answer is no.

But expressiveness has nothing whatever to do with it.  This is simply a 
turf battle between LET and LET* over the syntactic sugar of nested 
function calls.

rg
0
rNOSPAMon (1927)
10/7/2004 6:19:30 PM
Neelakantan Krishnaswami wrote:
> In article <3q69d.6979$Vm1.1407@newsread3.news.atl.earthlink.net>,
> Anton van Straaten wrote:
> >
> > Some people complain that such an assertion is not statically checkable,
> > and even dynamic checkability is harder than usual to come by.  However,
> > we don't usually check types statically in Scheme, either; and in
practice,
> > experience in Scheme, C, C++, and OCaml indicates that the issues
> > resulting from unspecified evaluation order are certainly no more
problematic
> > than those that arise from unintentional order dependencies in language
> > with fixed evaluation order (and arguably, less so).  That's because
> > evaluation order issues can occur in any language with side effects,
> > regardless of the language's specified evaluation order.
>
> That's not my experience. Every single order-of-evaluation-related bug
> that I have ever had in a strict language has arisen when evaluation
> was not left to right. (Not just in Scheme, but in Ocaml, too.) If you
> fixed order of evaluation to left to right, I would never have ever
> even seen a single instance of this kind of error.

I've encounted counter-examples in Java.  Another two points here are that
(1) a useful fixed order makes certain kinds of refactoring into much more
of a minefield than it needs to be; related to this, (2) a useful fixed
order can hide order dependencies that aren't obvious even to the original
programmer - basically, allowing a deficient mental model of the program's
operation to seem correct.  That could be useful in a language like Java,
but it's not necessarily universally desirable.

> I think there are some pretty good theoretical reasons for this, too.
> If there is to be an isomorphism between the curried and uncurried
> forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
> strict setting, then you must have have left-to-right order of
> evaluation.

That's a nice point to which I'll have to give some thought.

> > Since examples such as (f (read) (read) (read)) are by far the
exception,
> > rather than the rule, they could easily be dealt with by a convenient
> > special form.
>
> No, this is literally the only source of order of evaluation bugs I've
> ever had. I mean, I can see the pragmatic case not to declare a fixed
> order -- it's not cool to declare solid, existing implementations
> non-conforming -- but I don't think there's any principled case
> against fixing the order of evaluation to left to right.

There would be no case against it if there were some other standardized way
of encoding the distinction between code which depends on a particular
evaluation order, and code which doesn't.  In the absence of that, there's a
principled case.

In fact, aside from your currying equivalence point above, the *principled*
case on the other side seems hard to divine: so far, it's seemed limited to
minimizing the value of the ability to encode an order distinction, and
maximizing the undesirability of having an unspecified order in a
specification.  These two claims are mutually dependent, i.e. the latter is
assumed to outweigh the former.  That's little more than an argument from
differing perspectives.

Anton


0
anton58 (1240)
10/7/2004 6:43:34 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> Matthias Blume wrote:
> > "Anton van Straaten" <anton@appsolutions.com> writes:
> >
> > > The convention loses significant value if it's not universally followed.
> >
> > It isn't now.
> 
> It is by all Scheme programs that attempt to be portable between
> implementations.  It's only not followed by people who have picked, and plan
> to stick to, a specific implementation or subset of implementations.

.... or by people who just didn't get it right or who weren't even
aware of the problem.

Now, you may say that other methods suffer from the same problem: if I
write a comment or a pragma that says "order-independent", I might get
that wrong, too.  Sure.  But at least it did not gratuituously make
the behavior of the program unpredictable across different compilers,
machines, and phases of the moon.

There are two pieces of information here: (1) what the current program
is supposed to do, and (2) how the program can be modified without
losing (1).  You suggest that it is a good idea to link these together
so that getting (2) wrong also makes (1) wrong -- sort of as an
incentive to people to make sure they work hard to get (2) right.  I
think this sort of linking is a very bad idea.  The first priority is
on getting (1) right -- because (2) is meaningless without (1). If you
want to get people to get (2) right as well, you should provide a way
of stating (2) such that it can be rigorously verified. Otherwise it
is just an extra, unnecessary hurdle with respect to (1) and,
therefore, jeopardizes both (1) and (2).

> > (Also, remember that the "technique" currently applied is particularly
> > bad.)
> 
> This is a case of "a bird in the hand is worth two in the bush".  See below.

No.  What you hold in your hand is not a bird.  (I won't say what it
is, but I recommend dropping it as quickly as you can. :-)

Matthias
0
find19 (1244)
10/7/2004 6:49:38 PM
Thant Tessman wrote:
> Anton van Straaten wrote:
>
> > [...] The argument against "ambiguous semantics" is
> > primarily a semantic argument, not a human factors argument, and the
> > argument goes "we must restrict the language's expressivity in order to
make
> > it tractable".
>
> No. The argument is that leaving argument OofE unspecified does nothing
> to make the language more expressive.

You must be working off a different definition of expressive.  I assume
you're thinking only of the behavior of the program, and not of what the
code expresses to human readers, or to tools.  If you've ever worked in
commercial programming, as I believe you have, you should know that there's
much more to a program than its behavior when it runs.

The difference in expressivity is easily demonstrable: for example, it
allows compilers to use different strategies when compiling.  It similarly
allows different approaches to refactoring.

You've previously said, repeatedly, things like "There is no information
lost by fixing argument order of evaluation."  If you truly believe that,
then I'd doubt you'd be capable of making it past the fourth paragraph of
this page: http://www-2.cs.cmu.edu/~dst/Tutorials/Info-Theory/ .

However, what's more likely is that you're quibbling that it could still be
assumed to be bad style to depend on OofE even in the presence of a fixed
order, or something along those lines (your brief categorical denials of
fact leave your actual beliefs obscure).  Here, the argument is a human
factors one: unless tools enforce the distinction somehow, any ability to
distinguish the two types of code will be effectively lost.  Right now,
Scheme implementations do enforce this distinction on portable Scheme code.

> > [...] But that's theoreticaly tractability, not practical
> > tractability.  The argument can and has been made that fixed evaluation
> > order is less tractable in practice, because it leads to the masking of
> > fragile unintended order dependence.
>
> Except that no one has successfully argued how leaving OofE unspecified
> makes this less likely to happen. Any OofE rearrangement test is equally
> effective in either situation. The only difference is that in the case
> of a language with fixed OofE, it's possible that in some situations,
> you're merely a style cop, and not a bug hunter.

You can't even be a style cop, unless there's widespread agreement on style.
And note, as I've said, that the point here is not to be a style cop - it's
to support the expression of a distinction between two different types of
code.  That does tend to require some kind of enforcement, however.

> > The problem with the opposing positions here tends to be that even when
they
> > acknowledge any value in the ability to specify order independence, they
all
> > seem to take the basic stance that this ability is worth sacrificing, in
> > exchange for unambiguous semantics.
>
> Again, no. I'm running out of ways to describe how silly this sounds.

You haven't even done so once.  Instead, you've denied factual points which
even other people on your side of the discussion acknowledge to be true.

> The goal is to write code that avoids imperative style as much as
> practical. A side-effect (er, so to speak) of the persuit of that goal
> is that the order of argument evaluation becomes irrelevant. It does not
> follow that decreeing OofE irrelevant will automatically make code less
> imperative.

No-one has claimed that.

Anton


0
anton58 (1240)
10/7/2004 6:53:33 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> Right now, Scheme implementations do enforce this distinction on
> portable Scheme code.

I don't know what definition of "expressive" Thant runs on, but Anton
seem to be running on a strange definition of "to enforce".

Matthias
0
find19 (1244)
10/7/2004 6:58:28 PM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
> > [The convention is followed] by all Scheme programs that attempt
> > to be portable between implementations.  It's only not followed
> > by people who have picked, and plan to stick to, a specific
> > implementation or subset of implementations.
>
> ... or by people who just didn't get it right or who weren't even
> aware of the problem.
>
> Now, you may say that other methods suffer from the same problem: if I
> write a comment or a pragma that says "order-independent", I might get
> that wrong, too.  Sure.  But at least it did not gratuituously make
> the behavior of the program unpredictable across different compilers,
> machines, and phases of the moon.

IOW, you don't like the enforcement mechanism, and I've agreed it's not
ideal.  However, I can tell you that in practice, it works.  You've argued
that this issue isn't important enough to warrant the development of a
better solution - that may be true, but the current "solution" is very
economic.

> There are two pieces of information here: (1) what the current program
> is supposed to do, and (2) how the program can be modified without
> losing (1).  You suggest that it is a good idea to link these together
> so that getting (2) wrong also makes (1) wrong -- sort of as an
> incentive to people to make sure they work hard to get (2) right.  I
> think this sort of linking is a very bad idea.

I agree it's a bad idea.  I'd be happy to support a better one.  That's why
I've agreed with Will Clinger's suggestion.

> The first priority is
> on getting (1) right -- because (2) is meaningless without (1). If you
> want to get people to get (2) right as well, you should provide a way
> of stating (2) such that it can be rigorously verified. Otherwise it
> is just an extra, unnecessary hurdle with respect to (1) and,
> therefore, jeopardizes both (1) and (2).

This ignores the effects of order dependencies in languages that aren't
capable of expressing a distinction.  Those jeopardize (1) also, for example
by lending credence to incorrect mental models of a program's behavior.

> > > (Also, remember that the "technique" currently applied is particularly
> > > bad.)
> >
> > This is a case of "a bird in the hand is worth two in the bush".  See
below.
>
> No.  What you hold in your hand is not a bird.  (I won't say what it
> is, but I recommend dropping it as quickly as you can. :-)

I work in the commercial sector.  Believe me, I've held much worse things in
my hands.  Sometimes, I have to swim in it.

Anton


0
anton58 (1240)
10/7/2004 7:08:14 PM
In article <u0t6saxx.fsf@ccs.neu.edu>, Joe Marshall wrote:
> Neelakantan Krishnaswami <neelk@cs.cmu.edu> writes:
> 
>> I think there are some pretty good theoretical reasons for this, too.
>> If there is to be an isomorphism between the curried and uncurried
>> forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
>> strict setting, then you must have have left-to-right order of
>> evaluation.
> 
> If you use left-to-right notation for currying in your math, then of
> course it would be left-to-right. [...] Is there a principled case
> against fixing the order right to left?

Ah, I see what you mean. I want

  ((lambda (x y) body) e1 e2)

and 

  (((lambda (x) (lambda (y) body)) e1) e2)

to be equivalent to one another. This will hold only under either a
left-to-right OR right-to-left order (and only those two orders).

The reason I break in favor of left-to-right is that all of my order
of evaluation bugs, without even a single exception, have arisen
because the evaluation order was right to left when I expected left to
right. A less important reason is that all of the operational
semantics I've seen in the literature do left-to-right evaluation, and
it's nice when implementation and theory are as much in sync as
possible.

-- 
Neel Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
10/7/2004 7:14:34 PM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
>
> > [ ... ]but rather that the ability to communicate order of evaluation
> > dependency distinctions in code becomes lost, if there is no
> > "enforcement" mechanism whatsoever.
>
> But in practice there currently is no enforcement mechanism.

I disagree.  There's a huge bogeyman for code that is intended to be
portable - the very fact that you think it's so bad is, in an admittedly
twisted sense, part of its usefulness.  Anyone writing portable code has to
pay attention to this, even if they're not always testing for violations.
Take away the bogeyman, without replacing it somehow, and you take away any
reason to pay attention to the issue, other than personal choice.

> That's my whole point: establishing that I did not violate the
> rules is too difficult in general.  That's why the rules are bad.

It's really not as difficult as you make out.  It's done all the time by
programmers in C and C++.  I occasionally move code between SISC and PLT,
which have opposite evalution orders.  I've never encountered a problem
doing that, which makes me pretty confident that I'm not violating the
rules.  It's not a semantic certainty, but the same is true of all sorts of
other properties of programs that are difficult to check.  The difficulty of
checking doesn't stop us from trying to write bug-free programs.

Anton


0
anton58 (1240)
10/7/2004 7:46:02 PM
Ron Garret <rNOSPAMon@flownet.com> writes:
> In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> > Is this order better than leaving the order unspecified?
> 
> Yes.

No. It is confusing as hell, and so it is better not to have to think about
it.

A *simple* order is best. 

Left-to-right is arguably best for the programmer.

Right-to-left could be arguably better for compiler writers on most machines.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/7/2004 8:02:52 PM
Ron Garret <rNOSPAMon@flownet.com> writes:
> Fine.  Use LET for code where OoE doesn't matter.

But then you cannot implement LET in terms of lambda, since OoE for lambda
will be specified.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/7/2004 8:10:25 PM
Andre <andre@het.brown.edu> wrote in message news:<4165578C.E6078880@het.brown.edu>...
> Neelakantan Krishnaswami wrote:
> 
> > I think there are some pretty good theoretical reasons for this, too.
> > If there is to be an isomorphism between the curried and uncurried
> > forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
> > strict setting, then you must have have left-to-right order of
> > evaluation.
> 
> That is actually a very solid reason.  I can feel myself being swayed.

No, this is *egregiously* wrong!  Curried function applications and
uncurried function applications are _no_different_ with respect to
order of evaluation issues; there is a minor distinguishing property:
with curried function applications, each node in the tree of evaluation
of combination components has exactly two children (the function & the
argument), whereas with uncurried function it has N+1, where N is the
number of arguments.  Or, in clearer terms: with curried applications,
the question is 'do you evaluate the function or the argument first?'
while with uncurried applications, the question is 'which of the list
of arguments or function do you evaluate first?'  There is no solid
theoretical reasoning that points to left-to-right on the grounds of
curried application.  It could equally well be right-to-left, if you
evaluate the argument first, rather than the curried function; it could
even just as well be left unspecified as to whether curried function or
argument be evaluated first.

> > > Since examples such as (f (read) (read) (read)) are by far the exception,
> > > rather than the rule, they could easily be dealt with by a convenient
> > > special form.
> > 
> > No, this is literally the only source of order of evaluation bugs I've
> > ever had. I mean, I can see the pragmatic case not to declare a fixed
> > order -- it's not cool to declare solid, existing implementations
> > non-conforming -- but I don't think there's any principled case
> > against fixing the order of evaluation to left to right.

The most concrete example in this thread that I've seen, explained by
Joe Marshall (and _also_, _independently_, given by Jorgen Schaefer on
another medium) was a bug introduced by permuting an _undocumented_
dependency on the order of evaluation.  Because an argument list, even
with a fixed order, contains no information about what _actually_
depends on what, you just don't know if permuting it is OK.  By using
LET* explicitly, you make it explicit what depends on what.  This, to
me, expresses a very strong principled argument against fixing the OoE.

> I can contribute a (somewhat esoteric) bug that I have had
> in the context of the Filinski encoding of monads in Scheme.
> See the thread
> 
>  http://groups.google.com/groups?selm=403B9327.A03773D9%40het.brown.edu
> 
> where the following expression in the list monad
> 
>    (reify (cons (reflect '(1 2)) 
>                 (reflect '(5 6))) 
> 
> would not give the correctly ordered answer.

What _is_ the 'correctly ordered answer?'  Is not the list monad also
known as the _non-determinism_ monad?
0
campbell1 (74)
10/7/2004 8:13:46 PM
Anton van Straaten wrote:
> Thant Tessman wrote:
> 
>>Anton van Straaten wrote:
>>
>>
>>>[...] The argument against "ambiguous semantics" is
>>>primarily a semantic argument, not a human factors argument, and the
>>>argument goes "we must restrict the language's expressivity in order to
> 
> make
> 
>>>it tractable".
>>
>>No. The argument is that leaving argument OofE unspecified does nothing
>>to make the language more expressive.
> 
> 
> You must be working off a different definition of expressive.  I assume
> you're thinking only of the behavior of the program, and not of what the
> code expresses to human readers, or to tools. [...]

I'm actually thinking of both, and thought I'd made that point several 
times by now. You claim the use of a function call implies the 
programmer  is consciously communicating their intention that the 
arguments are evaluation-order independent. As far as I know, I've never 
written code that was argument-order dependent. Yet I've *never* assumed 
that the use of a function call communicated this fact about my code. I 
honestly don't think there are more than two or three of you out there 
who do. And while I think there is no language that surpasses Scheme in 
the number of opportunities it provides to refactor code, I've *never* 
relied on what unspecified OofE implies about the code to do so.


> You've previously said, repeatedly, things like "There is no information
> lost by fixing argument order of evaluation."  If you truly believe that,
> then I'd doubt you'd be capable of making it past the fourth paragraph of
> this page: http://www-2.cs.cmu.edu/~dst/Tutorials/Info-Theory/ .

What information is lost? The only information lost is the fact that you 
can reorder argument evaluation without changing the meaning of a 
program *assuming* the code is correct--where "correct" in this 
situation means that you can reorder argument evaluation without 
changing the meaning of a program. The situation doesn't change *at all* 
under fixed OofE except that they stop using the word 
"correct"--possibly replacing it with "good style."

Opportunities for optimization are lost (again, assuming a "correct" 
program--and "correct" in a way the compiler can't determine for itself, 
but in a way that a human has--to the degree a human can), but that's a 
different argument.

[...]

>>The goal is to write code that avoids imperative style as much as
>>practical. A side-effect (er, so to speak) of the persuit of that goal
>>is that the order of argument evaluation becomes irrelevant. It does not
>>follow that decreeing OofE irrelevant will automatically make code less
>>imperative.
> 
> 
> No-one has claimed that.

What I meant to say was: "It does not follow that decreeing OofE 
irrelevant is an effective way to encourage a less-imperative 
programming style. My point is that you're trying to cure the disease by 
outlawing the symptoms.

-thant


0
thant (332)
10/7/2004 8:21:49 PM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> In article <3q69d.6979$Vm1.1407@newsread3.news.atl.earthlink.net>,
>  "Anton van Straaten" <anton@appsolutions.com> wrote:
>
> > The problem with the opposing positions here tends to be that even when
they
> > acknowledge any value in the ability to specify order independence, they
all
> > seem to take the basic stance that this ability is worth sacrificing, in
> > exchange for unambiguous semantics.  No-one should be surprised that
there's
> > opposition to this idea.  It offers unambiguous semantics only for a
less
> > expressive language, a language that cannot express certain properties
of
> > the programs written in it.
>
> Nonsense.  All we're arguing over is whether
>
> (f (g) (h))
>
> ought to mean:
>
> (let ( (x (g))
>        (y (h)) )
>   (f x y))
>
> or
>
> (let* ( (x (g))
>         (y (h)) )
>   (f x y))
>
> The expressiveness of the language is the same in either case.

That's only true if some other feature is added to the language to
reintroduce the ability to express code with an unspecified evaluation
order, since proponents of fixed order want (or even need) to fix LET, too.

You've suggested adding such a feature, in which case I agree, the argument
comes down to how to do that, and possibly which default makes more sense.
That's not the argument that's being had in most of the rest of the thread,
though, and I'm sorry for confusing the two.

A feature which requires every function call to be annotated for order
independence doesn't satisfy the requirements I'm concerned with.  It would
have to be something like a pragma, which works at least at the level of
compilation units or similar.  It would need to be explictly written in
code, not e.g. via command line switches, since it needs to be tightly
coupled with the code to which it applies.  Such a feature would have to be
clearly defined in the standard.

> But expressiveness has nothing whatever to do with it.  This is simply a
> turf battle between LET and LET* over the syntactic sugar of nested
> function calls.

Again, that would be true if there were concrete proposals on the table for
reintroducing the ability to express code with unspecified evaluation order
(or code which is asserted to be free of order dependencies), and if those
who want to fix evaluation order were in favor of agreeing on such a
proposal.  It's not clear to me what many of the others on the
useful-fixed-order side of the debate think in this respect - many seem
quite happy with the idea of simply fixing a useful evaluation order in the
standard, and ignoring the surrounding issues.

Anton


0
anton58 (1240)
10/7/2004 8:26:29 PM
Joe Marshall wrote:

> I suspect, though, that they are motivated solely out of a feeling of
> distaste for leaving things unspecified rather than an objective
> criterion.  I predict, therefore, that virtually *all* the proponents
> of specifying an order have `left to right' in mind and will violently
> object to any other specific order.  I also predict that they will
> call this `natural' (as if progamming were a natural activity) and
> `what people are used to' (as if Arabic numerals are uncommon in
> programs).

In many languages, left to right is natural. In some arabic languages, 
right to left would be natural. In Japanese, top to bottom would be natural.

I think this could be turned into a pattern, similar to 
http://c2.com/cgi/wiki?LocalVariablesReassignedAboveTheirUses - the left 
to right rule is, in fact, mentioned in 
http://c2.com/cgi/wiki?SimplyUnderstoodCode


Pascal

-- 
Tyler: "How's that working out for you?"
Jack: "Great."
Tyler: "Keep it up, then."
0
costanza (1427)
10/7/2004 8:32:48 PM
"Display Name" <email@somwhere.com> writes:

> "Joe Marshall" <jrm@ccs.neu.edu> wrote
>
>> So I propose that if the order is fixed, it should be this: number the
>> arguments from right to left starting with one (not zero), write the
>> numerals as English words and sort them lexicographically:
>
> I violently object to the cultural imperialism implicit in the choice of
> English!

I knew someone would.

> I propose either an extinct isolate, such as Etruscan, or a rare language
> in dire need of revivial, such as the Khoisan group ;)

Etruscan sounds good.  Khoisan would be better for side-effects.
0
jrm (1310)
10/7/2004 8:37:45 PM
Taylor Campbell wrote:
> 
> Andre <andre@het.brown.edu> wrote in message news:<4165578C.E6078880@het.brown.edu>...
> > Neelakantan Krishnaswami wrote:
> >
> > > I think there are some pretty good theoretical reasons for this, too.
> > > If there is to be an isomorphism between the curried and uncurried
> > > forms of functions (ie, (A x B) -> C and A -> B -> C) in an impure,
> > > strict setting, then you must have have left-to-right order of
> > > evaluation.
> >
> > That is actually a very solid reason.  I can feel myself being swayed.
> 
> No, this is *egregiously* wrong!  Curried function applications and
> uncurried function applications are _no_different_ with respect to
> order of evaluation issues; 

You are right, of course (as Neel Krishnaswami explained in 
his follow-up also).  

> > where the following expression in the list monad
> >
> >    (reify (cons (reflect '(1 2))
> >                 (reflect '(5 6)))
> >
> > would not give the correctly ordered answer.
> 
> What _is_ the 'correctly ordered answer?'  Is not the list monad also
> known as the _non-determinism_ monad?

No.  One is commutative (lists are ordered) and the other isn't.  
Actually, with nondeterministic OoE, my wording that the above 
expression was "in" the list monad was misleading (although hopefully
it was clear from the rest that I considered it a _buggy_ or 
meaningless expression in this context).  
As you noticed, it would be a correct expression if the monad 
in question was indeed the nondeterminism monad.  

Regards
Andre
0
andre9567 (120)
10/7/2004 8:42:30 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> wrote:
>
>> The people that argue in favor of a deterministic order of evaluation
>> generally use arguments that do not favor a *particular* order, but
>> rather argue that *any* specified order is better that none at all.
>
> That's right.
>
>> I suspect, though, that they are motivated solely out of a feeling of
>> distaste for leaving things unspecified rather than an objective
>> criterion.
>
> That's wrong.

I'll suspect that *others* have this motivation, then.  I'll do it on
a case-by-case basis.

>> I predict, therefore, that virtually *all* the proponents
>> of specifying an order have `left to right' in mind and will violently
>> object to any other specific order.
>
> That does not follow.  There are objective arguments in favor of fixed 
> OoE.  There are further, distinct objective arguments in favor of 
> particular fixed OoE's over others.

Let's hear them!

>> I also predict that they will
>> call this `natural' (as if progamming were a natural activity) and
>> `what people are used to' (as if Arabic numerals are uncommon in
>> programs).
>
> Perhaps.  So?

Arguments based on `natural' order are specious.

>> So I propose that if the order is fixed, it should be this: number the
>> arguments from right to left starting with one (not zero), write the
>> numerals as English words and sort them lexicographically:
>> 
>> (f a)           => a, then f
>> 
>> (f a b)         => b, f, a
>> 
>> (f a b c)       => f, c, a, b
>> 
>> (f a b c d)     => f, a, d, b, c
>> 
>> (f a b c d e)   => a, b, e, f, c, d
>> 
>> (f a b c d e h) => b, c, h, f, a, d, e
>> 
>> Is this order better than leaving the order unspecified?
>
> Yes.
>
>> Is this order worse than right to left?
>
> Of course.

Why?
0
jrm (1310)
10/7/2004 8:44:46 PM
"Anton van Straaten" <anton@appsolutions.com> schreef in bericht
news:_1h9d.10994
> It's really not as difficult as you make out.  It's done all the time by
> programmers in C and C++.  I occasionally move code between SISC and PLT,
> which have opposite evalution orders.  I've never encountered a problem
> doing that, which makes me pretty confident that I'm not violating the
> rules.  It's not a semantic certainty, but the same is true of all sorts
of
> other properties of programs that are difficult to check.  The difficulty
of
> checking doesn't stop us from trying to write bug-free programs.

A related question which perhaps somebody here might be able to answer:
How much does the unspecified order of evaluation actually help in
compilation?
Would a fixed left-to-right order give a factor 1.01
or  a factor 10 increase in runtime? Would there be any fixed order
clearly more efficient from an implementation point of view?

Thanks,

Stephan


0
10/7/2004 8:45:18 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Ron Garret <rNOSPAMon@flownet.com> writes:
>> In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
>> > Is this order better than leaving the order unspecified?
>> 
>> Yes.
>
> No. It is confusing as hell, and so it is better not to have to think about
> it.

Why does that matter?  I thought the bug we were trying to solve was
that unspecified order of evaluation causes non-portability.  This
solves that problem.

Since no one here actually intends to *rely* on the order, who cares
what that order is?  Or do you intend to rely on it?
0
jrm (1310)
10/7/2004 8:46:22 PM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
>
> > The problem with the opposing positions here tends to be that even
> > when they acknowledge any value in the ability to specify order
> > independence, they all seem to take the basic stance that this
> > ability is worth sacrificing, in exchange for unambiguous semantics.
> > No-one should be surprised that there's opposition to this idea.
> > It offers unambiguous semantics only for a less expressive language,
> > a language that cannot express certain properties of the programs
> > written in it.
>
> Hear, hear!  Isn't that *precisely* the argument in favor of static
> type systems?

Yes, I believe I've mentioned that before.  So we're agreed, then?
Evaluation order will be fixed in Scheme right around the time it gets a
static type system?  :oP

> > Suggest a credible alternative to this, and I'm sure everyone will
listen.
>
> The alternative is to express this information some other way -- as
> pragma annotations or something similar.  Such a solution does not
> compromise the semantics but can still give hints to programmers and
> lint tools.

I'm in favor of that, but it needs to be done in a Cold War-style "bridge
exchange".  (Our respective prisoners will begin walking towards each other
at the same time from opposite sides of the bridge.)

IOW, a *useful* order shouldn't be fixed in Scheme without providing an
acceptable way to express order independence (where "acceptable" means,
among other things, "not on every function annotation").

> > Otherwise, we're left fighting over whose preferences might get stomped
on
> > in a future standard, which makes for a lot of heat, and unusually
little
> > light.
>
> Ok, just to make sure you realize that I do understand the issue, let
> me put this whole thing a bit more formally:

I do realize that you understand the issue, and I appreciate it.

> Consider some programs p, p1, p2, ... and a correctness criterion C.

Thanks.  Saved for closer reading later today.

> > SML made a number of other pragmatic choices: things like LET being
> > equivalent to Scheme's LET*, for example.
>
> False.

Oh well, the usual story.  :)

> SML's "let" can express both Scheme's "let" and Scheme's "let*"
> (ignoring order-of-evaluation guarantees):
>
>    let val x = ...                      works like Scheme's let*
>        val y = ...
>
>
>    let val x = ...                      works like Scheme's let
>        and y = ...
>
> Although this has nothing to do with the argument at hand, incorrect
> claims like this do not reflect well on your reasoning and might be
> construed as evidence for a blind, uncritical bias towards the way
> Scheme does things right now.

I don't think it should be my reasoning that is poorly reflected on, but
rather my knowledge, in this case of SML.  I've used the LET...AND form in
SML programs, so my claim was a lapse due to too-infrequent use.  I do
appreciate your patience in correcting me whenever I mention SML.  ;)

However, this does go to a point at issue, which is that I haven't seen any
proposals for Scheme that offer the SML feature you've just described.  My
primary goal in what this discussion has evolved to is to remind the people
who seem to believe that nothing is lost by simply changing R5RS to fix a
useful evaluation order, that without a more complete and considered
proposal, they're wrong.  :)

Anton


0
anton58 (1240)
10/7/2004 8:50:22 PM
Matthias Blume wrote:
> "Anton van Straaten" <anton@appsolutions.com> writes:
>
> > Right now, Scheme implementations do enforce this distinction on
> > portable Scheme code.
>
> I don't know what definition of "expressive" Thant runs on, but Anton
> seem to be running on a strange definition of "to enforce".

You're right, mea culpa, although I've explained my position on this in
another reply to you, in which I mention bogeymen.

Anton


0
anton58 (1240)
10/7/2004 8:52:33 PM
Joe Marshall wrote:
> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> 
>> [...] There are objective arguments in favor of fixed 
>>OoE.  There are further, distinct objective arguments in favor of 
>>particular fixed OoE's over others.
> 
> Let's hear them!

It is always good to make it easier to understand what a program does 
independent of the tastes and skills of the programmer who wrote it.

-thant

0
thant (332)
10/7/2004 9:01:35 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>> Ron Garret <rNOSPAMon@flownet.com> writes:
>>
>>> [...] There are objective arguments in favor of fixed OoE.  There
>>> are further, distinct objective arguments in favor of particular
>>> fixed OoE's over others.
>> Let's hear them!
>
> It is always good to make it easier to understand what a program does
> independent of the tastes and skills of the programmer who wrote it.

Unspecified order:
  Assuming a correct program, this implies that the program does not
  depend upon argument order.

Specified order:
  Assuming a correct program, this says nothing about whether the
  program depends upon argument order.

So by specifying the order of evaluation, we introduce ambiguity:  was
the intent of the programmer to depend upon the order?  It is
therefore *harder* to understand.

 
0
jrm (1310)
10/7/2004 9:21:08 PM
In article <pt3ugr7f.fsf@ccs.neu.edu>, Joe Marshall wrote:
> 
> Unspecified order:
>   Assuming a correct program, this implies that the program does not
>   depend upon argument order.
> 
> Specified order:
>   Assuming a correct program, this says nothing about whether the
>   program depends upon argument order.
> 
> So by specifying the order of evaluation, we introduce ambiguity:  was
> the intent of the programmer to depend upon the order?  It is
> therefore *harder* to understand.

The main flaw with this reasoning is that it is contradicted by my
empirical experience -- having an unspecified evaluation order leads
to bugs that would not have existed in an implementation that used a
left-to-right order. 

I mean, if you don't want to specify evaluation order, why are you
programming in a strict language anyway? Haskell exists for a reason,
after all. ;)

-- 
Neel Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
10/7/2004 9:34:05 PM
Joe Marshall wrote:
> Thant Tessman <thant@acm.org> writes:
> 
> 
>>Joe Marshall wrote:
>>
>>>Ron Garret <rNOSPAMon@flownet.com> writes:
>>>
>>>
>>>>[...] There are objective arguments in favor of fixed OoE.  There
>>>>are further, distinct objective arguments in favor of particular
>>>>fixed OoE's over others.
>>>
>>>Let's hear them!
>>
>>It is always good to make it easier to understand what a program does
>>independent of the tastes and skills of the programmer who wrote it.
> 
> 
> Unspecified order:
>   Assuming a correct program, this implies that the program does not
>   depend upon argument order.
> 
> Specified order:
>   Assuming a correct program, this says nothing about whether the
>   program depends upon argument order.
> 
> So by specifying the order of evaluation, we introduce ambiguity:  was
> the intent of the programmer to depend upon the order?  It is
> therefore *harder* to understand.

But you don't know if the programmer's intention was to rely on fixed 
order of evaluation even in the unspecified case. You have to assume 
they didn't. You disguise this assumption behind the term "correct," but 
it's no different than assuming "good style" in the fixed-order case.

The real difference is that the latter case allows you to understand 
what a program actually does independent of what the programmer intended 
it to do.

-thant

0
thant (332)
10/7/2004 9:35:50 PM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> In article <xa79d.6994$Vm1.1199@newsread3.news.atl.earthlink.net>,
>  "Anton van Straaten" <anton@appsolutions.com> wrote:
> > Let me come at that from the other direction.  Where can I read up on
this
> > principle, so that I can understand it as something other than a way to
> > defend some of the quirkier features of scripting languages?
>
> A Google search makes a good start.

Not really.  I see references to the principle in "the design of all kinds
of interfaces, not just software", but the first real programming-language
specific link that comes up is related to Ruby:
http://lists.free.net.ph/pipermail/compsci/2004-April/001807.html

I'm afraid that didn't shed any light on the matter at all.  I'd seriously
be interested in seeing some discussion of how to meaningfully apply this
principle to programming languages.  I've never seen such a description in
other than informal contexts, in languages that I wouldn't want to emulate.

The obvious big problem is the principle of least surprise with respect to
what?  Newbies?  Imperative programmers?  Functional programmers?  Experts?
Englishmen?  Israelis?

Best I can tell, you're really talking about the principle of least surprise
for people who already have ingrained imperative habits.  I don't consider
that a strong criterion for influencing the design of functionally-oriented
languages.

> > You can use an implementation with fixed evaluation order to be sure of
> > that.  No-one (afaik) is suggesting that implementations should not be
> > allowed to offer fixed evaluation order.  We're talking about the
> > specification here.
>
> That's right.  Under the specification it is impossible to know whether
> the behavior of a program is invariant with respect to the
> implementation it is running under except in certain special cases.  IMO
> that's a bad thing.

I agree.  I'm happy to support a better solution, as I've said elsewhere,
just not one that destroys a useful capability.

> > The exact same argument applies to having the ability to
> > specify a distinction between code that depends on order of evaluation,
> > and code which does not.
>
> Perhaps, but that's a red herring.  No one is arguing against the
> ability to specify such a distinction.

Not true.  People have argued in this thread that there is so little merit
to specifying this distinction, that the capability can be abandoned
entirely.

> The argument is over *how* that distinction is specified.
> I have no problem with leaving the OoE of LET clauses unspecified.

As has been pointed out, there are some problems with this.  Of course,
there are other solutions, but the point is those solutions have to be
worked out and agreed on before a useful evaluation order can be fixed.

> > > And for some reason, most people find it easier to
> > > think in terms of side effects when they sit down to solve certain
> > > classes of problems.  That's just the way that the human brain seems
to
> > > be wired.
> >
> > Oy.  I think this belongs in c.l.l.
>
> Really?  Why?  Do you believe that Scheme is just a mathematical toy and
> should not be used for real world applications?

No.  I believe that your claim "That's just the way that the human brain
seems to be wired" would at the very least, require a lot of qualification
to be meaningful.  In general, this kind of thinking is based on a range of
assumptions that are often only true relative to individual experience, and
historical factors, including how someone has been taught or learned
something, or how currently popular languages have evolved.  Many people
who've learned mathematics, mutation-free programming, and/or recursion
first find mutating loops and other uses of mutation unnatural.

I think there are definitely some human factor issues here: functional
languages are sometimes overly restrictive and could be more helpful in some
cases in terms of supporting the use of side effects.  However, I think that
any attempt to reason from how traditional imperative languages work in this
area is suspect, because they're just broken in that respect, and have paid
almost no attention whatsoever to sensible management of mutation.  But it's
difficult to reason about human factors in languages without involving
traditional imperative languages.  The bottom line is we don't have good
controls for proper experiments in this area, and we need to be very careful
about how we reach conclusions.

> > I agree that human factors are very important.
>
> Then why do you want to banish me to c.l.l. just because I brought them
> up?

I don't want to banish *you*, just that part of the argument.  I like you.
:)

If you really want to have that discussion, it has to be based on something
more verifiable than subjective experiences.  Otherwise, we may as well be
discussing postmodernism.

> > But that's theoreticaly tractability, not practical
> > tractability.  The argument can and has been made that fixed evaluation
> > order is less tractable in practice, because it leads to the masking of
> > fragile unintended order dependence.
>
> Maybe I don't understand what you mean by "tractable".  Fixed OoE
> doesn't mask unintended order dependence, it eliminates it.

False.  I've seen situations in which an order dependence exists, which the
author of the program is unaware of.  That tends to lead to bugs in future,
not only when code is incorrectly refactored, but also when the author(s)
use their incorrect mental model of the program to reason further about the
program.  A useful fixed order of evaluation helps support incorrect mental
models of programs.

> It occurred to me that call-with-arguments-evaluated-in-any-order is
> unnecessary.  LET suffices.

I've addressed this in another reply to you.

> > The cases where it might matter include every function call whose
argument
> > list itself contains a function call.
>
> No.  The cases where it might matter includes ONLY those function calls
> whose argument list contains MORE THAN ONE function call, at least one
> of which has side effects.

Right, slight misstatement on my part.  However, we should also remember
that we're talking about macros, too, and often large nested expressions
containing a mix of functions, macros, and syntax, in which more than one
function call with side effects can become a common condition, if it's
allowed to be.

With functions which contain side effects, Scheme lacks a way to statically
encode that knowledge about the function, so the reader of code can be left
guessing about that, or have to investigate functions individually.  That's
part of the justification for annotating only the exceptions, where side
effect ordering is important.

Anton


0
anton58 (1240)
10/7/2004 9:48:18 PM
campbell@bloodandcoffee.net (Taylor Campbell) writes:

>> Neelakantan Krishnaswami wrote:
>> > No, this is literally the only source of order of evaluation bugs I've
>> > ever had. I mean, I can see the pragmatic case not to declare a fixed
>> > order -- it's not cool to declare solid, existing implementations
>> > non-conforming -- but I don't think there's any principled case
>> > against fixing the order of evaluation to left to right.
>
> The most concrete example in this thread that I've seen, explained by
> Joe Marshall (and _also_, _independently_, given by Jorgen Schaefer on
> another medium) was a bug introduced by permuting an _undocumented_
> dependency on the order of evaluation.  Because an argument list, even
> with a fixed order, contains no information about what _actually_
> depends on what, you just don't know if permuting it is OK.  By using
> LET* explicitly, you make it explicit what depends on what.  This, to
> me, expresses a very strong principled argument against fixing the OoE.

Maybe I should expand on this. I didn't originally want to post,
because I don't like participating in a discussion about a mostly
subjective matter (as explained by Anton van Straaten) when
participants are so serious about it, but as you asked whether I
minded...

This happened some time (over a year) ago. I was extending some
Java code (don't ask) that looked roughly like this:

    someMethod(Foo.thingy(), Foo.lenghtyComputation(), null);

I needed something from the value of the lengthyComputation to
compute the third argument. Easy:

    Bar b = Foo.lengthyComputation();
    someMethod(Foo.thingy(), b, b.someValue());

Unfortunately, the value someMethod used from its second argument
depended on some changes made by thingy(). This caused a slight
bug that showed up in a completely different part of the program,
and hence it took me about a day to trace it to this change.

The correct solution was of course:

    Baz z = Foo.thingy();
    Bar b = Foo.lengthyComputation();
    someMethod(z, b, b.someValue());

Since those days of debugging, I'm a friend of an undefined order
of evaluation. If it is undefined, I am correct for doing such a
transformation without being forced to trace the call tree on
whether maybe eventually one arguments side effects might affect
another argument, and hence inter depend. This is the reason Anton
(among others) pointed out that the signalling of interdependence
is important: So the programmer knows when he can do such
reordering or not. Since it is more common to have
non-interdependent arguments then interdependent, the
interdependence should be highlighted.

Of course, the same could have happened if the implementation
would just use left-to-right ordering, and the original author was
(unknowingly?) depending on that. But then, at least, it would
have been his error. I don't think it can justly be expected from
the programmer to look through all arguments to see whether they
happen to have some order requirement.

To repeat: This is my opinion. I don't have any claims on being
"right" in this issue. But I see that there are good arguments for
both sides, and hence know that this is a pretty subjective thing
that depends greatly on the personal preferences and taste, and
not on some inherent theoretical value.

Greetings,
        -- Jorgen

-- 
((email . "forcer@forcix.cx") (www . "http://www.forcix.cx/")
 (gpg   . "1024D/028AF63C")   (irc . "nick forcer on IRCnet"))
0
forcer (15)
10/7/2004 10:20:05 PM
Anton van Straaten wrote:

> [...]  People have argued in this thread that there is so little merit
> to specifying this distinction, that the capability can be abandoned
> entirely. [...]

Just to be clear, I argue that there is *no* merit *exept* when dealing 
with semantic constructs that are simultaneously imperative and 
genuinely non-deterministic. The example of a thread multiplexer comes 
to mind.

-thant

0
thant (332)
10/7/2004 10:26:08 PM
cesuraSPAM@verizon.net (William D Clinger) wrote in message news:<fb74251e.0410061616.4fd47535@posting.google.com>...
> I'm serious about this.  I really want to know.  What I am
> asking is:  Would you would be happy with a language in which
> the language's semantics imposes a fixed deterministic order
> of evaluation upon implementors, but programs that depend on
> this order of evaluation are regarded as buggy?


Mercury language has had the same dilemma regarding the order of
evaluation, and they have come up with the best, IMHO, compromise,
quoted below. I would wish the Scheme standard could contain a
similar declaration.

Extended quotation from:
http://www.cs.mu.oz.au/research/mercury/information/doc-release/reference_manual_12.html

There is an operational semantics of Mercury programs called the
strict sequential operational semantics. In this semantics, the
program is executed top-down, starting from `main/2', and function
calls within a goal, conjunctions and disjunctions are all executed in
depth-first left-to-right order....

Mercury implementations are required to provide a method of processing
Mercury programs which is equivalent to the strict sequential
operational semantics.

There is another operational semantics of Mercury programs called the
strict commutative operational semantics. This semantics is equivalent
to the strict sequential operational semantics except that there is no
requirement that function calls, conjunctions and disjunctions be
executed left-to-right; they may be executed in any order, and may
even be interleaved. Furthermore, the order may even be different each
time a particular goal is entered.

As well as providing the strict sequential operational semantics,
Mercury implementations may optionally provide additional
implementation-defined operational semantics, provided that any such
implementation-defined operational semantics are at least as complete
as the strict commutative operational semantics. An
implementation-defined semantics is "at least as complete" ...

Thus, to summarize, there are in fact a variety of different
operational semantics for Mercury. In one of them, the strict
sequential semantics, there is no nondeterminism -- the behaviour is
always specified exactly. Programs are executed top-down using SLDNF
(or something equivalent), mode analysis does "minimal" reordering (in
a precisely defined sense), function calls, conjunctions and
disjunctions are executed depth-first left-to-right, and function
evaluation is strict. All implementations are required to support the
strict sequential semantics, so that a program which works on one
implementation using this semantics will be guaranteed to work on any
other implementation. However, implementations are also allowed to
support other operational semantics, which may have non-determinism,
so long as they are sound with respect to the declarative semantics,
and so long as they meet a minimum level of completeness

This compromise allows Mercury to be used in several different ways.
Programmers who care more about ease of programming and portability
than about efficiency can use the strict sequential semantics, and can
then be guaranteed that if their program works on one correct
implementation, it will work on all correct implementations. Compiler
implementors who want to write optimizing implementations that do lots
of clever code reorderings and other high-level transformations or
that want to offer parallelizing implementations which take maximum
advantage of parallelism can define different semantic models.
Programmers who care about efficiency more than portability can write
code for these implementation-defined semantic models. Programmers who
care about efficiency and portability can achieve this by writing code
for the commutative semantics. Of course, this is not quite as easy as
using the strict sequential semantics, since it is in general not
sufficient to test your programs on just one implementation if you are
to be sure that it will be able to use the maximally efficient
operational semantics on any implementation. However, if you do write
code which works for all possible executions under commutative
semantics (i.e. for all possible orderings of conjunctions and
disjunctions), then you can be guaranteed that it will work correctly
on every implementation, under every possible implementation-defined
semantics.

The University of Melbourne Mercury implementation offers eight
different semantics, which can be selected with different combinations
of the `--no-reorder-conj', `--no-reorder-disj', and `--fully-strict'
options. (The `--fully-strict' option prevents the compiler from
improving completeness by optimizing away infinite loops or calls to
require__error/1 or exception__throw /1.) The default semantics are
the commutative semantics. Enabling all of these options gives you the
the strict sequential semantics. Enabling just some of them gives you
a semantics somewhere in between.

--end-quotation
0
oleg8119 (112)
10/7/2004 10:29:06 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> > Perhaps, but that's a red herring.  No one is arguing against the
> > ability to specify such a distinction.
> 
> Not true.  People have argued in this thread that there is so little merit
> to specifying this distinction, that the capability can be abandoned
> entirely.

"Arguing against" would, as I understand it, correspond to saying
"must be abandoned".  At least I was not saying that.  What I did say
is that it "might as well be abandoned".  In other words, I don't
object to a mechanism for expressing order-independence, but I do
object to the particular convention that currently passes for such a
mechanism.

> As has been pointed out, there are some problems with this.  Of course,
> there are other solutions, but the point is those solutions have to be
> worked out and agreed on before a useful evaluation order can be fixed.

No, they don't.  There are plenty of successful languages that specify
OoE without having a mechanism for indicating intended
order-(in)dependence.  I am using such a language on a daily basis,
and I have refactored large amounts of code written in this language
(but in many cases by others than myself).  The lack of information
about intended order-independence has not once come up as a stumbling
block.

> I've seen situations in which an order dependence exists, which the
> author of the program is unaware of.  That tends to lead to bugs in
> future, not only when code is incorrectly refactored, but also when
> the author(s) use their incorrect mental model of the program to
> reason further about the program.

The contents of this paragraph is independent of whether or not the
language specifies order of evaluation.  The only difference is that
with unspecified order it already constitutes a bug, but that bug
might not manisfest itself in observable misbehavior. Unfortunately,
it might when the phase of the moon changes.

> A useful fixed order of evaluation helps support incorrect mental
> models of programs.

This is bogus reasoning.  Whether or not I have an unintended order
dependence in my program does not depend on whether or not the
language specifies a fixed order.  With a fixed order I might be
encouraged to rely on this order -- in which case the dependencies are
not unintended by definition.  With a fixed order, order dependencies
-- regardless of whether they are intended or not -- are dealt with
equally by all implementations, so my program does not suddenly start
misbehaving when I shift to a new compiler or platform.

> > > The cases where it might matter include every function call whose
> argument
> > > list itself contains a function call.
> >
> > No.  The cases where it might matter includes ONLY those function calls
> > whose argument list contains MORE THAN ONE function call, at least one
> > of which has side effects.
> 
> Right, slight misstatement on my part.

It was not a misstatement, the original statement is correct, at least
in general. Example:

   (f (g) x)

can depend on order of evaluation if g has the capacity of mutating x.
[If x is known to be immutable, then OoE does not matter here.  In
Scheme a compiler can easily figure this out for local variables.  In
ML it is a given.]

> However, we should also remember
> that we're talking about macros, too, and often large nested expressions
> containing a mix of functions, macros, and syntax, in which more than one
> function call with side effects can become a common condition, if it's
> allowed to be.

Glad you mention macros.  Don't they completely undermine the "encodes
knowledge about order-depenencies" claim?  After all, a big macro of the form

    (m A b C d E)

might expand into

    (f A b C d)

or into

    (let* ((d A) (b C)) E)

What information do I have if all I see is (m A b C d E)?  Not even
scoping is evident, nor is strictness, let alone order dependence!

Matthias
0
find19 (1244)
10/7/2004 10:31:59 PM
In article <uy8iii930.fsf@STRIPCAPStelus.net>,
 Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > Fine.  Use LET for code where OoE doesn't matter.
> 
> But then you cannot implement LET in terms of lambda, since OoE for lambda
> will be specified.

Nonsense.  Implementing a non-deterministic LET in terms of a 
deterministic LAMBDA is an elementary exercise.  Granted the mapping 
will no longer be quite as straightforward as it is now, but to say it's 
impossible is categorically false.

rg
0
rNOSPAMon (1927)
10/7/2004 11:05:31 PM
Joe Marshall <jrm@ccs.neu.edu> writes:
> Since no one here actually intends to *rely* on the order, who cares
> what that order is?  Or do you intend to rely on it?

Well, yes, if it is part of the specified language. For things like currying,
etc.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/7/2004 11:08:19 PM
In article <3c0qi7gh.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> >> I predict, therefore, that virtually *all* the proponents
> >> of specifying an order have `left to right' in mind and will violently
> >> object to any other specific order.
> >
> > That does not follow.  There are objective arguments in favor of fixed 
> > OoE.  There are further, distinct objective arguments in favor of 
> > particular fixed OoE's over others.
> 
> Let's hear them!

Which ones?  I have presented an objective argument in favor of a fixed 
OoE in terms of the needs of industrial applications of programming 
languages.  I have not taken a position on *which* OoE is to be 
preferred, though my personal preference as a reader of English would be 
left to right.  But I can't think of any principled reason to prefer L2R 
over R2L.  Personally, I would be content to settle the issue with a 
coin toss.

> >> I also predict that they will
> >> call this `natural' (as if progamming were a natural activity) and
> >> `what people are used to' (as if Arabic numerals are uncommon in
> >> programs).
> >
> > Perhaps.  So?
> 
> Arguments based on `natural' order are specious.

Agreed, which is exactly why I have steered clear of taking a position 
on this issue.

> >> So I propose that if the order is fixed, it should be this: number the
> >> arguments from right to left starting with one (not zero), write the
> >> numerals as English words and sort them lexicographically:
> >> 
> >> (f a)           => a, then f
> >> 
> >> (f a b)         => b, f, a
> >> 
> >> (f a b c)       => f, c, a, b
> >> 
> >> (f a b c d)     => f, a, d, b, c
> >> 
> >> (f a b c d e)   => a, b, e, f, c, d
> >> 
> >> (f a b c d e h) => b, c, h, f, a, d, e
> >> 
> >> Is this order better than leaving the order unspecified?
> >
> > Yes.
> >
> >> Is this order worse than right to left?
> >
> > Of course.
> 
> Why?

Because it's specifically designed to be complicated and obscure, which 
is diametrically counter to the philosophy underlying the design of 
Scheme.

rg
0
rNOSPAMon (1927)
10/7/2004 11:15:36 PM
Joe Marshall <jrm@ccs.neu.edu> writes:
> Since no one here actually intends to *rely* on the order, who cares
> what that order is?  Or do you intend to rely on it?

Example: if specified as left-to-right in the language, then it is natural and
robust to do things like:

  (let ((itr (create-iterator ...)))
    ; Show the first 3 items
    (print (next itr) (next itr) (next itr)))

I find myself swayed back to the unsepcified order of things, however. The
reason is that I want LAMBDA to be the backbone of everything. If we can't
specify LET in terms of LAMBDA, then our language spirit is very different.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/7/2004 11:16:25 PM
In article <pt3ugr7f.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> Thant Tessman <thant@acm.org> writes:
> 
> > Joe Marshall wrote:
> >> Ron Garret <rNOSPAMon@flownet.com> writes:
> >>
> >>> [...] There are objective arguments in favor of fixed OoE.  There
> >>> are further, distinct objective arguments in favor of particular
> >>> fixed OoE's over others.
> >> Let's hear them!
> >
> > It is always good to make it easier to understand what a program does
> > independent of the tastes and skills of the programmer who wrote it.
> 
> Unspecified order:
>   Assuming a correct program, this implies that the program does not
>   depend upon argument order.
> 
> Specified order:
>   Assuming a correct program, this says nothing about whether the
>   program depends upon argument order.
> 
> So by specifying the order of evaluation, we introduce ambiguity:  was
> the intent of the programmer to depend upon the order?  It is
> therefore *harder* to understand.

Your conclusion follows only if we have a way to tell a priori if the 
program is correct.  Since there is no such way, this argument is 
specious.  There is no way to tell if what you see is correct code that 
doesn't depend on OoE, or buggy code (with respect to some 
implementations) that does.  The ONLY defense for no OoE is that it 
raises the spectre of potential bugginess as a disincentive to be 
cavalier about OoE dependencies.  While I'm all for disincentives to be 
cavalier about the semantics of code, this seems to me to be a 
particularly ineffective means of achieving it.  It places *all* of the 
burden on the programmer and provides him with no support whatsoever to 
assist him in his task.

In fact, it's even worse than that: it's actually *impossible* for a 
programmer to do this job unless he has access to *all* the code.  If I 
want to write (f (g) (h)) how am I supposed to know if I have an order 
dependency if I didn't write g and h and don't have access to the source 
code?

rg
0
rNOSPAMon (1927)
10/7/2004 11:27:35 PM
In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
 Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> > > Is this order better than leaving the order unspecified?
> > 
> > Yes.
> 
> No. It is confusing as hell, and so it is better not to have to think about
> it.

You didn't read the question.  It is confusing as hell, but a confusing 
order is better than none at all.  At least it makes program behavior 
deterministic.  But a simple OoE would, of course, be even better.

> A *simple* order is best. 
> 
> Left-to-right is arguably best for the programmer.
> 
> Right-to-left could be arguably better for compiler writers on most machines.

Agreed.

rg
0
rNOSPAMon (1927)
10/7/2004 11:29:20 PM
In article <VDh9d.11008$gs1.1055@newsread2.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> > But expressiveness has nothing whatever to do with it.  This is simply a
> > turf battle between LET and LET* over the syntactic sugar of nested
> > function calls.
> 
> Again, that would be true if there were concrete proposals on the table for
> reintroducing the ability to express code with unspecified evaluation order
> (or code which is asserted to be free of order dependencies), and if those
> who want to fix evaluation order were in favor of agreeing on such a
> proposal.  It's not clear to me what many of the others on the
> useful-fixed-order side of the debate think in this respect - many seem
> quite happy with the idea of simply fixing a useful evaluation order in the
> standard, and ignoring the surrounding issues.

OK, how about this for a proposal:

1) Fix the order of evaluation for function calls.  (My personal 
preference is L2R but I can live with R2L.)

2) Keep the semantics of LET* as they are.

3) Either a) stipulate that the OoE of LET is potentially indeterminate, 
or b) introduce NDLET whose OoE is indeterminate.  (You could even 
stipulate that the preferred implementation of NDLET evaluates its 
arguments in a random order every time, or cycles through all possible 
permutations of orderings.)

Note that the straightforward implementation of LET in terms of LAMBDA 
remains a legal implementation (one of many) of LET under all possible 
permutations of the above proposal schema.

rg
0
rNOSPAMon (1927)
10/7/2004 11:50:40 PM
In article <rNOSPAMon-E9AEB5.16053107102004@nntp1.jpl.nasa.gov>,
 Ron Garret <rNOSPAMon@flownet.com> wrote:

> In article <uy8iii930.fsf@STRIPCAPStelus.net>,
>  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> 
> > Ron Garret <rNOSPAMon@flownet.com> writes:
> > > Fine.  Use LET for code where OoE doesn't matter.
> > 
> > But then you cannot implement LET in terms of lambda, since OoE for lambda
> > will be specified.
> 
> Nonsense.  Implementing a non-deterministic LET in terms of a 
> deterministic LAMBDA is an elementary exercise.  Granted the mapping 
> will no longer be quite as straightforward as it is now, but to say it's 
> impossible is categorically false.

Actually, it just occurred to me that even the straightforward 
implementation of LET in terms of LAMBDA remains a legal implementation 
when OoE for function calls is fixed even if OoE for LET is not.

rg
0
rNOSPAMon (1927)
10/7/2004 11:52:33 PM
Ron Garret <rNOSPAMon@flownet.com> schrieb:
> it's actually *impossible* for a programmer to do this job unless he
> has access to *all* the code.  If I want to write (f (g) (h)) how am I
> supposed to know if I have an order dependency if I didn't write g and
> h and don't have access to the source code?

How is this different under a fixed OoE? You still have to know
something about g and h to know what order to put them in.
0
adrian61 (83)
10/8/2004 12:41:55 AM
Joe Marshall wrote:
> Ray Dillinger <bear@sonic.net> writes:

>>There is a problem with this argument.
>>
>>Having an unspecified order of evaluation would not have
>>saved you from this bug.
> 
> 
> Correct.  I assert that the existence of order of evaluation bugs has
> nothing to do with whether the order is specified or not.

Hmmm.  We have a different idea of what an OofE bug is, then.
In a language with fixed Order of Evaluation, it is not a bug
to rely on that order of evaluation and it is a bug to rely
on any other order of evaluation.  At least according to my
idea of what a bug is.


>>Because of this consistency, it is easier to debug programs and
>>easier to be sure of their portability between implementations.
> 
> 
> If your intent is to port buggy programs, then clearly a specified
> order of evaluation is important.

My intent is to debug buggy programs before they are ported.
If the bug does not manifest in the current implementation's
OofE, and OofE is unspecified, it is  a bug but you will
never find out about it until someone runs it on a system
with different OofE.  If the bug does not manifest in the
current implmentation's OofE, and OofE is fixed, then it is
not a bug.

				Bear


0
bear (1219)
10/8/2004 1:24:25 AM
Jorgen Schaefer <forcer@forcix.cx> writes:

[ lengthy description of bad experience snipped ]

> Since those days of debugging, I'm a friend of an undefined order
> of evaluation. If it is undefined, I am correct for doing such a
> transformation without being forced to trace the call tree on
> whether maybe eventually one arguments side effects might affect
> another argument, and hence inter depend.

[...]

> Of course, the same could have happened if the implementation
> would just use left-to-right ordering, and the original author was
> (unknowingly?) depending on that.

Exactly.

> But then, at least, it would have been his error.

So what?  The space ship is out of reach now, and the board computer
is malfunctioning...
The problem is that even though it may have been her error, I can't
blame her very much for that because finding such an error is
extremely difficult.

> I don't think it can justly be expected from
> the programmer to look through all arguments to see whether they
> happen to have some order requirement.

Au contraire!  If you reorder the arguments, you have to make sure
doing so does not cause harm.  If you want to avoid the hassle, just
perform the correct transformation (which you showed).  That is easy
enough and does not require proving non-interdependence.

Matthias
0
find19 (1244)
10/8/2004 1:52:48 AM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> But expressiveness has nothing whatever to do with it.  This is simply a 
> turf battle between LET and LET* over the syntactic sugar of nested 
> function calls.

If this were true, it should be an easy battle to resolve.
(As I will attempt to show if Garret's assertion is shown
to be true.)

But is Ron Garret's assertion actually true?

Will
0
cesuraSPAM (401)
10/8/2004 1:58:54 AM
Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
>  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> 
> > Ron Garret <rNOSPAMon@flownet.com> writes:
> > > In article <y8iisb3g.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> > > > Is this order better than leaving the order unspecified?
> > > 
> > > Yes.
> > 
> > No. It is confusing as hell, and so it is better not to have to think about
> > it.
> 
> You didn't read the question.  It is confusing as hell, but a confusing 
> order is better than none at all.  At least it makes program behavior 
> deterministic.  But a simple OoE would, of course, be even better.

This is actually a very good starting point for arguing rationally
about the principle of least surprise.  Basically, we want to avoid
gratuituous complexity in the semantics of the language.  That's why
left-to-right and right-to-left are clear winners over other fixed
orders.  Incidentally, I think that it is also another reason
(although related to the ones I already brought forward) why a fixed
order wins over an unspecified one.  An unspecified order of
evaluation is pretty tricky to pin down formally -- much trickier than
a fixed order.

Matthias
0
find19 (1244)
10/8/2004 2:11:30 AM
Ray Dillinger <bear@sonic.net> schrieb:
> If the bug does not manifest in the current implmentation's OofE, and
> OofE is fixed, then it is not a bug.

Most bugs aren't relative to the language specification, they're
relative to the program specification. It doesn't matter if the language
spec says you can rely on fixed OofE, good designs will specify that you
*can't* -- except for maybe a few necessary, well-documented spots --
because maintainability demands that the program be invariant under
certain refactorings.

To me, if you modify a program in an acceptable way and it breaks,
that's just as much a bug as giving it some data it should accept and it
breaking. "Running" isn't the only thing you have to be able to
successfully do to programs.
0
adrian61 (83)
10/8/2004 4:18:48 AM
Matthias Blume <find@my.address.elsewhere> schrieb:
> If you reorder the arguments, you have to make sure doing so does not
> cause harm.  If you want to avoid the hassle, just perform the correct
> transformation (which you showed).  That is easy enough and does not
> require proving non-interdependence.

So this makes me wonder: what does it mean to say that not relying on
fixed OofE is "good style"?  I mean, what's the benefit of anybody
practicing good style, if you still have to proceed as if nobody
practiced it?
0
adrian61 (83)
10/8/2004 4:23:42 AM
Adrian Kubala <adrian@sixfingeredman.net> writes:

> Matthias Blume <find@my.address.elsewhere> schrieb:
> > If you reorder the arguments, you have to make sure doing so does not
> > cause harm.  If you want to avoid the hassle, just perform the correct
> > transformation (which you showed).  That is easy enough and does not
> > require proving non-interdependence.
> 
> So this makes me wonder: what does it mean to say that not relying on
> fixed OofE is "good style"?  I mean, what's the benefit of anybody
> practicing good style, if you still have to proceed as if nobody
> practiced it?

It's like driving: When approaching an intersection at a green light,
you should still watch out for the odd guy who might be running his
red light.  If you approach a red light, you should stop.  Strictly
speaking, only one of the two actions is necessary to avoid
collisions.  We still do both because we don't have an agreement as to
which of the two is guaranteed.  It's basically a way of taking
matters in one's own hands without having to blindly trust others.

Matthias
0
find19 (1244)
10/8/2004 4:58:35 AM
"Anton van Straaten" <anton@appsolutions.com> wrote...
> Jim Bender <jim@benderweb.net> wrote:
> > I would have trouble with a fixed order of evaluation, where the
> > actual order can not be defended logically except as an attempt
> > to confound those who would write (f (read) (read) (read)).
>
> I don't really mean to pick on Jim, and I hope he will forgive me, but I
> think that this discussion could be much more productive if some people
> didn't try to paint it as so one-sided.  "Can not be defended logically" is
> not just an overstatement of the case - it's simply false.

I have a lot of sympathy for the Mercury language quote that Oleg posted.
I believe absolutely that multiple, different orders of evaluation can be
justified logically-- _including_ an "unspecified order". No doubt I was
unclear in my original post. What I had in mind was a far more narrow point.
The original phrase that triggered my comment was "an extremely arcane
fixed order of evaluation". I would be unhappy with the choice of an arbitrary
order, which was what I interpreted "extemely arcane" to mean.

While the default "strict sequential operational semantics" of Mercury
matches what I personally prefer (i.e. left-to-right order), perhaps Will's
compromise could be combined with the Mercury "compromise":
make the extremely arcane fixed order the portable default semantics. Other
semantics such as left-to-right order and a non-deterministic (unspecified
order) semantics could either included in the standard as options, or
relegated to be implementation-specific semantics. (I think that,
if Scheme went with the Mercury approach, it would make sense to
actually include these two alternative semantics as well, in the same
manner that Mercury identifies the alternative "strict commutative
operational semantics" in the quote Oleg provided.)

Jim



0
jim251 (34)
10/8/2004 5:14:37 AM
In article <fb74251e.0410071758.6ec5e0a4@posting.google.com>,
 cesuraSPAM@verizon.net (William D Clinger) wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> > But expressiveness has nothing whatever to do with it.  This is simply a 
> > turf battle between LET and LET* over the syntactic sugar of nested 
> > function calls.
> 
> If this were true, it should be an easy battle to resolve.
> (As I will attempt to show if Garret's assertion is shown
> to be true.)
> 
> But is Ron Garret's assertion actually true?

Why would you doubt it?

rg
0
rNOSPAMon (1927)
10/8/2004 5:23:01 AM
In article <slrncmboij.m01.adrian@sixfingeredman.net>,
 Adrian Kubala <adrian@sixfingeredman.net> wrote:

> Ron Garret <rNOSPAMon@flownet.com> schrieb:
> > it's actually *impossible* for a programmer to do this job unless he
> > has access to *all* the code.  If I want to write (f (g) (h)) how am I
> > supposed to know if I have an order dependency if I didn't write g and
> > h and don't have access to the source code?
> 
> How is this different under a fixed OoE? You still have to know
> something about g and h to know what order to put them in.

No, the decision on which order to put the arguments is dictated by the 
API of F.  What is not possible is to know in general is whether it was 
OK for me to write (f (g) (h)), or whether it was necessary instead for 
me to write (let* ( (x (g)) (y (h)) ) (f x y)).

rg
0
rNOSPAMon (1927)
10/8/2004 5:33:50 AM
Adrian Kubala wrote:
> Ray Dillinger <bear@sonic.net> schrieb:
> 
>>If the bug does not manifest in the current implmentation's OofE, and
>>OofE is fixed, then it is not a bug.
> 
> 
> Most bugs aren't relative to the language specification, they're
> relative to the program specification. 

I do not agree.  The program, and hence any bugs, are relative
to both.  In a language with fixed OofE, relying on that order
is not a bug and relying on the ability to make 'transformations'
on the program that rely on OofE being irrelevant is erroneous.

			Bear

0
bear (1219)
10/8/2004 8:10:51 AM
Anton van Straaten wrote:

> The tests become worthless in practice when order is fixed, for the reason
> you mention.  You lose the ability to distinguish which code is supposed to
> be independent of evaluation order when people take advantage of the
> language guarantees outside of explicit sequencing constructs.

And in practical terms, what does it buy you to be able to specify
code as not requiring information about order of evaluation?  What
code is correct under this assumption but incorrect in a fixed OofE?

You're correct, in some trivial sense, that you lose the ability,
under fixed OofE, to specify that code does not depend on OofE.
That is, perhaps, mildly bad from a mathematical perspective.
But from an engineering perspective, that ability was worthless
anyway; it didn't buy you the ability to write any correct code
that can't be written, equally correctly, under fixed OofE.

Conversely, non-fixed OofE results in inconsistent behavior, making
it possible for bugs to go undetected on a development system and
become showstoppers in the deployment system.  From an Engineering
perspective, this is VERY BAD.

				Bear

0
bear (1219)
10/8/2004 8:30:56 AM
"Anton van Straaten" <anton@appsolutions.com> writes:
> Matthias Blume wrote:
> > And that's a good thing.  It is an extremely clumsy and brittle way
> > of encoding this type of information.  I can't believe anyone can
> > possibly defend it and keep a straight face.
> 
> My interest is in defending the ability to encode the information in
> question, not in any specific technique for doing that.  However, good
> techniques seem in short supply.  What alternative ways of encoding this
> information do you suggest?  Keep in mind that suggesting future
> possibilities doesn't actually address the issue today, and that Scheme
> currently does succeed in enforcing it in a way which some people find
> satisfactory, if not ideal.

In point of fact, you could argue that the annoyance value is
*precisely* the value that unspecified evaluation order is supposed to
have. We want reliance upon a specific evaluation order *without
explicitly coding for it* to be an unpleasant experience. It's not as
if anyone is being prohibited from coding an explicit evaluation order
as in Haskell (w/out monads).

david rush
-- 
Until someone finds a way to go further, Lisp of some kind
is what's standing at the end of every language-design journey.
        -- Bear (on comp.lang.scheme)
0
kumoyuki (163)
10/8/2004 8:39:34 AM
Matthias Blume <find@my.address.elsewhere> writes:
> "Anton van Straaten" <anton@appsolutions.com> writes:
> > SML made a number of other pragmatic choices: things like LET being
> > equivalent to Scheme's LET*, for example.
> 
> SML's "let" can express both Scheme's "let" and Scheme's "let*"
> (ignoring order-of-evaluation guarantees):
> 
>    let val x = ...                      works like Scheme's let*
>        val y = ...

To which Anton was referring. 
 
>    let val x = ...                      works like Scheme's let
>        and y = ...

Is this not more correctly analogous to letrec?

david rush
-- 
There's a big difference between the two parties. The Republicans want
to take away all your freedom. The Democrats want to take away all
your money.
        -- Bill McGarr
0
kumoyuki (163)
10/8/2004 9:20:11 AM
David Rush <kumoyuki@gmail.com> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> > "Anton van Straaten" <anton@appsolutions.com> writes:
> > > SML made a number of other pragmatic choices: things like LET being
> > > equivalent to Scheme's LET*, for example.
> > 
> > SML's "let" can express both Scheme's "let" and Scheme's "let*"
> > (ignoring order-of-evaluation guarantees):
> > 
> >    let val x = ...                      works like Scheme's let*
> >        val y = ...
> 
> To which Anton was referring. 
>  
> >    let val x = ...                      works like Scheme's let
> >        and y = ...
> 
> Is this not more correctly analogous to letrec?

No.  What you are thinking of is spelled

   let val rec f = ...
           and g = ...
           and h = ...

or, with syntactic sugar:

 let fun f <pat> ... = ...
       | f <pat> ... = ...
     and g <pat> ... = ...
     and h <pat> ... = ...
       | h <pat> ... = ...

Matthias
0
find19 (1244)
10/8/2004 12:33:21 PM
A small argument for the left-to-right order of evaluation:

We have function 'map'. With an unspecified order a natural
implementation will apply the procedure to elements in an unspecified
order, and this is indeed how standard 'map' in Scheme is specified.

This means that when we want 'map' with sequential order, we must look
for another function, or in this case write it by hand (there is no
standard 'map' with a fixed order).

With a fixed order of arguments the API is simpler: one variant of
'map' suffices for both of the most common choices of the order
(left-to-right or doesn't matter).

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
0
qrczak (1266)
10/8/2004 1:15:48 PM
Ron Garret <rNOSPAMon@flownet.com> schrieb:
> In article <slrncmboij.m01.adrian@sixfingeredman.net>,
>  Adrian Kubala <adrian@sixfingeredman.net> wrote:
>
>> Ron Garret <rNOSPAMon@flownet.com> schrieb:
>> > it's actually *impossible* for a programmer to do this job unless he
>> > has access to *all* the code.  If I want to write (f (g) (h)) how am I
>> > supposed to know if I have an order dependency if I didn't write g and
>> > h and don't have access to the source code?
>> 
>> How is this different under a fixed OoE? You still have to know
>> something about g and h to know what order to put them in.
>
> No, the decision on which order to put the arguments is dictated by the 
> API of F.  What is not possible is to know in general is whether it was 
> OK for me to write (f (g) (h)), or whether it was necessary instead for 
> me to write (let* ( (x (g)) (y (h)) ) (f x y)).

Which is still true under fixed OoE, only there the question is, is it
okay to write (f (g) (h)) versus (let* ((y (h)) (x (g))) (f x y))

What I'm saying is that, if there's an order dependency between g and h,
you still have to know about it, which means, as you say, having access
to all the code. Imperative programming sucks for just that reason.
0
adrian61 (83)
10/8/2004 2:21:50 PM
"Anton van Straaten" <anton@appsolutions.com> writes:

> Matthias Blume wrote:
> > "Anton van Straaten" <anton@appsolutions.com> writes:
> >
> > > Right now, Scheme implementations do enforce this distinction on
> > > portable Scheme code.
> >
> > I don't know what definition of "expressive" Thant runs on, but Anton
> > seem to be running on a strange definition of "to enforce".
> 
> You're right, mea culpa, although I've explained my position on this in
> another reply to you, in which I mention bogeymen.

The bogeyman metaphor shows how bad an idea it is.  It's like telling
people not to wear seatbelts in an effort to make them drive safely.

Matthias
0
find19 (1244)
10/8/2004 2:28:10 PM
Ray Dillinger <bear@sonic.net> writes:

> Joe Marshall wrote:
>> Ray Dillinger <bear@sonic.net> writes:
>
>>>There is a problem with this argument.
>>>
>>>Having an unspecified order of evaluation would not have
>>>saved you from this bug.
>> Correct.  I assert that the existence of order of evaluation bugs has
>> nothing to do with whether the order is specified or not.
>
> Hmmm.  We have a different idea of what an OofE bug is, then.
> In a language with fixed Order of Evaluation, it is not a bug
> to rely on that order of evaluation and it is a bug to rely
> on any other order of evaluation.  At least according to my
> idea of what a bug is.

I think we both agree that depending upon a specific order of
evaluation that is *different* from the actual order of evaluation
(specified or not) is a bug.  I have encountered order of evaluation
bugs in languages like Scheme (where the order is not specified) and
in Common Lisp (where it is specified).  Specifying the order does not
prevent the error of depending upon the wrong order.

I think we disagree on whether it is a bug to *unintentionally* rely
on the actual order of evaluation.  It would clearly be a bug to
*intentionally* rely on an unspecified order, and it would clearly be
poor style to *intentionally* rely on a specified order.

It seems to me if intentionally relying on a specific order of
evaluation is poor style, then doing so *unintentionally* is even
worse.  I'd consider it a bug because it is an unintended dependency.

If we are going to specify order of evaluation, then we ought to
specify the return values of DEFINE and SET! as well because someone
might be relying on them.
0
jrm (1310)
10/8/2004 2:45:05 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Jorgen Schaefer <forcer@forcix.cx> writes:
>
> [ lengthy description of bad experience snipped ]
>
>> Since those days of debugging, I'm a friend of an undefined order
>> of evaluation. If it is undefined, I am correct for doing such a
>> transformation without being forced to trace the call tree on
>> whether maybe eventually one arguments side effects might affect
>> another argument, and hence inter depend.
>
> [...]
>
>> Of course, the same could have happened if the implementation
>> would just use left-to-right ordering, and the original author was
>> (unknowingly?) depending on that.
>
> Exactly.
>
>> But then, at least, it would have been his error.
>
> So what?  The space ship is out of reach now, and the board computer
> is malfunctioning...
> The problem is that even though it may have been her error, I can't
> blame her very much for that because finding such an error is
> extremely difficult.

But Java *has* a fixed order of evaluation, and it was *still* hard to
debug.
0
jrm (1310)
10/8/2004 2:48:08 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>> Thant Tessman <thant@acm.org> writes:
>>
>>>Joe Marshall wrote:
>>>
>>>>Ron Garret <rNOSPAMon@flownet.com> writes:
>>>>
>>>>
>>>>>[...] There are objective arguments in favor of fixed OoE.  There
>>>>>are further, distinct objective arguments in favor of particular
>>>>>fixed OoE's over others.
>>>>
>>>>Let's hear them!
>>>
>>>It is always good to make it easier to understand what a program does
>>>independent of the tastes and skills of the programmer who wrote it.
>> Unspecified order:
>>   Assuming a correct program, this implies that the program does not
>>   depend upon argument order.
>> Specified order:
>>   Assuming a correct program, this says nothing about whether the
>>   program depends upon argument order.
>> So by specifying the order of evaluation, we introduce ambiguity:
>> was
>> the intent of the programmer to depend upon the order?  It is
>> therefore *harder* to understand.
>
> But you don't know if the programmer's intention was to rely on fixed
> order of evaluation even in the unspecified case. 

Sure I do.  Their intent was to *not* rely on it.  If their intent
were to rely on it, they'd be deliberately writing bogus code. 

> The real difference is that the latter case allows you to understand
> what a program actually does independent of what the programmer
> intended it to do.

When I have to debug other people's code, what the program actually
does is evident.  What the programmer intended it to do is more
difficult to determine.
0
jrm (1310)
10/8/2004 2:53:53 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <pt3ugr7f.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> wrote:
>
>> Thant Tessman <thant@acm.org> writes:
>> 
>> > Joe Marshall wrote:
>> >> Ron Garret <rNOSPAMon@flownet.com> writes:
>> >>
>> >>> [...] There are objective arguments in favor of fixed OoE.  There
>> >>> are further, distinct objective arguments in favor of particular
>> >>> fixed OoE's over others.
>> >> Let's hear them!
>> >
>> > It is always good to make it easier to understand what a program does
>> > independent of the tastes and skills of the programmer who wrote it.
>> 
>> Unspecified order:
>>   Assuming a correct program, this implies that the program does not
>>   depend upon argument order.
>> 
>> Specified order:
>>   Assuming a correct program, this says nothing about whether the
>>   program depends upon argument order.
>> 
>> So by specifying the order of evaluation, we introduce ambiguity:  was
>> the intent of the programmer to depend upon the order?  It is
>> therefore *harder* to understand.
>
> Your conclusion follows only if we have a way to tell a priori if the 
> program is correct.  

Hence the word `assume' at the beginning of each clause.

> Since there is no such way, this argument is specious.  

Making assumptions is fine.  They are often called axioms.  If you
wish to reject the axiom, then we have this:

Unspecified order:
   Assume a buggy program.  This implies nothing.

Specified order:
   Assume a buggy program.  This implies nothing.

Not very edifying, but there you go.

> There is no way to tell if what you see is correct code that 
> doesn't depend on OoE, or buggy code (with respect to some 
> implementations) that does.  

Yes, but it is hard to make *any* sort of assumptions about buggy code
other than the obvious one that by definition it *doesn't* do what it
was designed to do.

> The ONLY defense for no OoE is that it raises the spectre of
> potential bugginess as a disincentive to be cavalier about OoE
> dependencies.

I disagree.  I think that `poor style' ought to be disincentive
enough.

> While I'm all for disincentives to be cavalier about the semantics
> of code, this seems to me to be a particularly ineffective means of
> achieving it.  It places *all* of the burden on the programmer and
> provides him with no support whatsoever to assist him in his task.

It's all on him anyway.  You're providing a safety net for exactly one
half of the high-wire act and telling people they can be sloppy
provided that they always fall to the left!

> In fact, it's even worse than that: it's actually *impossible* for a 
> programmer to do this job unless he has access to *all* the code.  If I 
> want to write (f (g) (h)) how am I supposed to know if I have an order 
> dependency if I didn't write g and h and don't have access to the source 
> code?

How are you supposed to write code if you don't know what it does?!  I
assume that g and h are documented.  If you are afraid that you must
call g first, just write 

   (let ((g-result (g))) (f g (h))) 

problem solved.

But suppose order of evaluation were defined as left to right.  Does
that save you from an *undocumented* dependency that requires h to be
called first?
0
jrm (1310)
10/8/2004 3:07:23 PM
oleg@pobox.com (oleg@pobox.com) writes:

> cesuraSPAM@verizon.net (William D Clinger) wrote in message news:<fb74251e.0410061616.4fd47535@posting.google.com>...
>> I'm serious about this.  I really want to know.  What I am
>> asking is:  Would you would be happy with a language in which
>> the language's semantics imposes a fixed deterministic order
>> of evaluation upon implementors, but programs that depend on
>> this order of evaluation are regarded as buggy?
>
>
> Mercury language has had the same dilemma regarding the order of
> evaluation, and they have come up with the best, IMHO, compromise,
> quoted below. I would wish the Scheme standard could contain a
> similar declaration.
>
> Extended quotation from:
> http://www.cs.mu.oz.au/research/mercury/information/doc-release/reference_manual_12.html
>
> There is an operational semantics of Mercury programs called the
> strict sequential operational semantics. In this semantics, the
> program is executed top-down, starting from `main/2', and function
> calls within a goal, conjunctions and disjunctions are all executed in
> depth-first left-to-right order....
>
> Mercury implementations are required to provide a method of processing
> Mercury programs which is equivalent to the strict sequential
> operational semantics.

> There is another operational semantics of Mercury programs called the
> strict commutative operational semantics.

I'd definitely support this sort of thing for Scheme.

Thanks, Oleg.

0
jrm (1310)
10/8/2004 3:11:23 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Making assumptions is fine.  They are often called axioms.

We usually take as axioms only things which are "obviously" true.
The assumption of a program being correct is obviously not obviously true.

> It's all on him anyway.  You're providing a safety net for exactly one
> half of the high-wire act and telling people they can be sloppy
> provided that they always fall to the left!

No.  Nobody is suggesting that people can be sloppy.

Also, your high-wire metaphor is a bit funny.

To me it's more like the kind of acrobatics (I'm missing the proper
English word here) where one guy is upside-down on a swing (high in
the air), trying to catch another guy who comes flying from another
swing.  Basically you want to arrange for the first guy to fall if he
can't properly catch the second (so that in this case they both fall
and be dead instead of just the second poor fellow being dead).  I
guess this is to make the first guy give his very best to make sure
nobody falls.  But in the end, I'm afraid, we will have just an
increase in the expected number of dead bodies...

(At least that's the impression I get from my own experience with
either language design.)

> How are you supposed to write code if you don't know what it does?!  I
> assume that g and h are documented.  If you are afraid that you must
> call g first, just write 
> 
>    (let ((g-result (g))) (f g (h))) 
> 
> problem solved.

I sometimes do this (although I'd do it correctly, unlike you :-) for
totally unrelated reasons (i.e., despite the fact that I know that f
and g can be called in any order).  Now where did that precious
documentation go?

> But suppose order of evaluation were defined as left to right.  Does
> that save you from an *undocumented* dependency that requires h to be
> called first?

No.  But at least the failure, if observable at all, will be
observable consistently -- and therefore easier to debug.

Matthias
0
find19 (1244)
10/8/2004 3:26:54 PM
In article <7eb8ac3e.0410071429.35b2155d@posting.google.com>, oleg@pobox.com
wrote:
> 
> Mercury language has had the same dilemma regarding the order of
> evaluation, and they have come up with the best, IMHO, compromise,
> quoted below. I would wish the Scheme standard could contain a
> similar declaration.

I find it hard to believe that Scheme could, unfortunately. Mercury is
pure, like Haskell, and as such has a degree of freedom in evaluation
order that imperative languages like Scheme and ML lack. :(

-- 
Neel Krishnaswami
neelk@cs.cmu.edu
0
neelk (298)
10/8/2004 3:44:19 PM
Joe Marshall wrote:
> Thant Tessman <thant@acm.org> writes:

[...]

>>But you don't know if the programmer's intention was to rely on fixed
>>order of evaluation even in the unspecified case. 
> 
> 
> Sure I do.  Their intent was to *not* rely on it.  If their intent
> were to rely on it, they'd be deliberately writing bogus code. 

You are assuming that the programmer knows OofE is unspecified. In other
words, you are assuming exactly what it is I claim you don't know.


>>The real difference is that the latter case allows you to understand
>>what a program actually does independent of what the programmer
>>intended it to do.
> 
> 
> When I have to debug other people's code, what the program actually
> does is evident.  What the programmer intended it to do is more
> difficult to determine.

What output a program produces for a given execution is evident. How it 
produces that output is less evident under unspecified OofE than it is 
under specified OofE.

-thant

0
thant (332)
10/8/2004 5:02:46 PM
Ron Garret <rNOSPAMon@flownet.com> writes:
> In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
>  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> > > > Is this order better than leaving the order unspecified?
> > > Yes.
> > No. It is confusing as hell, and so it is better not to have to think about
> > it.
> 
> You didn't read the question.  It is confusing as hell, but a confusing 
> order is better than none at all.  At least it makes program behavior 
> deterministic.  But a simple OoE would, of course, be even better.

I did read the question and disagree. My point is that a sufficiently
confusing specified order is effectively equivalent to having none specified
at all, at least to the programmer's mental work load.

That is, if you can't think about it enough to make effective use of it, the
practical consequence is that it does not exist.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/8/2004 6:30:37 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>> Thant Tessman <thant@acm.org> writes:
>
> [...]
>
>>>But you don't know if the programmer's intention was to rely on fixed
>>> order of evaluation even in the unspecified case.
>> Sure I do.  Their intent was to *not* rely on it.  If their intent
>> were to rely on it, they'd be deliberately writing bogus code.
>
> You are assuming that the programmer knows OofE is unspecified. In other
> words, you are assuming exactly what it is I claim you don't know.

I certainly assume that if the programmer is programming in Scheme,
then he knows Scheme.  If we assume that the programmer is unfamiliar
with the language he is using, then order of evaluation is the least
of our worries.

In any case, if we have the two modes like Mercury, I'll be happy.
0
jrm (1310)
10/8/2004 6:36:25 PM
In article <8yahb650.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > In article <pt3ugr7f.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
> > wrote:
> >
> >> Thant Tessman <thant@acm.org> writes:
> >> 
> >> > Joe Marshall wrote:
> >> >> Ron Garret <rNOSPAMon@flownet.com> writes:
> >> >>
> >> >>> [...] There are objective arguments in favor of fixed OoE.  There
> >> >>> are further, distinct objective arguments in favor of particular
> >> >>> fixed OoE's over others.
> >> >> Let's hear them!
> >> >
> >> > It is always good to make it easier to understand what a program does
> >> > independent of the tastes and skills of the programmer who wrote it.
> >> 
> >> Unspecified order:
> >>   Assuming a correct program, this implies that the program does not
> >>   depend upon argument order.
> >> 
> >> Specified order:
> >>   Assuming a correct program, this says nothing about whether the
> >>   program depends upon argument order.
> >> 
> >> So by specifying the order of evaluation, we introduce ambiguity:  was
> >> the intent of the programmer to depend upon the order?  It is
> >> therefore *harder* to understand.
> >
> > Your conclusion follows only if we have a way to tell a priori if the 
> > program is correct.  
> 
> Hence the word `assume' at the beginning of each clause.

You can assume a spherical sheep too, but that won't help you much if 
your task is to shear a real sheep.

> How are you supposed to write code if you don't know what it does?!  I
> assume that g and h are documented.  If you are afraid that you must
> call g first, just write 
> 
>    (let ((g-result (g))) (f g (h))) 
> 
> problem solved.
> 
> But suppose order of evaluation were defined as left to right.  Does
> that save you from an *undocumented* dependency that requires h to be
> called first?

Permit me to introduce you to the concept of "testing".

Imagine you are an engineer on a large project.  You have access to G 
and H and their documentation, but not their source code.  According to 
the documentation, it is safe to write (f (g) (h)).  Does that mean it 
is in fact safe to write (f (g) (h))?  No.  The documentation could be 
wrong.

So how can you really tell if it's safe to write (f (g) (h))?  Well, one 
way is to write it, run the resulting code, and see if it does what you 
want.  This is known in the trade as "testing".

But, of course, what you really care about is not whether the program 
works during testing.  What you really care about in industrial settings 
is whether the program works in production.  The utility of testing is 
predicated on the fact that under certain circumstances the behavior of 
computer programs is deterministic and hence reliably reproducible.  
When those circumstances do not apply (e.g. in multithreaded systems) 
the utility of testing is greatly reduced, to the chagrin of developers 
everywhere trying to hunt down weird deadlock bugs.

The problem with unspecified OoE is that it extends the same kind of 
nondeterminism that makes testing useless for MT code to any code that 
includes nested function calls.  Moreover, this is not just an 
unfortunate side effect of unspecified OoE, it is actually the INTENT.  
Unspecified OoE is supposed to FORCE you to think explicitly about 
possible OoE dependencies every time you write a nested function call, 
and holds the spectre of unpredictable potential disaster over your head 
as punishment if you get it wrong.  And for all that, unspecified OoE 
provides you no benefit whatsoever.  The claim that it makes the 
language more expressive has been debunked in other postings.

It seems like a poor tradeoff to me.

rg
0
rNOSPAMon (1927)
10/8/2004 6:37:47 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
> >  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> > > > > Is this order better than leaving the order unspecified?
> > > > Yes.
> > > No. It is confusing as hell, and so it is better not to have to think about
> > > it.
> > 
> > You didn't read the question.  It is confusing as hell, but a confusing 
> > order is better than none at all.  At least it makes program behavior 
> > deterministic.  But a simple OoE would, of course, be even better.
> 
> I did read the question and disagree. My point is that a sufficiently
> confusing specified order is effectively equivalent to having none specified
> at all, at least to the programmer's mental work load.
> 
> That is, if you can't think about it enough to make effective use of it, the
> practical consequence is that it does not exist.

This is false.  Having a specified order makes program behavior
consistent.  Even if I don't know what the order is, I can be sure
that it won't change under me while I'm not looking.  At the very
least, this makes the results of testing more meaningful.

But ultimately I agree that a fixed order which is easy to formalize,
understand, and remember (e.g., left-to-right) is preferable by far.

Matthias
0
find19 (1244)
10/8/2004 6:43:40 PM
In article <CQi9d.11067$gs1.3091@newsread2.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> > In article <xa79d.6994$Vm1.1199@newsread3.news.atl.earthlink.net>,
> >  "Anton van Straaten" <anton@appsolutions.com> wrote:
> > > Let me come at that from the other direction.  Where can I read up on
> this
> > > principle, so that I can understand it as something other than a way to
> > > defend some of the quirkier features of scripting languages?
> >
> > A Google search makes a good start.
> 
> Not really.  I see references to the principle in "the design of all kinds
> of interfaces, not just software", but the first real programming-language
> specific link that comes up is related to Ruby:
> http://lists.free.net.ph/pipermail/compsci/2004-April/001807.html
> 
> I'm afraid that didn't shed any light on the matter at all.  I'd seriously
> be interested in seeing some discussion of how to meaningfully apply this
> principle to programming languages.  I've never seen such a description in
> other than informal contexts, in languages that I wouldn't want to emulate.
> 
> The obvious big problem is the principle of least surprise with respect to
> what?  Newbies?  Imperative programmers?  Functional programmers?  Experts?
> Englishmen?  Israelis?

With respect to the expectation that the behavior of single-threaded 
computer programs with no external input is deterministic.  I think most 
programmers have this expectation regardless of their nationality.  The 
utility of the widespread practice of testing code is predicated on it.

> Best I can tell, you're really talking about the principle of least surprise
> for people who already have ingrained imperative habits.  I don't consider
> that a strong criterion for influencing the design of functionally-oriented
> languages.

Perhaps, but what does that have to do with Scheme?

Here is the description of Scheme given in R5RS:

"Scheme is a statically scoped and properly tail-recursive dialect of 
the Lisp programming language invented by Guy Lewis SteeleJr. and Gerald 
JaySussman.  It was designed to have an exceptionally clear and simple 
semantics and few different ways to form expressions.  A wide variety of 
programming paradigms, INCLUDING IMPERATIVE, functional, and message 
passing styles, find convenient expression in Scheme."

Emphasis added.


> > That's right.  Under the specification it is impossible to know whether
> > the behavior of a program is invariant with respect to the
> > implementation it is running under except in certain special cases.  IMO
> > that's a bad thing.
> 
> I agree.  I'm happy to support a better solution, as I've said elsewhere,
> just not one that destroys a useful capability.

I posted a proposal in another branch of this thread.

> > > The exact same argument applies to having the ability to
> > > specify a distinction between code that depends on order of evaluation,
> > > and code which does not.
> >
> > Perhaps, but that's a red herring.  No one is arguing against the
> > ability to specify such a distinction.
> 
> Not true.  People have argued in this thread that there is so little merit
> to specifying this distinction, that the capability can be abandoned
> entirely.

Arguing that it *can* be abandoned is not the same as arguing that it 
ought to be.

> > The argument is over *how* that distinction is specified.
> > I have no problem with leaving the OoE of LET clauses unspecified.
> 
> As has been pointed out, there are some problems with this.

Like what?

> > > > And for some reason, most people find it easier to
> > > > think in terms of side effects when they sit down to solve certain
> > > > classes of problems.  That's just the way that the human brain seems
> to
> > > > be wired.
> > >
> > > Oy.  I think this belongs in c.l.l.
> >
> > Really?  Why?  Do you believe that Scheme is just a mathematical toy and
> > should not be used for real world applications?
> 
> No.  I believe that your claim "That's just the way that the human brain
> seems to be wired" would at the very least, require a lot of qualification
> to be meaningful.  In general, this kind of thinking is based on a range of
> assumptions that are often only true relative to individual experience, and
> historical factors, including how someone has been taught or learned
> something, or how currently popular languages have evolved.  Many people
> who've learned mathematics, mutation-free programming, and/or recursion
> first find mutating loops and other uses of mutation unnatural.
> 
> I think there are definitely some human factor issues here: functional
> languages are sometimes overly restrictive and could be more helpful in some
> cases in terms of supporting the use of side effects.  However, I think that
> any attempt to reason from how traditional imperative languages work in this
> area is suspect, because they're just broken in that respect, and have paid
> almost no attention whatsoever to sensible management of mutation.  But it's
> difficult to reason about human factors in languages without involving
> traditional imperative languages.  The bottom line is we don't have good
> controls for proper experiments in this area, and we need to be very careful
> about how we reach conclusions.

That's true, but we could do a thought experiment where we took one 
group of non-programmers and tried to teach them BASIC and another group 
of non-programmers and tried to teach them Haskell and see which one has 
more trouble.  Do you doubt what the outcome would be?

> > > I agree that human factors are very important.
> >
> > Then why do you want to banish me to c.l.l. just because I brought them
> > up?
> 
> I don't want to banish *you*, just that part of the argument.  I like you.
> :)

Oh, whew!  :-)

> If you really want to have that discussion, it has to be based on something
> more verifiable than subjective experiences.  Otherwise, we may as well be
> discussing postmodernism.

Well, there is quite a bit of data out there on what programming 
languages people actually use.  The factors that go into those choices 
are, of course, complex, but surely the impedance match between the code 
and the brain has some influence in this regard.  Otherwise there is no 
way to account for the popularity of high level languages over machine 
language.  After all, most HLLs are strictly less powerful (in practice) 
than machine language.  (This is why you will often see snippets of 
assembler code in operating systems.)

rg
0
rNOSPAMon (1927)
10/8/2004 7:02:58 PM
In article <uzn2xysmh.fsf@STRIPCAPStelus.net>,
 Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
> >  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> > > > > Is this order better than leaving the order unspecified?
> > > > Yes.
> > > No. It is confusing as hell, and so it is better not to have to think 
> > > about
> > > it.
> > 
> > You didn't read the question.  It is confusing as hell, but a confusing 
> > order is better than none at all.  At least it makes program behavior 
> > deterministic.  But a simple OoE would, of course, be even better.
> 
> I did read the question and disagree. My point is that a sufficiently
> confusing specified order is effectively equivalent to having none specified
> at all, at least to the programmer's mental work load.
> 
> That is, if you can't think about it enough to make effective use of it, the
> practical consequence is that it does not exist.

No, the practical consequence is that it makes the behavior of (f (g) 
(h)) deterministic, which makes testing a useful technique for 
determining program correctness.

rg
0
rNOSPAMon (1927)
10/8/2004 7:05:23 PM
Ron Garret wrote:

> The problem with unspecified OoE is that it extends the same kind of
> nondeterminism that makes testing useless for MT code to any code that
> includes nested function calls.  

Can't a compiler print warnings for possible OoE dependencies?  
For critical code, you can then enforce a no-warnings 
policy.  

Andre
0
andre9567 (120)
10/8/2004 7:08:50 PM
Ron Garret wrote:
  
> Moreover, this is not just an
> unfortunate side effect of unspecified OoE, it is actually the INTENT.
> Unspecified OoE is supposed to FORCE you to think explicitly about
> possible OoE dependencies every time you write a nested function call,
> and holds the spectre of unpredictable potential disaster over your head
> as punishment if you get it wrong.  

I would consider this a benefit.  You seem to be arguing in favor 
of "accidentally correct" code, "confirmed correct" by testing.

As I see it:

  Accidentally correct code isn't.
  Testing for correctness usually doesn't.

I would argue that someone who is not aware of how to 
handle order dependencies should not be in the business of writing 
critical code.  As I mentioned in a previous message, a good compiler
can probably emit warnings where order dependencies may be present.  
You might decide to ignore these (e.g., for certified, proven correct 
referentially transparent algorithms that might use mutation 
internally), but presumably only if you know very well what you
are doing.

Andre
0
andre9567 (120)
10/8/2004 7:21:45 PM
"Stephan Houben" <shmjhouben@yahoo.com> wrote:
> A related question which perhaps somebody here might be able to answer:
> How much does the unspecified order of evaluation actually help in
> compilation?

Something on the order of 5%.  It depends on both the program being
compiled and on various properties of the compiler.

> Would a fixed left-to-right order give a factor 1.01
> or  a factor 10 increase in runtime?

More than 1.01, much less than 10.  Probably about 1.05.

> Would there be any fixed order
> clearly more efficient from an implementation point of view?

Yes.  Left-to-right evaluation is one of the least efficient
fixed orders of evaluation.  On the other hand, the order of
evaluation that people appear to have in mind when they talk
about left-to-right evaluation is one of the more efficient
fixed orders of evaluation.

That's one of the more interesting things I have learned from
this thread.  There have been four formal examples of what
people mean by left-to-right evaluation.  In each of those
four examples, what they mean is that arguments are evaluated
from left to right, followed by the procedure.

Here are the four examples, quoted verbatim.

Example 1:

Nonsense.  All we're arguing over is whether

(f (g) (h))

ought to mean:

(let ( (x (g))
       (y (h)) )
  (f x y))

or

(let* ( (x (g))
        (y (h)) )
  (f x y))


Example 2:

No, the decision on which order to put the arguments is dictated by the 
API of F.  What is not possible is to know in general is whether it was 
OK for me to write (f (g) (h)), or whether it was necessary instead for 
me to write (let* ( (x (g)) (y (h)) ) (f x y)).


Example 3:

Which is still true under fixed OoE, only there the question is, is it
okay to write (f (g) (h)) versus (let* ((y (h)) (x (g))) (f x y))


Example 4:

True.  But so what?  The fact you are getting at is /obvious/ because
you rearranged the order of evaluation and order of evaluation matters
in languages with effects.  The correct (and easy) fix is to write:

   (let* ((var0 <expression0>)
          (var1 <expression1>))
      (foo var0 var1 <expression2>)))


This last example is ambiguous as to whether the procedure is evaluated
before or after the third argument.  I suspect, however, that the
author of this example wanted the argument to be evaluated before the
procedure, rather than to have the procedure evaluated after the first
two arguments but before the third.

These examples illustrate the difficulty of applying the Law of Least
Astonishment.  Should we standardize on what people say they expect?
Or should we standardize on what they actually expect?

Will
0
cesuraSPAM (401)
10/8/2004 7:36:29 PM
> > > But expressiveness has nothing whatever to do with it.  This is simply a 
> > > turf battle between LET and LET* over the syntactic sugar of nested 
> > > function calls.
> > 
> > If this were true, it should be an easy battle to resolve.
> > (As I will attempt to show if Garret's assertion is shown
> > to be true.)
> > 
> > But is Ron Garret's assertion actually true?
> 
> Why would you doubt it?
> 
> rg

Because several people who advocate a fixed order of evaluation
have explicitly denied that it is merely a turf battle over the
tastiest syntactic sugar.  Several of them have explicitly said
that their goal is to do away with indeterminate order of
evaluation, not merely to make indeterminate order of evaluation
more difficult to express.

It is not unheard of for people to deny their true motives, but
I see no reason to doubt them in this case.

On the other hand, you and several others have given me concrete
reason to doubt whether you really expect left-to-right evaluation.
I quoted that evidence in my response to Stephan Houben.

Will
0
cesuraSPAM (401)
10/8/2004 7:43:15 PM
cesuraSPAM@verizon.net (William D Clinger) writes:

> Example 4:
> 
> True.  But so what?  The fact you are getting at is /obvious/ because
> you rearranged the order of evaluation and order of evaluation matters
> in languages with effects.  The correct (and easy) fix is to write:
> 
>    (let* ((var0 <expression0>)
>           (var1 <expression1>))
>       (foo var0 var1 <expression2>)))
> 
> 
> This last example is ambiguous as to whether the procedure is evaluated
> before or after the third argument.  I suspect, however, that the
> author of this example wanted the argument to be evaluated before the
                                                             ^^^^^^ after
> procedure, rather than to have the procedure evaluated after the first
> two arguments but before the third.

That would have been me (and your suspicion is right even though you
misstated it).

To clarify: I did not even think about the procedure.  My brain is
wired for ML these days, so having an identifier in procedure position
means that it does not matter when it is being evaluated.  In Scheme
that is generally not true because in Scheme identifiers are not
syntactic values.

Anyway, what I meant was strictly-left-to-right.  Had the example been
rendered more generally as

    (<e0> <e1> <e2> <e3>)

then I would have recommended using

    (let* ((v0 <e0>) (v1 <e1>) (v2 <e2>) (v3 <e3>)) (v0 v1 v2 v3))

-- of course, assuming v0..v3 are fresh.

Matthias
0
find19 (1244)
10/8/2004 7:57:10 PM
In article <fb74251e.0410081143.4536bb2b@posting.google.com>,
 cesuraSPAM@verizon.net (William D Clinger) wrote:

> > > > But expressiveness has nothing whatever to do with it.  This is simply 
> > > > a 
> > > > turf battle between LET and LET* over the syntactic sugar of nested 
> > > > function calls.
> > > 
> > > If this were true, it should be an easy battle to resolve.
> > > (As I will attempt to show if Garret's assertion is shown
> > > to be true.)
> > > 
> > > But is Ron Garret's assertion actually true?
> > 
> > Why would you doubt it?
> > 
> > rg
> 
> Because several people who advocate a fixed order of evaluation
> have explicitly denied that it is merely a turf battle over the
> tastiest syntactic sugar.  Several of them have explicitly said
> that their goal is to do away with indeterminate order of
> evaluation, not merely to make indeterminate order of evaluation
> more difficult to express.
> 
> It is not unheard of for people to deny their true motives, but
> I see no reason to doubt them in this case.

I do.  There's no way to prevent someone from adding a non-deterministic 
binding macro to the language if they want it, even if the core language 
is completely deterministic.  I suspect that when you point this out to 
those who think they want to completely eliminate nondeterministic 
binding that they will realize that they simply haven't thought it 
through.

> On the other hand, you and several others have given me concrete
> reason to doubt whether you really expect left-to-right evaluation.
> I quoted that evidence in my response to Stephan Houben.

I've said this before, I'll say it again: my personal preference would 
be for left-to-right, but I can think of no principled argument to 
prefer this order over right-to-left.  I would be perfectly happy with 
either one.  The main thing I want is for nested function calls to 
behave deterministically.

rg
0
rNOSPAMon (1927)
10/8/2004 7:59:09 PM
In article <4166E5C2.4041BBB0@het.brown.edu>,
 Andre <andre@het.brown.edu> wrote:

> Ron Garret wrote:
> 
> > The problem with unspecified OoE is that it extends the same kind of
> > nondeterminism that makes testing useless for MT code to any code that
> > includes nested function calls.  
> 
> Can't a compiler print warnings for possible OoE dependencies?  

Sure, but you'll get a lot of false positives, especially if some of the 
functions you are calling are in precompiled libraries.

> For critical code, you can then enforce a no-warnings 
> policy.  

You could also enforce a policy of no nested function calls at all.  
That would also "solve" the problem.

rg
0
rNOSPAMon (1927)
10/8/2004 8:06:26 PM
In article <4166E8C9.DD5F70C2@het.brown.edu>,
 Andre <andre@het.brown.edu> wrote:

> Ron Garret wrote:
>   
> > Moreover, this is not just an
> > unfortunate side effect of unspecified OoE, it is actually the INTENT.
> > Unspecified OoE is supposed to FORCE you to think explicitly about
> > possible OoE dependencies every time you write a nested function call,
> > and holds the spectre of unpredictable potential disaster over your head
> > as punishment if you get it wrong.  
> 
> I would consider this a benefit.  You seem to be arguing in favor 
> of "accidentally correct" code, "confirmed correct" by testing.

I'd spin it differently, but that is essentially correct.  In fact, 
until someone figures out how to automatically generate provably correct 
code from specifications I'd say that producing "accidentally correct" 
code as you put it is in fact the only practical way to produce correct 
(or even working) code in general.

> As I see it:
> 
>   Accidentally correct code isn't.
>   Testing for correctness usually doesn't.

Really?  How do you determine if your code is correct then?

> I would argue that someone who is not aware of how to 
> handle order dependencies should not be in the business of writing 
> critical code.  As I mentioned in a previous message, a good compiler
> can probably emit warnings where order dependencies may be present.  
> You might decide to ignore these (e.g., for certified, proven correct 
> referentially transparent algorithms that might use mutation 
> internally), but presumably only if you know very well what you
> are doing.

Another way to "solve" this problem is to write all critical code in 
unlambda.

rg
0
rNOSPAMon (1927)
10/8/2004 8:13:38 PM
Joe Marshall wrote:
> Thant Tessman <thant@acm.org> writes:
> 
> 
>>Joe Marshall wrote:
>>
>>>Thant Tessman <thant@acm.org> writes:
>>
>>[...]
>>
>>
>>>>But you don't know if the programmer's intention was to rely on fixed
>>>>order of evaluation even in the unspecified case.
>>>
>>>Sure I do.  Their intent was to *not* rely on it.  If their intent
>>>were to rely on it, they'd be deliberately writing bogus code.
>>
>>You are assuming that the programmer knows OofE is unspecified. In other
>>words, you are assuming exactly what it is I claim you don't know.
> 
> 
> I certainly assume that if the programmer is programming in Scheme,
> then he knows Scheme.  If we assume that the programmer is unfamiliar
> with the language he is using, then order of evaluation is the least
> of our worries.

There are very few experts in any language. Favoring an aspect of a 
language for its ability to punish an incorrect guess is no way to 
design a programming language.

-thant

0
thant (332)
10/8/2004 8:35:52 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

>> >> Unspecified order:
>> >>   Assuming a correct program, this implies that the program does not
>> >>   depend upon argument order.
>> >> 
>> >> Specified order:
>> >>   Assuming a correct program, this says nothing about whether the
>> >>   program depends upon argument order.
>> >> 
>> >> So by specifying the order of evaluation, we introduce ambiguity:  was
>> >> the intent of the programmer to depend upon the order?  It is
>> >> therefore *harder* to understand.
>> >
>> > Your conclusion follows only if we have a way to tell a priori if the 
>> > program is correct.  
>> 
>> Hence the word `assume' at the beginning of each clause.
>
> You can assume a spherical sheep too, but that won't help you much if 
> your task is to shear a real sheep.

I sure hope that correct programs are more common than spherical
sheep.

Are we to assume, then, that the point of specifying the order of
evaluation will help us with incorrect programs? 

> Permit me to introduce you to the concept of "testing".

Please do!  I've heard of such a thing, but since I assume that I'm
supposed to write correct programs....

> Imagine you are an engineer on a large project.  You have access to G 
> and H and their documentation, but not their source code.  According to 
> the documentation, it is safe to write (f (g) (h)).  Does that mean it 
> is in fact safe to write (f (g) (h))?  No.  The documentation could be 
> wrong.

Ok, we assume that the documentation is in error.

> So how can you really tell if it's safe to write (f (g) (h))?  

I cannot.

> Well, one way is to write it, run the resulting code, and see if it
> does what you want.  This is known in the trade as "testing".

This tells me it worked once.

> But, of course, what you really care about is not whether the program 
> works during testing.  What you really care about in industrial settings 
> is whether the program works in production.  The utility of testing is 
> predicated on the fact that under certain circumstances the behavior of 
> computer programs is deterministic and hence reliably reproducible.  
> When those circumstances do not apply (e.g. in multithreaded systems) 
> the utility of testing is greatly reduced, to the chagrin of developers 
> everywhere trying to hunt down weird deadlock bugs.

Ok, so let us assume that the order of evaluation is specified.  Is it
*now* safe to write (f (g) (h))?  You still don't know.  You can test
it, but still....

> Unspecified OoE is supposed to FORCE you to think explicitly about 
> possible OoE dependencies every time you write a nested function call, 
> and holds the spectre of unpredictable potential disaster over your head 
> as punishment if you get it wrong.  And for all that, unspecified OoE 
> provides you no benefit whatsoever. 

I don't make that claim.  I see no benefit to a hard landing.  I see
no benefit to a probabilistic chance of a soft landing.  An
unspecified order is like flipping a coin.  A specified order is like
flipping a double-headed coin.  But the problem is that *someone else*
is calling it.  There's no benefit to using a double-headed coin ---
it doesn't make things more predictable in the ideal case, and it
enables cheating in the worst case.

So what about that Mercury mode thing? 
0
jrm (1310)
10/8/2004 8:48:06 PM
In article <acuxq6m1.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> There's no benefit to using a double-headed coin ---
> it doesn't make things more predictable in the ideal case,

Of course it does.  When I flip a double-headed coin I can confidently 
predict that it will come up heads.  (Actually, a better analogy is that 
if I flip a coin that has the same markings on both sides, then I can 
confidently predict that whatever came up on the first flip will also 
come up on all subsequent flips.)

> and it enables cheating in the worst case.

I think your analogy breaks down here.  The kind of cheating you can do 
with a double-headed coin involves gambling.  In that case, random 
behavior is manifestly a part of the objective.  That is usually not the 
case when it comes to programming.

> So what about that Mercury mode thing? 

I haven't had time to give it much thought.

rg
0
rNOSPAMon (1927)
10/8/2004 9:26:38 PM
Neelakantan Krishnaswami <neelk@cs.cmu.edu> wrote in message news:<slrncmddej.b4s.neelk@gs3106.sp.cs.cmu.edu>...
> I find it hard to believe that Scheme could, unfortunately. Mercury is
> pure, like Haskell, and as such has a degree of freedom in evaluation
> order that imperative languages like Scheme and ML lack. :(

I'm afraid you may be over-estimating the degree of freedom in
the evaluation order of Mercury.

First of all, modes impose a significant constraint on the
evaluation order. 

http://www.cs.mu.oz.au/research/mercury/information/doc-release/reference_manual_4.html#SEC39

Second, predicates may happen to be semi-pure or impure:
 "Impurity declarations"
http://www.cs.mu.oz.au/research/mercury/information/doc-release/reference_manual_15.html

which again affects the evaluation order.

Lastly, even the pure all-mode Mercury code can have an effect:
non-termination. Rearranging of conjuncts may turn a terminating
program into non-terminating, or vice versa. That's the reason for the
last sentence of the following paragraph from the manual cited
earlier:

"As well as providing the strict sequential operational semantics,
Mercury implementations may optionally provide additional
implementation-defined operational semantics, provided that any such
implementation-defined operational semantics are at least as complete
as the strict commutative operational semantics. An
implementation-defined semantics is "at least as complete" as the
strict commutative semantics if and only if the implementation-defined
semantics guarantees to compute an answer in finite time for any
program for which an answer would be computed in finite time for all
possible executions under the strict commutative semantics (i.e. for
all possible orderings of conjunctions and disjunctions)."

In general therefore, a program that terminates under the strict
sequential semantics may diverge under strict commutative semantics
(or under some particular schedules conforming to the commutative
semantics). Or vice-versa. The compiler may optimize away an infinite
loop or a call to exception__throw/1 if the compiler can detect the
infinite loop (Mercury is well-known for its excellent termination
checker) and find a schedule that avoids the loop or the exception. If
this is undesirable, the programmer can always assert the strict
sequential semantics.

Thus, as far as the evaluation order and dis-order are concerned,
there is less difference between Scheme and Mercury than
it may appear.
0
oleg8119 (112)
10/8/2004 11:15:35 PM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> Permit me to introduce you to the concept of "testing".

Permit us to introduce you to the concepts of test coverage,
computational complexity, and verification conditions.

The computational complexity of expression coverage is the
same with a fixed order of evaluation as it is with an
unspecified order of evaluation.

With a fixed order of evaluation, the computational complexity
of path coverage is generally infinite.  That infinite
complexity becomes exponentially worse with an unspecified
order of evaluation.

The computational complexity of verifying the kind of program
transformations that Joe has been talking about is the same
for a fixed order of evaluation as for an unspecified order
of evaluation, because the usual verification condition is the
same in either case: none of the expressions have side effects.

> The utility of testing is 
> predicated on the fact that under certain circumstances the behavior of 
> computer programs is deterministic and hence reliably reproducible.

Untrue.  In realistic settings, with a large or infinite number
of possible inputs, testing is a sampling technique.  Testing
is viable in nondeterministic as well as deterministic settings.
The advantage of determinism is that it tends to reduce the size
of the sample space.

Nondeterministic execution is not what we're talking about here.
We're talking about deliberately incomplete, precisely ambiguous
specifications, which have long been a standard technique in
software design and development.  Such specifications do indeed
shift the focus from execution-based testing to static verification
of contractual interfaces.

If testing is the only technique you understand, then you will not
only regard that shift as a bad thing, but as a self-evidently bad
thing, and you will argue on that basis.

> The claim that it makes the 
> language more expressive has been debunked in other postings.

By whom?  Bill Richter?

The expressive power of languages is an interesting subject, but
it is not a subject that average programmers understand very well,
and it is not a subject that you are likely to understand better
by reading this thread.

Will
0
cesuraSPAM (401)
10/9/2004 1:04:36 AM
William D Clinger wrote:

[...]

> The expressive power of languages is an interesting subject, but
> it is not a subject that average programmers understand very well,
> and it is not a subject that you are likely to understand better
> by reading this thread.

I can imagine both a more and less technical definition of "expressive." 
If by "expressive," one means the ability of a program to convey the 
intention of the programmer, unspecified OofE fails.

I don't know what a more technical definition of "expressive" might be, 
but I do know that given some program, it is more likely to be 
well-defined given fixed OofE than unspecified OofE. It's hard to 
imagine a definition of "expressive" worth taking seriously that 
attributed more "expressivity" to unspecified OofE than it did to fixed 
OofE.

-thant
0
thant (332)
10/9/2004 2:30:14 AM
An edited exchange between Ron Garret and myself:

RG> But expressiveness has nothing whatever to do with it.  This is simply a 
RG> turf battle between LET and LET* over the syntactic sugar of nested 
RG> function calls.

WC> If this were true, it should be an easy battle to resolve.

RG> ...There's no way to prevent someone from adding a non-deterministic 
RG> binding macro to the language if they want it, even if the core language 
RG> is completely deterministic.  I suspect that when you point this out to 
RG> those who think they want to completely eliminate nondeterministic 
RG> binding that they will realize that they simply haven't thought it 
RG> through.

I hope you're right.  If you are, and this is all about sugar,
then we can make everyone happy by designing the syntactic sugar.

If there is anyone who disagrees with Ron on this, please speak up!

Will
0
cesuraSPAM (401)
10/9/2004 3:10:50 AM
In article <fb74251e.0410081704.25f5f3@posting.google.com>,
 cesuraSPAM@verizon.net (William D Clinger) wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> > Permit me to introduce you to the concept of "testing".
> 
> Permit us to introduce you to the concepts of test coverage,
> computational complexity, and verification conditions.
> 
> The computational complexity of expression coverage is the
> same with a fixed order of evaluation as it is with an
> unspecified order of evaluation.

Well, I suppose that's true in theory, but it's a bit misleading...

> With a fixed order of evaluation, the computational complexity
> of path coverage is generally infinite.  That infinite
> complexity becomes exponentially worse with an unspecified
> order of evaluation.

Yes.  And in cases where the path coverage is not infinite, it still 
becomes exponentially worse with unspecified OoE.  Either way, that 
seems bad to me.

> The computational complexity of verifying the kind of program
> transformations that Joe has been talking about is the same
> for a fixed order of evaluation as for an unspecified order
> of evaluation, because the usual verification condition is the
> same in either case: none of the expressions have side effects.

I have from the beginning endorsed the idea of allowing the compiler to 
rearrange the OoE in cases where the program semantics can be proven not 
to change.  The case where none of the expressions have side effects 
would be the most common, most useful, and easiest to implement of those 
cases.

> > The utility of testing is 
> > predicated on the fact that under certain circumstances the behavior of 
> > computer programs is deterministic and hence reliably reproducible.
> 
> Untrue.  In realistic settings, with a large or infinite number
> of possible inputs, testing is a sampling technique.  Testing
> is viable in nondeterministic as well as deterministic settings.
> The advantage of determinism is that it tends to reduce the size
> of the sample space.

I don't see how that in any way contradicts what I said.

> Nondeterministic execution is not what we're talking about here.
> We're talking about deliberately incomplete, precisely ambiguous
> specifications, which have long been a standard technique in
> software design and development.  Such specifications do indeed
> shift the focus from execution-based testing to static verification
> of contractual interfaces.
> 
> If testing is the only technique you understand, then you will not
> only regard that shift as a bad thing, but as a self-evidently bad
> thing, and you will argue on that basis.

It is not the only technique I understand.  It is nonetheless a useful 
technique, and not one to be abandoned lightly IMO.


> > The claim that it makes the 
> > language more expressive has been debunked in other postings.
> 
> By whom?  Bill Richter?

No, by me.  I have pointed out that nondeterministic OoE can be 
implemented/expressed in other ways (e.g. by specifying that LET has an 
unspecified OoE, or by introducing a new binding construct that has an 
unspecified OoE).  I have even posted a concrete proposal on how to 
modify the language that I think would make everyone happy.  So far no 
one has responded to any of those postings.  (See e.g. message id 
rNOSPAMon-53FCD0.16504007102004%40nntp1.jpl.nasa.gov)

And I take being compared to Bill Richter (especially by you) as an 
insult of the highest order.  I don't think I've done or said anything 
remotely deserving of that.

> The expressive power of languages is an interesting subject, but
> it is not a subject that average programmers understand very well,
> and it is not a subject that you are likely to understand better
> by reading this thread.

Unlike Bill Richter I do not automatically assume that my credentials 
necessarily imbue me with any actual understanding.  I would, however, 
appreciate it if you would give me the benefit of the doubt that the 
information contained in this thread does not represent the totality of 
my knowledge on the subject unless you have some actual evidence to the 
contrary.

rg
0
rNOSPAMon (1927)
10/9/2004 4:51:15 AM
Just by the way, do the folks here advocating an unfixed
order of evaluation specifically because it punishes something
they find offensive or consider poor style think that no
parking zones ought to contain hidden, position-varying
landmines?  Because the thinking seems very similar to me.

				Bear
   (in favor of at least having the landmines visible and
	in fixed places).



0
bear (1219)
10/9/2004 5:14:20 AM
cesuraSPAM@verizon.net (William D Clinger) writes:

> An edited exchange between Ron Garret and myself:
> 
> RG> But expressiveness has nothing whatever to do with it.  This is simply a 
> RG> turf battle between LET and LET* over the syntactic sugar of nested 
> RG> function calls.
> 
> WC> If this were true, it should be an easy battle to resolve.
> 
> RG> ...There's no way to prevent someone from adding a non-deterministic 
> RG> binding macro to the language if they want it, even if the core language 
> RG> is completely deterministic.  I suspect that when you point this out to 
> RG> those who think they want to completely eliminate nondeterministic 
> RG> binding that they will realize that they simply haven't thought it 
> RG> through.
> 
> I hope you're right.  If you are, and this is all about sugar,
> then we can make everyone happy by designing the syntactic sugar.
> 
> If there is anyone who disagrees with Ron on this, please speak up!

Given that Scheme already has LET, which has an unspecified order of
evaluation for bindings, and LET*, which has a specified order, then we
already have ways of expressing both unspecified and specified orders of
evaluation; the complaints are that the order is unspecified rather than
specified in some cases.  (I use the term "specified" instead of
"deterministic" since implementations are individually likely to be
deterministic in their implementation of unspecified ordering, just not
all deterministic in the same way.)  Just for clarity, when I talk about
order of evaluation below, I'm specifically talking about order of
evaluation of function arguments.

I've been having trouble buying the "principle of least surprise"
argument given how clearly R5RS states that evaluation order is
unspecified.  Programmers who are surprised by this behavior are
programmers who have not bothered to learn the language they are using.
I personally have never been surprised by this behavior myself, but I'm
also used to using other languages (such as C) that do not guarantee a
specific order of evaluation.  so I am not in the habit of depending on
it.  I also think that sometimes, a programmer who is surprised by his
program's behavior is a programmer who is about to learn something
important about programming.

Personally, I have simply learned to shy away from the kinds of uses of
side effects that behave differently under different orders of
evaluation, and when use of side effects seems the most clear or
expedient solution, it's better to express the ordering of side effects
as obviously as possible because this results in clearer and less
error-prone programs, not because I was "punished" by experiences with
undependable evaluation order.  I don't see the choice of leaving
evaluation order unspecified (and more importantly, that implementors
have chosen different implementations) as an attempt to punish
programmers for certain programming methods.  At worst, a programmer who
persists in doing something that causes him problems is only punishing
himself.

I am curious whether the choice of leaving the order of evaluation
unspecified in the Scheme standard was motivated by wanting to give
implementors more freedom, or just because there was no consensus among
implementors on which order to use.  Obviously some languages (like C)
have chosen to leave evaluation order unspecified, and others (like
Java) specify it, which at least indicates there is no widespread
agreement among all language designers as to which choice is right.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/9/2004 8:44:08 AM
Ray Dillinger <bear@sonic.net> writes:

> Just by the way, do the folks here advocating an unfixed
> order of evaluation specifically because it punishes something
> they find offensive or consider poor style think that no
> parking zones ought to contain hidden, position-varying
> landmines?  Because the thinking seems very similar to me.
> 
> 				Bear
>    (in favor of at least having the landmines visible and
> 	in fixed places).

If the intent was to put in hidden land mines as an attempt to punish a
purportedly poor practice, then why does the Scheme standard make the
land mines visible by so clearly stating that the order of evaluation of
function arguments is unspecified?  (See the multiple paragraphs on the
topic in the section "Procedure calls" in R5RS.)  It also seems the
intent of the standard in leaving this unspecified was pragmatic rather
than ideological.

There are an awful lot of places in R5RS where behaviors in specific
situations are left unspecified, and hence opportunities for a naive
programmer to think one particular implementation's choice for how to
implement an unspecified behavior is how all implementations work, and
thus write a program that behaves differently in a different Scheme
implementation.  When that happens, is that naive programmer really
being punished by anyone, or is he just a victim of his own naivete?

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/9/2004 9:18:23 AM
Ray Dillinger <bear@sonic.net> writes:

> Just by the way, do the folks here advocating an unfixed
> order of evaluation specifically because it punishes something
> they find offensive or consider poor style think that no
> parking zones ought to contain hidden, position-varying
> landmines?  Because the thinking seems very similar to me.

I agree with you. I'm a poor simple boy and I don't have much book
learnin' but it seems to me that a fixed order, and left to right to
boot, would just simplify at the expense of nothing.

Maybe I've got it wrong but this thread hasn't enlightened me at all.

Can somebody do a simple enumeration of the reasons why fixed OoE is
bad?


Nic Ferrier
0
nferrier (66)
10/9/2004 11:46:04 AM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> > > The utility of testing is 
> > > predicated on the fact that under certain circumstances the behavior of 
> > > computer programs is deterministic and hence reliably reproducible.
> > 
> > Untrue.  In realistic settings, with a large or infinite number
> > of possible inputs, testing is a sampling technique.  Testing
> > is viable in nondeterministic as well as deterministic settings.
> > The advantage of determinism is that it tends to reduce the size
> > of the sample space.
> 
> I don't see how that in any way contradicts what I said.

Had you written "assisted by" instead of "predicated on", your
statement would have been true.

> And I take being compared to Bill Richter (especially by you) as an 
> insult of the highest order.  I don't think I've done or said anything 
> remotely deserving of that.

I didn't realize I was comparing you to Bill Richter.  I was and
remain quite aware that you have not debunked the claim you said
had been debunked, so it didn't occur to me that you thought you
had been the debunker.

> Unlike Bill Richter I do not automatically assume that my credentials 
> necessarily imbue me with any actual understanding.  I would, however, 
> appreciate it if you would give me the benefit of the doubt that the 
> information contained in this thread does not represent the totality of 
> my knowledge on the subject unless you have some actual evidence to the 
> contrary.

I thought you were joking when you wrote "Permit me to introduce
you to the concept of "testing".", and wrote my response in the
same spirit to see whether you were willing to take the kind of
joke you had dished out.  Evidently not.

Will
0
cesuraSPAM (401)
10/9/2004 3:08:02 PM
Nic Ferrier <nferrier@tapsellferrier.co.uk> writes:

> Can somebody do a simple enumeration of the reasons why fixed OoE is
> bad?


Here you go:
0
find19 (1244)
10/9/2004 3:10:47 PM
Hi, Steve.  Nice post.

Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:
> I am curious whether the choice of leaving the order of evaluation
> unspecified in the Scheme standard was motivated by wanting to give
> implementors more freedom, or just because there was no consensus among
> implementors on which order to use.  Obviously some languages (like C)
> have chosen to leave evaluation order unspecified, and others (like
> Java) specify it, which at least indicates there is no widespread
> agreement among all language designers as to which choice is right.

Scheme is derived from Carl Hewitt's actor model of
nondeterministic concurrent computation.  The use of
sequential evaluation in Steele and Sussman's first Scheme
interpreter was a pragmatic choice, made because they
wanted to focus on the message passing, tail recursive,
and CPS aspects of the actor model.

In the early years of Scheme, parallel (concurrent) order
of evaluation of arguments was considered legitimate, as
in the actor model.  Several such implementations of Scheme
have actually been constructed, and were used to develop
the concept of a "future".

IIRC, parallel evaluation of arguments was first ruled out
in the RRRS, which required the evaluation to be consistent
with some sequential order.  This change was made at the
insistence of people who were worried about side effects
and mutual exclusion in random number generators and other
stateful procedures.  This change was opposed by people who
were more interested in exterminating side effects.

The subsequent history of this issue has been marked by a
steady decline in the influence of those who regard Scheme
as a mostly functional language that allows side effects
provided the programmers are super-careful, accompanied by
a corresponding rise in the influence of those who regard
side effects as normal.

Perhaps this history is just a healthy reflection of Scheme's
as-yet-incomplete transition from academic research language
to industrial applications language.

Will
0
cesuraSPAM (401)
10/9/2004 3:37:26 PM
In article <fb74251e.0410090708.743dc83f@posting.google.com>,
 cesuraSPAM@verizon.net (William D Clinger) wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> > > > The utility of testing is 
> > > > predicated on the fact that under certain circumstances the behavior of 
> > > > computer programs is deterministic and hence reliably reproducible.
> > > 
> > > Untrue.  In realistic settings, with a large or infinite number
> > > of possible inputs, testing is a sampling technique.  Testing
> > > is viable in nondeterministic as well as deterministic settings.
> > > The advantage of determinism is that it tends to reduce the size
> > > of the sample space.
> > 
> > I don't see how that in any way contradicts what I said.
> 
> Had you written "assisted by" instead of "predicated on", your
> statement would have been true.

Ah.

> I was and
> remain quite aware that you have not debunked the claim you said
> had been debunked, so it didn't occur to me that you thought you
> had been the debunker.

(f (g) (h)) under r5rs semantics can be expressed as (let ((x (g)) (y 
(h))) (f x y)).  Therefore, changing function calls to fixed OoE does 
not result in any loss of expressive power, since a function call with 
unspecified OoE can be written as a LET.  Q.E.D.

> I thought you were joking when you wrote "Permit me to introduce
> you to the concept of "testing"."

No, I was being ironic, but your point is well taken.

rg
0
rNOSPAMon (1927)
10/9/2004 5:25:53 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> (f (g) (h)) under r5rs semantics can be expressed as (let ((x (g)) (y 
> (h))) (f x y)).  Therefore, changing function calls to fixed OoE does 
> not result in any loss of expressive power, since a function call with 
> unspecified OoE can be written as a LET.  Q.E.D.

In Scheme, it's also widely regarded that the two forms below are
equivalent in behavior (and in fact LET is often implemented as a macro
converting the first to the second, which is allowable since it is
specified as "library syntax" in R5RS):

(let ((x (g)) (y (h))) (f x y))

((lambda (x y) (f x y)) (g) (h))

The reason that LET performs bindings in unspecified order is a direct
consequence of function arguments being evaluated in unspecified order.

Sure, perhaps the order of function argument evaluation could be
specified while LET binding order could remain unspecified, but then
these two forms that everyone has learned to treat as equivalent no
longer would be.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/9/2004 8:48:45 PM
cesuraSPAM@verizon.net (William D Clinger) writes:

> In the early years of Scheme, parallel (concurrent) order
> of evaluation of arguments was considered legitimate, as
> in the actor model.  Several such implementations of Scheme
> have actually been constructed, and were used to develop
> the concept of a "future".

This explains a lot.

It seems like a very valid reason not to specify OoE.



Nic
0
nferrier (66)
10/10/2004 12:07:52 AM
In article <87zn2vy5w2.fsf@localhost.efn.org>,
 Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > (f (g) (h)) under r5rs semantics can be expressed as (let ((x (g)) (y 
> > (h))) (f x y)).  Therefore, changing function calls to fixed OoE does 
> > not result in any loss of expressive power, since a function call with 
> > unspecified OoE can be written as a LET.  Q.E.D.
> 
> In Scheme, it's also widely regarded that the two forms below are
> equivalent in behavior (and in fact LET is often implemented as a macro
> converting the first to the second, which is allowable since it is
> specified as "library syntax" in R5RS):
> 
> (let ((x (g)) (y (h))) (f x y))
> 
> ((lambda (x y) (f x y)) (g) (h))
> 
> The reason that LET performs bindings in unspecified order is a direct
> consequence of function arguments being evaluated in unspecified order.
> 
> Sure, perhaps the order of function argument evaluation could be
> specified while LET binding order could remain unspecified, but then
> these two forms that everyone has learned to treat as equivalent no
> longer would be.

No, the would just no longer be *necessarily* equivalent.  An 
implementation would still be free to implement them as equivalent.

Also, the fact that they are no longer necessarily equivalent would be a 
feature, as then LET would actually add expressiveness to the language 
whereas currently it does not.

rg
0
rNOSPAMon (1927)
10/10/2004 4:29:38 AM
Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <87zn2vy5w2.fsf@localhost.efn.org>,
>  Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:

> > (let ((x (g)) (y (h))) (f x y))
> > 
> > ((lambda (x y) (f x y)) (g) (h))

> No, the would just no longer be *necessarily* equivalent.  An 
> implementation would still be free to implement them as equivalent.

> Also, the fact that they are no longer necessarily equivalent would be a 
> feature, as then LET would actually add expressiveness to the language 
> whereas currently it does not.

Every item of syntax and every procedure marked "library" in R5RS
technically does not add expressiveness to the language; library syntax
and procedures can always be implemented in terms of the essential
syntax and procedures.  If you think it's OK to modify the semantics of
LET to make it behave in a subtly different way than the use of LAMBDA,
does that also mean that, for example, some special semantics should be
assigned to COND to make it behave in a subtly different way than its
translation into IF epressions to "add expressiveness" to the language?
If we don't want to introduce hidden landmines into the language, it
seems we'll plant a lot more of them by introducing such subtle
inconsistencies in the name of "expressiveness" than by accepting a
particular lack of specification of evaluation order.

As Scheme is currently specified, both LET and LET* are library syntax,
and they can both be implemented using only LAMBDA as the underlying
binding construct.  Isn't it interesting that a function as expressed
through LAMBDA has unspecified, possibly even unsequenced and
nondeterministic, order of evaluation for its arguments, and yet this
same LAMBDA can be used to express both unsequenced and sequenced
evaluation?  What you're proposing to do is change a fundamental part of
Scheme.  This is why I look so skeptically at your proposal,
particularly when the distinction you want to express is already easily
expressible in Scheme.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/10/2004 7:58:56 AM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Joe Marshall <jrm@ccs.neu.edu> writes:
> > Since no one here actually intends to *rely* on the order, who cares
> > what that order is?  Or do you intend to rely on it?
> 
> Example: if specified as left-to-right in the language, then it is natural and
> robust to do things like:
> 
>   (let ((itr (create-iterator ...)))
>     ; Show the first 3 items
>     (print (next itr) (next itr) (next itr)))
> 
> I find myself swayed back to the unsepcified order of things, however. The
> reason is that I want LAMBDA to be the backbone of everything. If we can't
> specify LET in terms of LAMBDA, then our language spirit is very different.

I don't see why LET couldn't be defined in terms of LAMBDA if the
order of evaluation is fixed?


Bj�rn
0
d95-bli (130)
10/10/2004 11:21:25 AM
In article <87vfdjxav3.fsf@localhost.efn.org>,
 Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > In article <87zn2vy5w2.fsf@localhost.efn.org>,
> >  Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:
> 
> > > (let ((x (g)) (y (h))) (f x y))
> > > 
> > > ((lambda (x y) (f x y)) (g) (h))
> 
> > No, the would just no longer be *necessarily* equivalent.  An 
> > implementation would still be free to implement them as equivalent.
> 
> > Also, the fact that they are no longer necessarily equivalent would be a 
> > feature, as then LET would actually add expressiveness to the language 
> > whereas currently it does not.
> 
> Every item of syntax and every procedure marked "library" in R5RS
> technically does not add expressiveness to the language; library syntax
> and procedures can always be implemented in terms of the essential
> syntax and procedures.

Just because something *can* be implemented in terms of something else 
that alone does not mean that no expressiveness has been added.  
Otherwise Scheme would be no more expressive than a Turing machine.

> If you think it's OK to modify the semantics of
> LET to make it behave in a subtly different way than the use of LAMBDA,
> does that also mean that, for example, some special semantics should be
> assigned to COND to make it behave in a subtly different way than its
> translation into IF epressions to "add expressiveness" to the language?

If there were a good reason to make that change, sure.  Otherwise not.  
I do not advocate making things different for the sake of making them 
different.

> If we don't want to introduce hidden landmines into the language, it
> seems we'll plant a lot more of them by introducing such subtle
> inconsistencies in the name of "expressiveness" than by accepting a
> particular lack of specification of evaluation order.

But expressiveness is all about subtle inconsistencies.  That is 
precisely the grounds on which those who advocate R5RS semantics argue 
their case.

> As Scheme is currently specified, both LET and LET* are library syntax,
> and they can both be implemented using only LAMBDA as the underlying
> binding construct.  Isn't it interesting that a function as expressed
> through LAMBDA has unspecified, possibly even unsequenced and
> nondeterministic, order of evaluation for its arguments, and yet this
> same LAMBDA can be used to express both unsequenced and sequenced
> evaluation?

The situation would be no different under my proposal.  Both LET and 
LET* could (and probably would) still be library syntax.  And both 
sequenced and unsequenced evaluation could (and probably would) still be 
expressible using (deterministic) LAMBDA.

By the way, it's not necessary to usurp LAMBDA to satisfy me.  I'd be 
perfectly content with adding a DLAMBDA (deterministic lambda) such that:

(define x (dlambda (...) ...))
(x ...) 

produced deterministic evaluation, provided that dlambda were no less 
efficient than lambda.  But my guess is that that would render the 
denotational semantics of the language unacceptably complicated.  (I 
don't know nearly enough about DS to be able to assess that.)

> What you're proposing to do is change a fundamental part of
> Scheme.  This is why I look so skeptically at your proposal,
> particularly when the distinction you want to express is already easily
> expressible in Scheme.

No, it's not so easily expressible.  It requires writing a LOT more code 
to get deterministic evaluation, which undermines one of the principal 
motivations for using a high level language in the first place.  You are 
right to be skeptical of any proposal to change the fundamental 
semantics of the language, but I believe that this particular "feature" 
of Scheme renders it unsuitable for safety-critical applications.  (I 
feel the same way about Python's syntactically significant white space.)

rg
0
rNOSPAMon (1927)
10/10/2004 4:58:57 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> But expressiveness is all about subtle inconsistencies.  That is 
> precisely the grounds on which those who advocate R5RS semantics argue 
> their case.

Expressivness ought to be about _clearly_ expressing subtle
distinctions.  A subtle distinction expressed in a subtle fashion makes
it difficult for a reader to understand the distinction.

> The situation would be no different under my proposal.  Both LET and 
> LET* could (and probably would) still be library syntax.  And both 
> sequenced and unsequenced evaluation could (and probably would) still be 
> expressible using (deterministic) LAMBDA.

How do you think you would express unspecified evaluation order using
procedure application with specified order of evaluation?  I'm having a
hard time coming up with how to do that myself.

The reason that it's currently possible to express both unspecified and
specified orders of evaluation using procedure application with
unspecified order of evaluation of arguments is that the body of a
LAMBDA is evaluated only after all the parameter names are bound.  LET
can be expressed using a LAMDBA with multiple parameters

((lambda (x y z) body) a b c)

while LET* uses nested LAMBDAs:

((lambda (x) ((lambda (y) ((lambda (z) body) c)) b)) a)

> No, it's not so easily expressible.  It requires writing a LOT more code 
> to get deterministic evaluation, which undermines one of the principal 
> motivations for using a high level language in the first place.  You are 
> right to be skeptical of any proposal to change the fundamental 
> semantics of the language, but I believe that this particular "feature" 
> of Scheme renders it unsuitable for safety-critical applications.  (I 
> feel the same way about Python's syntactically significant white space.)

The vast majority of procedure applications in real Scheme programs (and
in other languages) do not require any specific order of evaluation for
arguments since it is uncommon for programmers to use argument
expressions containing side effects that would cause the order of
evaluation to make a difference.  So the common case has the simplest
expression, which is certainly a virtue in a high-level language.  If
the order of evaluation of your procedure arguments really does make a
difference, then making it explicitly clear that it does so is also
highly desirable, and using a construct that ensures the desired order
of evaluation is also worth it, even if it takes more space.

I could see arguing that Scheme might be unsuitable for safety-critical
applications if it had poorly-defined semantics or a lack of ability to
control sequencing of evaluation under all circumstances.  But Scheme
does have better-defined semantics than many other languages, and it
does have the ability to control sequencing of evaluation.  Once again,
you are not complaining because Scheme does not allow you to do
something you want to do; you are complaining because Scheme chooses a
default behavior that you don't like.

What I think would be more important for producing good safety-critical
applications is for the programmer(s) to have a solid understanding of
both the application they are programming and the language they are
using to program it.  As I said before, I can't see any reason for any
Scheme programmer _who has actually bothered to study the language_ to
be surprised by the unspecified order of evaluation of procedure
arguments.  This is not some behavior of the language buried in an
appendix; it is laid out explicitly in the description of procedure
calls.  The argument that unspecified evaluation order is capable of
breeding subtle bugs seems to be based mainly on an assumption that
programmers are dumb.

I might also note that the laws of physics seem to be fundamentally
non-deterministic in certain ways.  I guess I could also argue that the
universe seems unsuitable for safety-critical applications.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/11/2004 5:50:51 AM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:

> Expressivness ought to be about _clearly_ expressing subtle
> distinctions.  A subtle distinction expressed in a subtle fashion makes
> it difficult for a reader to understand the distinction.

This is one of the best-articulated arguments against using procedure
call syntax for specifying the programmer's belief that the order of
evaluation of certain terms does not matter.
0
find19 (1244)
10/11/2004 12:32:06 PM
Thant Tessman <thant@acm.org> writes:
> Anton van Straaten wrote:
> > you're thinking only of the behavior of the program, and not of what the
> > code expresses to human readers, or to tools. [...]
> 
> I'm actually thinking of both, and thought I'd made that point
> several times by now. You claim the use of a function call implies
> the programmer  is consciously communicating their intention that the
> arguments are evaluation-order independent. ... Yet I've *never*
> assumed that the use of a function call communicated this fact about
> my code. I  honestly don't think there are more than two or three of
> you out there who do. And while I think there is no language that
> surpasses Scheme in the number of opportunities it provides to
> refactor code, I've *never* relied on what unspecified OofE implies
> about the code to do so. 

Well I'm one who does count on unspecified order, explicitly and
implicitly communicated for correctness. In fact I would venture that
the opposite of your assertion is true. Most people implicitly use the
fact that arg eval order is unspecified *all the time*. Every time you
lift an expression into an enclosing let it happens (Yes, this is
manual CSE). I would, in fact, generally be surprised is performing such
a lift caused a bug in the code, yet all the cases which have been put
forth in favor of specified order would cause such bugs.

david rush
-- 
I repeat myself when under stress. I repeat myself when under
stress. I repeat myself when under stress. I repeat myself when
under stress. I repeat myself when under stress. I repeat myself
when under stress. I repeat myself when under stress. I repeat
0
kumoyuki (163)
10/11/2004 3:35:58 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
>
>> Expressivness ought to be about _clearly_ expressing subtle
>> distinctions.  A subtle distinction expressed in a subtle fashion makes
>> it difficult for a reader to understand the distinction.
>
> This is one of the best-articulated arguments against using procedure
> call syntax for specifying the programmer's belief that the order of
> evaluation of certain terms does not matter.

You may notice I went on to say that my experience in programming leads
me to think that order of evaluation for procedure arguments is a
distinction that rarely, if ever, matters in any practical program.

Can any of you who feel so passionately that the unspecified order of
evaluation for procedure arguments is such a problem provide an example
from a real, practical program of how this caused a problem (as opposed
to an example contrived only to demonstrate unspecified evaluation
order)?

I think that even should procedure argument evaluation order become
specified (but which order?  There's no clear consensus on which) that
it doesn't necessarily solve all the programming problems.  Here's a
contrived example:

Suppose a programmer created a function (foo a b), and later decides for
some reason (probably aesthetic) to swap the argument order.  Another
naive programmer called foo with expressions that had side effects,
depending on some specified order of evaluation to sequence those side
effects, but in modifying his code to reflect the change in argument
order for foo did not remember the order-dependence.  He might then
simply replace all occurrences of (foo a b) with (foo b a), except then
the side effects in the expressions happen in the opposite order and he
encounters a bug, which he has to fix by using an explicit
order-of-evaluation construct around each function call.

In the case where the second programmer was used to the idea of no
guaranteed order of evaluation, he would have been likely to write

(let* ((a (f))
       (b (g)))
  (foo a b))

so just changing the function call to (foo b a) would not affect the
behavior of the program.

In short, specifying evaluation order for procedure application still
leaves a subtle distinction that could cause problems for programmers,
and which would still require explicit coding to prevent certain kinds
of bugs.

-- 
For I know things that you don't know / And I see things you'll never see /
And I've a different way of living, you know / And I've such a different
frame of mind, and so ... / I'm on my way to the funnyfarm
 -- Happy Rhodes, "To the Funnyfarm"
0
stevev (36)
10/11/2004 7:04:56 PM
In article <87pt3pyf9g.fsf@localhost.efn.org>,
 Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > But expressiveness is all about subtle inconsistencies.  That is 
> > precisely the grounds on which those who advocate R5RS semantics argue 
> > their case.
> 
> Expressivness ought to be about _clearly_ expressing subtle
> distinctions.  A subtle distinction expressed in a subtle fashion makes
> it difficult for a reader to understand the distinction.

Yes, I agree completely.  That is exactly why I advocate deterministic 
OoE.

> > The situation would be no different under my proposal.  Both LET and 
> > LET* could (and probably would) still be library syntax.  And both 
> > sequenced and unsequenced evaluation could (and probably would) still be 
> > expressible using (deterministic) LAMBDA.
> 
> How do you think you would express unspecified evaluation order using
> procedure application with specified order of evaluation?  I'm having a
> hard time coming up with how to do that myself.

(defmacro let-with-unspecified-binding-order (bindings &body body)
  `(let ,(permute-as-desired bindings) ,@body)))

(Translate into Scheme as appropriate.)

The only specification of PERMUTE-AS-DESIRED is that it takes a list as 
input and returns a permutation of its input.  A perfectly acceptable 
implementation of PERMUTE-AS-DESIRED is the identity function.  Other 
possible implementations include a random permutation, and a stateful 
permutation function that cycles through all possible permutations.

> The reason that it's currently possible to express both unspecified and
> specified orders of evaluation using procedure application with
> unspecified order of evaluation of arguments is that the body of a
> LAMBDA is evaluated only after all the parameter names are bound.

No, the reason it's possible to express both specified and unspecified 
OoE using procedure application is that procedure application is 
Turing-complete.  But this is true regardless of whether OoE is 
deterministic or not.  As I have pointed out before, non-deterministic 
OoE is nothing more than syntactic sugar hiding a call to 
PERMUTE-AS-DESIRED.

> > No, it's not so easily expressible.  It requires writing a LOT more code 
> > to get deterministic evaluation, which undermines one of the principal 
> > motivations for using a high level language in the first place.  You are 
> > right to be skeptical of any proposal to change the fundamental 
> > semantics of the language, but I believe that this particular "feature" 
> > of Scheme renders it unsuitable for safety-critical applications.  (I 
> > feel the same way about Python's syntactically significant white space.)
> 
> The vast majority of procedure applications in real Scheme programs (and
> in other languages) do not require any specific order of evaluation for
> arguments since it is uncommon for programmers to use argument
> expressions containing side effects that would cause the order of
> evaluation to make a difference.  So the common case has the simplest
> expression, which is certainly a virtue in a high-level language.

Yes, but you're missing a very important point.  The issue is not 
whether a given procedure call depends on OoE, but whether or not you 
can tell if a given procedure call depends on OoE.  To safely write (f 
(g) (h)) it is not sufficient for g and h to BE order independent, it 
must be the case that you can KNOW that they are order independent.

If you have a million function calls it doesn't matter that only one of 
them is order dependent if 1) you can't tell which one it is and 2) 
getting the order wrong will result in your nuclear power plant melting 
down.

> If
> the order of evaluation of your procedure arguments really does make a
> difference, then making it explicitly clear that it does so is also
> highly desirable, and using a construct that ensures the desired order
> of evaluation is also worth it, even if it takes more space.

Agreed.  But it would be even better if the construct that ensures the 
desired order of evaluation didn't take more space.  In a tradeoff 
between safety by default or efficiency by default I think safety ought 
to win.

> I could see arguing that Scheme might be unsuitable for safety-critical
> applications if it had poorly-defined semantics or a lack of ability to
> control sequencing of evaluation under all circumstances.  But Scheme
> does have better-defined semantics than many other languages, and it
> does have the ability to control sequencing of evaluation.  Once again,
> you are not complaining because Scheme does not allow you to do
> something you want to do; you are complaining because Scheme chooses a
> default behavior that you don't like.

That's exactly right, because in actual practice many programmers will 
write (f (g) (h)) without thinking deeply about (or without having 
enough information to tell) whether g and h have order dependencies.  In 
such cases I would like to be able to fall back on testing as a 
methodology for determining if the code is "correct", and unspecified 
OoE makes testing vastly more difficult.  (Actually, unspecified OoE 
makes testing all but impossible.  To test (f (g) (h) ...) you actually 
have to explicitly write out all possible permutations of the arguments 
and test each one individually.)

> What I think would be more important for producing good safety-critical
> applications is for the programmer(s) to have a solid understanding of
> both the application they are programming and the language they are
> using to program it.

That is not sufficient.

> As I said before, I can't see any reason for any
> Scheme programmer _who has actually bothered to study the language_ to
> be surprised by the unspecified order of evaluation of procedure
> arguments.  This is not some behavior of the language buried in an
> appendix; it is laid out explicitly in the description of procedure
> calls.  The argument that unspecified evaluation order is capable of
> breeding subtle bugs seems to be based mainly on an assumption that
> programmers are dumb.

No.  It is based on the assumption that programmers sometimes make 
unwarranted assumptions, or sometimes do not have all the required 
information at their disposal, or sometimes have to make expedient 
shortcuts to meet schedule or budgetary constraints.

> I might also note that the laws of physics seem to be fundamentally
> non-deterministic in certain ways.  I guess I could also argue that the
> universe seems unsuitable for safety-critical applications.

Indeed.  That is precisely why engineering exists, to root out and 
eliminate to the extent possible the nondeterministic aspects of the 
universe to create artifacts whose behavior is reliably reproducible.

rg
0
rNOSPAMon (1927)
10/11/2004 7:16:40 PM
David Rush wrote:
> Thant Tessman <thant@acm.org> writes:
> 
>> [...] Yet I've *never*
>>assumed that the use of a function call communicated this fact about
>>my code. I  honestly don't think there are more than two or three of
>>you out there who do. [...]
> 
> 
> Well I'm one who does count on unspecified order, explicitly and
> implicitly communicated for correctness. 

That's three. :-)


> In fact I would venture that
> the opposite of your assertion is true. Most people implicitly use the
> fact that arg eval order is unspecified *all the time*. Every time you
> lift an expression into an enclosing let it happens [...]

Obviously there are situations where one can lift an expression into an 
enclosing let without changing the meaning of a program even in a 
language with fixed argument order of evaluation. So obviously the mere 
act isn't always an implicit use of whatever unspecified order of 
evaluation is supposed to communicate about the code.


> [...] I would, in fact, generally be surprised is performing such
> a lift caused a bug in the code, yet all the cases which have been put
> forth in favor of specified order would cause such bugs.

You mean: All examples of code which deliberately rely on fixed argument 
order of evaluation are simultaneously examples of code where one cannot 
arbitrarily lift expressions. Yes. But is that really what all this is 
about?

-thant

0
thant (332)
10/11/2004 9:00:08 PM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
> >
> >> Expressivness ought to be about _clearly_ expressing subtle
> >> distinctions.  A subtle distinction expressed in a subtle fashion makes
> >> it difficult for a reader to understand the distinction.
> >
> > This is one of the best-articulated arguments against using procedure
> > call syntax for specifying the programmer's belief that the order of
> > evaluation of certain terms does not matter.
> 
> You may notice I went on to say that my experience in programming leads
> me to think that order of evaluation for procedure arguments is a
> distinction that rarely, if ever, matters in any practical program.

Yes, I did notice that.  I have the same experience.  Therefore, I see
no harm in fixing the order.  On the other hand, the few times I have
seen evaluation-order-related problems, it was always due to a
language leaving the order unspecified.  I have /never/ seen a
real-world problem caused by a fixed evaluation order.

> Can any of you who feel so passionately that the unspecified order of
> evaluation for procedure arguments is such a problem provide an example
> from a real, practical program of how this caused a problem (as opposed
> to an example contrived only to demonstrate unspecified evaluation
> order)?

I have done so in this group before.  But here you go:

A fairly expert computer graphics person was hunting a bug in his (C)
program.  The program seemed to work fine when compiled without
optimization and went haywire with optimization.  He suspected a bug
in the C compiler, but let me have a look at the program.  It came
down to two C macro invocations which occured within the same function
argument list.  The macro expanded into code that modified and read
some variable which needed to be declared global to the macro
invocations.  By the rules of C, the two pieces of code were not
separated by sequence points, and in optimizing mode the compiler made
a mess of them (assuming legally but in this case incorrectly that
they do not interfere).

The guy (I won't give his name away) is a very respected CG authority
today and was well on its way to become one back then.  In other
words: a very smart person.  But I had the hardest of times explaining
to him that the compiler -- according to the langugage definition --
is right and the code was wrong.  (To this day I am not sure I left
him convinced.)

I have seen lesser people suprised at the result of what amounts to

   (list (read) (read) (read))

Granted, it perhaps does not happen often and maybe does not really
matter considering the big picture.  But then, all else being equal, I
/personally/ prefer a language with simpler semantics.  Fixed order of
evaluation is considerably simpler than leaving the order unspecified.
(To get an idea of why that is, see RnRS, especially its denotational
semantics, and remember that this semantics is technically wrong on
this point because it was deemed to tedious to do it right.)

> Suppose a programmer created a function (foo a b), and later decides for
> some reason (probably aesthetic) to swap the argument order.  Another
> naive programmer called foo with expressions that had side effects,
> depending on some specified order of evaluation to sequence those side
> effects, but in modifying his code to reflect the change in argument
> order for foo did not remember the order-dependence.  He might then
> simply replace all occurrences of (foo a b) with (foo b a), except then
> the side effects in the expressions happen in the opposite order and he
> encounters a bug, which he has to fix by using an explicit
> order-of-evaluation construct around each function call.

I consider this *extremely* contrived.  When the order is fixed, then
/obviously/ exchanging /any/ two expressions has to be done very
carefully.

> In the case where the second programmer was used to the idea of no
> guaranteed order of evaluation, he would have been likely to write
> 
> (let* ((a (f))
>        (b (g)))
>   (foo a b))

In the case where the first programmer was used to the idea of fixed
order, and assuming it was not clear whether (f) and (g) can be
exchanged (which, in my experience, is a rare thing to happen), she
would have rewritten (foo (f) (g)) as

   (let* ((a (f)) (b (g))) (foo b a))

> In short, specifying evaluation order for procedure application still
> leaves a subtle distinction that could cause problems for programmers,
> and which would still require explicit coding to prevent certain kinds
> of bugs.

I have programmed extensively in either kind of language, and my
experience is in direct contrast to the scenario you are painting.

Matthias
0
find19 (1244)
10/11/2004 9:02:26 PM
Thant Tessman wrote:
> David Rush wrote:
> 
>> Thant Tessman <thant@acm.org> writes:
>>
>>> [...] Yet I've *never*
>>> assumed that the use of a function call communicated this fact about
>>> my code. I  honestly don't think there are more than two or three of
>>> you out there who do. [...]
>>
>>
>>
>> Well I'm one who does count on unspecified order, explicitly and
>> implicitly communicated for correctness. 
> 
> 
> That's three. :-)
> 
> 
>> In fact I would venture that
>> the opposite of your assertion is true. Most people implicitly use the
>> fact that arg eval order is unspecified *all the time*. Every time you
>> lift an expression into an enclosing let it happens [...]
> 
> 
> Obviously there are situations where one can lift an expression into an 
> enclosing let without changing the meaning of a program even in a 
> language with fixed argument order of evaluation. So obviously the mere 
> act isn't always an implicit use of whatever unspecified order of 
> evaluation is supposed to communicate about the code.
> 
> 
>> [...] I would, in fact, generally be surprised is performing such
>> a lift caused a bug in the code, yet all the cases which have been put
>> forth in favor of specified order would cause such bugs.
> 
> 
> You mean: All examples of code which deliberately rely on fixed argument 
> order of evaluation are simultaneously examples of code where one cannot 
> arbitrarily lift expressions. Yes. But is that really what all this is 
> about?

It certainly speaks to the usefulness of an unspecified order in code
refactoring.  I would definitely be highly inconvenienced if for 90% of 
Scheme code I had to assume that I couldn't cut/paste expressions from
function calls, reorder function arguments, and relocate code without 
first reading all the code to make sure it didn't depend on OoE.  Some 
would say you should understand the program fully anyway, but this is 
just not a realistic requirement for multi-member programming teams and 
large projecs.

It makes sense that the default language semantics match the actual 
program semantics for most programs.  It is for this reason that I 
reject the idea that the programmer should have to declare when he 
doesn't rely on the OoE, rather than having to declare (as is the case 
now) the opposite.

	Scott
0
scgmille (240)
10/12/2004 4:56:24 AM
Scott G. Miller wrote:
> Thant Tessman wrote to David Rush:

[...]

>> You mean: All examples of code which deliberately rely on fixed 
>> argument order of evaluation are simultaneously examples of code where 
>> one cannot arbitrarily lift expressions. Yes. But is that really what 
>> all this is about?
> 
> 
> It certainly speaks to the usefulness of an unspecified order in code
> refactoring. [...]

No, it doesn't--for reasons I would only be repeating.

-thant
0
thant (332)
10/12/2004 12:07:31 PM
Joe Marshall <jrm@ccs.neu.edu> writes:
> If we are going to specify order of evaluation, then we ought to
> specify the return values of DEFINE and SET! as well because someone
> might be relying on them.

Just to throw a little gasoline on the fire, I think this ought to be
done actually. And (if #f #f) should return a meaningful value within
the language, too. And #NaN...

david rush
-- 
By the force of will my lungs are filled and so I breathe...
        -- Natalie Merchant in _Like the Weather_
0
kumoyuki (163)
10/12/2004 2:17:13 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In article <u3c0qjo00.fsf@STRIPCAPStelus.net>,
> >  Ray Blaak <rAYblaaK@STRIPCAPStelus.net> wrote:
> > > > Joe Marshall suggested Reverse-Ordinal-Form-Lexicographic order...
> > > > > Is this order better than leaving the order unspecified?
> > > > Yes.
> > > No. It is confusing as hell, and so it is better not to have to
> > > think about it.
> > 
> > You didn't read the question.  It is confusing as hell, but a confusing 
> > order is better than none at all.  At least it makes program behavior 
> > deterministic.  But a simple OoE would, of course, be even better.
> 
> I did read the question and disagree. My point is that a sufficiently
> confusing specified order is effectively equivalent to having none specified
> at all, at least to the programmer's mental work load.
> 
> That is, if you can't think about it enough to make effective use of it, the
> practical consequence is that it does not exist.

Which was Joe's intent in suggesting ROFL[1] order in the first
place. It's a particularly excellent straw-man. The pun, of course, is
my own...

david rush
1 - see the attributions...
-- 
In no other country in the world is the love of property keener or
more alert than in the United States, and nowhere else does the
majority display less inclination toward doctrines which in any way
threaten the way property is owned.
	-- Democracy in America (Alexis de Tocqueville)
0
kumoyuki (163)
10/12/2004 2:25:42 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>> Thant Tessman <thant@acm.org> writes:
>>
>>>Joe Marshall wrote:
>>>
>>>>Thant Tessman <thant@acm.org> writes:
>>>
>>>[...]
>>>
>>>
>>>>>But you don't know if the programmer's intention was to rely on fixed
>>>>>order of evaluation even in the unspecified case.
>>>>
>>>>Sure I do.  Their intent was to *not* rely on it.  If their intent
>>>>were to rely on it, they'd be deliberately writing bogus code.
>>>
>>>You are assuming that the programmer knows OofE is unspecified. In other
>>>words, you are assuming exactly what it is I claim you don't know.
>> I certainly assume that if the programmer is programming in Scheme,
>> then he knows Scheme.  If we assume that the programmer is unfamiliar
>> with the language he is using, then order of evaluation is the least
>> of our worries.
>
> There are very few experts in any language. Favoring an aspect of a
> language for its ability to punish an incorrect guess is no way to
> design a programming language.

Do you think I favor unspecified order of evaluation because it
confuses people that (erroneously) expect it to be left to right?

If I chose a language based on its hostility to newbies, I'd choose
C++ or Perl.
0
jrm (1310)
10/12/2004 2:31:49 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> I'd spin it differently, but that is essentially correct.  In fact, 
> until someone figures out how to automatically generate provably correct 
> code from specifications I'd say that producing "accidentally correct" 
> code as you put it is in fact the only practical way to produce correct 
> (or even working) code in general.

Nonsense.  I've actually seen people design code and write things on purpose.
0
jrm (1310)
10/12/2004 2:33:12 PM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
> There are an awful lot of places in R5RS where behaviors in specific
> situations are left unspecified, and hence opportunities for a naive
> programmer to think one particular implementation's choice for how to
> implement an unspecified behavior is how all implementations work, and
> thus write a program that behaves differently in a different Scheme
> implementation.  When that happens, is that naive programmer really
> being punished by anyone, or is he just a victim of his own naivete?

Stupidity has always been a capital offense...

david rush
-- 
It's not what you've got that matters, it's how you've got it.
	-- Esmerelda Weatherwax in _Lords and Ladies_
0
kumoyuki (163)
10/12/2004 2:33:23 PM
Nic Ferrier <nferrier@tapsellferrier.co.uk> writes:
> Can somebody do a simple enumeration of the reasons why fixed OoE is
> bad?

It turns out that the reasons it are bad are the same as the reasons
it is good, which explains why there is a controversy.

unspec OoE says the following transformation is always correct:

        (foo (a) (b))  => (let ((b* (b))) (f (a) b*))

Fixed OoE asserts that the author of (foo (a) (b)) has to tell you that
transformation is correct. Which condition you prefer to live with is
a matter of taste. I'm for unspec, since I regularly let-lift
expressions while I'm working on code.

david rush
-- 
Engineering is the art of making what you want from things you can get.
	-- Jerry Avins (on comp.lang.scheme)
0
kumoyuki (163)
10/12/2004 2:44:06 PM
Ray Dillinger <bear@sonic.net> writes:

> Just by the way, do the folks here advocating an unfixed
> order of evaluation specifically because it punishes something
> they find offensive or consider poor style think that no
> parking zones ought to contain hidden, position-varying
> landmines?  

No.

I favor unspecified order of evaluation because I can then make the
tacit assumption (when looking at other people's code) that if the
order were important, then the author would have explicitly gone out
of his way to ensure that the order was what he intended.  When I see
Scheme code like this:

  (let* ((a (foo))
         (b (bar))) ;; assuming a is not free in bar
    (baz a b))

I know that the author, for whatever reason, thinks it is important
that (foo) run *before* (bar).

When I see (baz (foo) (bar)) in Scheme code, I *know* that the author
did not think it important that (foo) be called before (bar).  I know
this because

  - Either the author is aware that order is not enforced and does not
    believe that the order is important here.

  - The author is unaware that order is not enforced and he *didn't
    bother to check*.  He therefore didn't think the order of
    evaluation was important enough to look it up.

If the order were specified, then I can no longer determine whether
or not the author intented (bar) to always execute before (baz) in an
expression such as  (foo (bar) (baz)) 

0
jrm (1310)
10/12/2004 2:46:12 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Nic Ferrier <nferrier@tapsellferrier.co.uk> writes:
>
>> Can somebody do a simple enumeration of the reasons why fixed OoE is
>> bad?
>
>
> Here you go:


Sigh.  You are too used to using a lazy language, Matthias.
0
jrm (1310)
10/12/2004 2:46:38 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
>
>> Expressivness ought to be about _clearly_ expressing subtle
>> distinctions.  A subtle distinction expressed in a subtle fashion makes
>> it difficult for a reader to understand the distinction.
>
> This is one of the best-articulated arguments against using procedure
> call syntax for specifying the programmer's belief that the order of
> evaluation of certain terms does not matter.

And, by symmetry, an argument against using procedure call syntax for
specifying the programmer's belief that the order of evaluation *does*
matter.
0
jrm (1310)
10/12/2004 2:50:55 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Nic Ferrier <nferrier@tapsellferrier.co.uk> writes:
> >
> >> Can somebody do a simple enumeration of the reasons why fixed OoE is
> >> bad?
> >
> >
> > Here you go:
> 
> 
> Sigh.  You are too used to using a lazy language, Matthias.

I am not using a lazy language.

However, I should say that I am very used to a language with much
fewer effects than Scheme, so whether or not order matters is obvious
much more often.  For example, in that language I can always transform
(using Scheme notation):

       (f (g) x)

into

       (let ((g-res (g))) (f g-res x))

even though the order of evaluation is fixed.  In Scheme, I have to
know that g does not fiddle with the values of f or x.  In the
language that I am using, I do know that because it isn't possible for
g to fiddle with the values of f or x there.  Same goes for the
contents of cons cells, records, and vectors.

When working with programs written in that language, I have not once
seen a problem caused by its fixed order of evaluation.  So from that
perspective I think that anyone who claims that fixed order causes
problems is talking out of their behind.

I have also written quite a lot of code in Scheme and C, both
languages where order of evaluation is not fixed.  While it has been
some time -- which means I may have forgotten, I am still unable to
recall a case where I felt much of a burden taken from me by this
language design.

On the other hand, I distinctly remember a few (although admittedly
not very many) cases where people had problems which were caused by
the combination of side effects and unspecified order.  Whether you
attribute this more to the effects or to the order may seem like a
matter of taste.  However, if we blame effects and largely eliminate
them from the language, then there is no reason not to fix the order
anymore.

So in short: If the problem is with unfixed order, we /should/ fix the
order.  If the problem is with effects, then we should eliminate (most)
effects, after wich we /might as well/ fix the order.

Matthias
0
find19 (1244)
10/12/2004 3:06:11 PM
David Rush <kumoyuki@gmail.com> writes:

> Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
>> There are an awful lot of places in R5RS where behaviors in specific
>> situations are left unspecified, and hence opportunities for a naive
>> programmer to think one particular implementation's choice for how to
>> implement an unspecified behavior is how all implementations work, and
>> thus write a program that behaves differently in a different Scheme
>> implementation.  When that happens, is that naive programmer really
>> being punished by anyone, or is he just a victim of his own naivete?
>
> Stupidity has always been a capital offense...

Were that true.  My daughter remarked the other day that the world
would be so much better if stupidity were physically painful.
0
jrm (1310)
10/12/2004 3:11:14 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
> >
> >> Expressivness ought to be about _clearly_ expressing subtle
> >> distinctions.  A subtle distinction expressed in a subtle fashion makes
> >> it difficult for a reader to understand the distinction.
> >
> > This is one of the best-articulated arguments against using procedure
> > call syntax for specifying the programmer's belief that the order of
> > evaluation of certain terms does not matter.
> 
> And, by symmetry, an argument against using procedure call syntax for
> specifying the programmer's belief that the order of evaluation *does*
> matter.

Right.  But so what?  I am not advocating this.  Procedure call syntax
should not be used at all for the purpose of expressing such beliefs.
(Also notice that if anything, what it would express is the
programmer's admission that she was not quite sure whether or not the
order matters.)

All I want is procedure calls to have a well-defined deterministic
semantics in all cases.  This makes for a simpler semantics, i.e., a
simpler mental model. As a bonus you also get more meaningful results
from testing.

Matthias
0
find19 (1244)
10/12/2004 3:12:07 PM
Matthias Blume <find@my.address.elsewhere> writes:

> So in short: If the problem is with unfixed order, we /should/ fix the
> order.  If the problem is with effects, then we should eliminate (most)
> effects, after wich we /might as well/ fix the order.

I agree.  Let's get rid of SET!
0
jrm (1310)
10/12/2004 3:14:39 PM
David Rush wrote:
> Nic Ferrier <nferrier@tapsellferrier.co.uk> writes:
> 
>>Can somebody do a simple enumeration of the reasons why fixed OoE is
>>bad?
> 
> 
> It turns out that the reasons it are bad are the same as the reasons
> it is good, which explains why there is a controversy.
> 
> unspec OoE says the following transformation is always correct:
> 
>         (foo (a) (b))  => (let ((b* (b))) (f (a) b*))

Not quite. Unspecified OofE implies that the above transformation won't 
change the behavior of "correct" code, where "correct" is defined as 
code whose behvior the above transformation won't change. Unspecified 
OofE has nothing to say about whether the code is in fact "correct." 
That's why this benefit of unspecified OofE is at best unreliable, and 
at worst dangerously misleading.

[...]

-thant

0
thant (332)
10/12/2004 3:15:31 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > So in short: If the problem is with unfixed order, we /should/ fix the
> > order.  If the problem is with effects, then we should eliminate (most)
> > effects, after wich we /might as well/ fix the order.
> 
> I agree.  Let's get rid of SET!

SET! is the least of the problems -- at least as long as it is applied
to local variables.  Global mutable variables are much more of a pain,
and -- as has been pointed out -- most serious Scheme implementations
offer some way of "declaring" that certain top-level bindings are to
be considered immutable.

Much bigger problems for local transformations:

   -- all cons cells (in fact, all structured values) have state and identity
   -- all lambdas have identity

Matthias
0
find19 (1244)
10/12/2004 3:23:48 PM
Joe Marshall wrote:

[...]

> Do you think I favor unspecified order of evaluation because it
> confuses people that (erroneously) expect it to be left to right?

If not, why not fix OofE and simply tell programmers that it's a bad 
idea to write code that depends on OofE?

[...]

-thant

0
thant (332)
10/12/2004 3:27:09 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Much bigger problems for local transformations:
>
>    -- all cons cells (in fact, all structured values) have state and identity
>    -- all lambdas have identity

What do you mean by "lambdas have identity"?

(They are not required to be separately allocated if they behave
the same.)

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
0
qrczak (1266)
10/12/2004 5:33:43 PM
Thant Tessman wrote:
> Joe Marshall wrote:
> 
> [...]
> 
>> Do you think I favor unspecified order of evaluation because it
>> confuses people that (erroneously) expect it to be left to right?
> 
> 
> If not, why not fix OofE and simply tell programmers that it's a bad 
> idea to write code that depends on OofE?

wouldn't telling them that the order of evaluation is unspecified the 
best way of telling them that?

hs
0
hs60 (77)
10/12/2004 7:06:55 PM
In article <y8icm2fr.fsf@ccs.neu.edu>, Joe Marshall <jrm@ccs.neu.edu> 
wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > I'd spin it differently, but that is essentially correct.  In fact, 
> > until someone figures out how to automatically generate provably correct 
> > code from specifications I'd say that producing "accidentally correct" 
> > code as you put it is in fact the only practical way to produce correct 
> > (or even working) code in general.
> 
> Nonsense.  I've actually seen people design code and write things on purpose.

Yes, but I doubt very much that you've often seen people get it right.  
Just because someone does a design and writes code on purpose doesn't 
mean they haven't made a mistake.

I work in the space industry.  I have written and have observed other 
people write mission-critical code for unmanned spacecraft, assets 
costing hundreds of millions to billion of dollars.  The organizations 
that support these activities do their best to "design code" and "write 
things on purpose" as you put it.  Nonetheless, there are two outcomes 
that tend to be reliably reproducible: 1) the code that emerges from 
these process is riddled with flaws and 2) despite this it tends to be 
pretty reliable the vast majority of the time.

The reason that the software is flawed is not that the people writing it 
are dumb or incompetent, but that they are working under time and 
schedule constraints that make it impossible to write flawless code.  
(To say nothing of the fact that they're using C and C++.)  So the way 
that they make the code reliable despite its flaws is they test it, and 
use the behavior of the system to focus their attention on those flaws 
that actually matter.  This works because the system (hardware and 
software) is designed as much as possible to be deterministic.  And if 
you look at the history of in-flight software failures, of the ones that 
were not due to simple operational stupidity, the vast majority had 
their root causes in some non-deterministic aspect of the system that 
was either not engineered away or, more commonly, intentionally designed 
in (e.g. preemptive multitasking leading to deadlocks).

The arguments for unspecified OoE apply only in an ideal world where 
programmers have perfect knowledge and never make mistakes.  In the real 
world programmers rarely have complete knowledge, and rarely have the 
time necessary to fully explore all ramifications of their design 
decisions.  In the real world, programmers write (f (g) (h)) not because 
they really have confidence that g and h are order independent, but 
because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
they have a deadline to meet.  In the real world, the processes that are 
used to write real code resemble a random walk much more than a 
mathematically principled methodology, and they rely on the reliable 
reproducibility of the behavior of software from one run to the next, or 
from one compilation session to the next.  It's not ideal, but that's 
the way it is.

rg
0
rNOSPAMon (1927)
10/12/2004 7:09:36 PM
Matthias Blume wrote:
> ...
>>And, by symmetry, an argument against using procedure call syntax for
>>specifying the programmer's belief that the order of evaluation *does*
>>matter.
> 
> ...
> All I want is procedure calls to have a well-defined deterministic
> semantics in all cases.  This makes for a simpler semantics, i.e., a
> simpler mental model. As a bonus you also get more meaningful results
> from testing.

for me, the rule that everything must be evaluated before it is used is 
deterministic enough.

hs
0
hs60 (77)
10/12/2004 7:17:29 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>
> [...]
>
>> Do you think I favor unspecified order of evaluation because it
>> confuses people that (erroneously) expect it to be left to right?
>
> If not, why not fix OofE and simply tell programmers that it's a bad
> idea to write code that depends on OofE?
>

Why not simply tell programmers that it's a bad idea to write code
that depends on OofE?  You have to do that anyway.

Remind me again what specifying the order of arguments solved? 
0
jrm (1310)
10/12/2004 7:40:35 PM
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Much bigger problems for local transformations:
> >
> >    -- all cons cells (in fact, all structured values) have state and identity
> >    -- all lambdas have identity
> 
> What do you mean by "lambdas have identity"?

See section 4.1.4 of R5RS ("location tags").

> (They are not required to be separately allocated if they behave
> the same.)

Right.  But they are required to be allocated equally in certain
cases.  For example,

   (let ((f (lambda (x) x))) (g f f))

cannot legally be transformed into

   (g (lambda (x) x) (lambda (x) x))

because the standard requires g to receive to arguments that compare
eqv?.

Incidentally, this sort of requirement makes -- strictly speaking --
tools like DrScheme "incorrect" in the sense that programs can observe
whether contract checking is in effect in ways other than observing
contract failures.  In fact, some programs might behave incorrectly
under DrScheme if they relied on the eqv? guarantee for procedures
that the standard provides.

More generally, eta-reduction and -expansion are invalid,
i.e., (lambda (x) (M x)) is not equivalent to M even if M is of the
form (lambda ...).

All told, this means that (lambda ...) is not a syntactic value in
Scheme.

Matthias
0
find19 (1244)
10/12/2004 7:53:40 PM
Hartmann Schaffer <hs@hartmann.schaffernet> writes:

> Matthias Blume wrote:
> > ...
> >>And, by symmetry, an argument against using procedure call syntax for
> >>specifying the programmer's belief that the order of evaluation *does*
> >>matter.
> > ...
> > All I want is procedure calls to have a well-defined deterministic
> > semantics in all cases.  This makes for a simpler semantics, i.e., a
> > simpler mental model. As a bonus you also get more meaningful results
> > from testing.
> 
> for me, the rule that everything must be evaluated before it is used
> is deterministic enough.

So you want Scheme to be lazy?

Matthias
0
find19 (1244)
10/12/2004 7:54:50 PM
Joe Marshall wrote:
> Thant Tessman <thant@acm.org> writes:
> 
> 
>>Joe Marshall wrote:
>>
>>[...]
>>
>>
>>>Do you think I favor unspecified order of evaluation because it
>>>confuses people that (erroneously) expect it to be left to right?
>>
>>If not, why not fix OofE and simply tell programmers that it's a bad
>>idea to write code that depends on OofE?
>>
> 
> Why not simply tell programmers that it's a bad idea to write code
> that depends on OofE?  You have to do that anyway.

Because merely telling them will not prevent such code from being written.

> Remind me again what specifying the order of arguments solved? 

Code that is buggy in unspecified OofE is merely bad style in fixed 
OofE. Bad style is better than buggy.

-thant


0
thant (332)
10/12/2004 7:55:43 PM
Hartmann Schaffer wrote:
> Thant Tessman wrote:
> 
>> Joe Marshall wrote:
>>
>> [...]
>>
>>> Do you think I favor unspecified order of evaluation because it
>>> confuses people that (erroneously) expect it to be left to right?
>>
>>
>>
>> If not, why not fix OofE and simply tell programmers that it's a bad 
>> idea to write code that depends on OofE?
> 
> 
> wouldn't telling them that the order of evaluation is unspecified the 
> best way of telling them that?

Why? Because it carries the extra weight of the threat of buggy code? 
Joe just said he didn't want to be hostile to newbies.

-thant

0
thant (332)
10/12/2004 7:58:25 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Thant Tessman <thant@acm.org> writes:
> 
> > Joe Marshall wrote:
> >
> > [...]
> >
> >> Do you think I favor unspecified order of evaluation because it
> >> confuses people that (erroneously) expect it to be left to right?
> >
> > If not, why not fix OofE and simply tell programmers that it's a bad
> > idea to write code that depends on OofE?
> >
> 
> Why not simply tell programmers that it's a bad idea to write code
> that depends on OofE?  You have to do that anyway.
> 
> Remind me again what specifying the order of arguments solved? 

You must have an awful short-term memory.

Here it is again:

   1.  It eliminates non-determinism from the language, making its
       semantics simpler.
   2.  As a result, tests become repeatable across platforms and
       implementations, which in turn adds relevance to the results of
       testing.

Matthias
0
find19 (1244)
10/12/2004 8:00:53 PM
Matthias Blume wrote:
> Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
> 
> 
>>Matthias Blume <find@my.address.elsewhere> writes:
>>
>>
>>>Much bigger problems for local transformations:
>>>
>>>   -- all cons cells (in fact, all structured values) have state and identity
>>>   -- all lambdas have identity
>>
>>What do you mean by "lambdas have identity"?
> 
> 
> See section 4.1.4 of R5RS ("location tags").
> 
> 
>>(They are not required to be separately allocated if they behave
>>the same.)
> 
> 
> Right.  But they are required to be allocated equally in certain
> cases.  For example,
> 
>    (let ((f (lambda (x) x))) (g f f))
> 
> cannot legally be transformed into
> 
>    (g (lambda (x) x) (lambda (x) x))
> 
> because the standard requires g to receive to arguments that compare
> eqv?.
> 

The standard allows (eqv? (lambda (x) x) (lambda (x) x)) to evaluate
to either true, or false.  And in some cases (this particular
example being trivial) it's possible to have the compiler detect
anonymous functions with identical or very similar source code
and just allocate once. So you could easily build a scheme in
which the above transformation were reliable and did what you
want.

But, it's not possible, in general, to detect functions with the
same range, domain, and behavior by source-code comparison, so
there will always be nominally "identical" functions whose equality
can't be detected.  For example,

(eqv? (lambda (x) (and (real? x)(sin x)))
       (lambda (x) (and (real? x)(/ 1 (csc x)))))

will be an "undetected equality" in almost all conceivable compilers.
So it's not reasonable to specify eqv? behavior on functions.

					Bear

0
bear (1219)
10/12/2004 9:45:03 PM
Joe Marshall wrote:
> 
> I favor unspecified order of evaluation because I can then make the
> tacit assumption (when looking at other people's code) that if the
> order were important, then the author would have explicitly gone out
> of his way to ensure that the order was what he intended.  When I see
> Scheme code like this:

I guess I rarely think about the author's intent in these terms.
All the 'credit' I give is that I assume the author probably
tested it and got it to work on whatever implementation he was
using.

The fact that that doesn't necessarily mean it will work on the
implementation I'm using - that an OofE bug may have gone undetected -
is like a bomb, lurking there under the surface and waiting for
the wrong combination of optimization, transformation, etc, to
set it off.

And no matter how careful I am, the fact that I may inadvertently
rely on OofE and produce working code that breaks "for no reason"
on another implementation or in another optimization setting, is
like programming under the sword of Damocles.

					Bear

0
bear (1219)
10/12/2004 9:56:21 PM
Matthias Blume <find@my.address.elsewhere> writes:

>    (let ((f (lambda (x) x))) (g f f))
>
> cannot legally be transformed into
>
>    (g (lambda (x) x) (lambda (x) x))
>
> because the standard requires g to receive to arguments that compare
> eqv?.

I don't understand. Why would *any* value be not eqv? to itself?

> More generally, eta-reduction and -expansion are invalid,
> i.e., (lambda (x) (M x)) is not equivalent to M even if M is of the
> form (lambda ...).

As in every language I know which supports any kind of comparison of
functions. Because it's impossible to detect all forms which are
"the same" without false positives.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
0
qrczak (1266)
10/12/2004 9:56:55 PM
Ray Dillinger <bear@sonic.net> writes:

> Matthias Blume wrote:
> > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
> > 
> >>Matthias Blume <find@my.address.elsewhere> writes:
> >>
> >>
> >>>Much bigger problems for local transformations:
> >>>
> >>>   -- all cons cells (in fact, all structured values) have state and identity
> >>>   -- all lambdas have identity
> >>
> >>What do you mean by "lambdas have identity"?
> > See section 4.1.4 of R5RS ("location tags").
> > 
> >>(They are not required to be separately allocated if they behave
> >>the same.)
> > Right.  But they are required to be allocated equally in certain
> > cases.  For example,
> >    (let ((f (lambda (x) x))) (g f f))
> > cannot legally be transformed into
> >    (g (lambda (x) x) (lambda (x) x))
> > because the standard requires g to receive to arguments that compare
> > eqv?.
> > 
> 
> The standard allows (eqv? (lambda (x) x) (lambda (x) x)) to evaluate
> to either true, or false.  And in some cases (this particular
> example being trivial) it's possible to have the compiler detect
> anonymous functions with identical or very similar source code
> and just allocate once. So you could easily build a scheme in
> which the above transformation were reliable and did what you
> want.

I don't care about "in some implementations".  It's not portable, period.

> But, it's not possible, in general, to detect functions with the
> same range, domain, and behavior by source-code comparison, so
> there will always be nominally "identical" functions whose equality
> can't be detected.  For example,
> 
> (eqv? (lambda (x) (and (real? x)(sin x)))
>        (lambda (x) (and (real? x)(/ 1 (csc x)))))
> 
> will be an "undetected equality" in almost all conceivable compilers.
> So it's not reasonable to specify eqv? behavior on functions.

But, unfortunately, the standard did specify the behavior for this
case:

   (let ((f (lambda ...))) (eqv? f f))

It says that it must be #t.  And that is the problem.
0
find19 (1244)
10/12/2004 10:36:50 PM
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> >    (let ((f (lambda (x) x))) (g f f))
> >
> > cannot legally be transformed into
> >
> >    (g (lambda (x) x) (lambda (x) x))
> >
> > because the standard requires g to receive to arguments that compare
> > eqv?.
> 
> I don't understand. Why would *any* value be not eqv? to itself?

Short answer: What does "itself" mean?  (Answer: Identity on lambdas.
This should answer your original question.)

Slightly longer answer: Because it makes the above transformation and
things like DrScheme illegal.  Fortunately, the designers of DrScheme
have taken the approach of ignoring this particular aspect of the
standard.  (If your program relies on it, it is likely to fail under
DrScheme.)

> > More generally, eta-reduction and -expansion are invalid,
> > i.e., (lambda (x) (M x)) is not equivalent to M even if M is of the
> > form (lambda ...).
> 
> As in every language I know which supports any kind of comparison of
> functions.

Yes.  Comparisons on functions should not be allowed.  That was my point.

Matthias
0
find19 (1244)
10/12/2004 10:40:34 PM
Matthias Blume wrote:
> Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:

>>Matthias Blume <find@my.address.elsewhere> writes:

>>>   (let ((f (lambda (x) x))) (g f f))
>>>
>>>cannot legally be transformed into
>>>
>>>   (g (lambda (x) x) (lambda (x) x))
>>>
>>>because the standard requires g to receive to arguments that compare
>>>eqv?.
>>
>>I don't understand. Why would *any* value be not eqv? to itself?
>=20
>=20
> Short answer: What does "itself" mean?  (Answer: Identity on lambdas.
> This should answer your original question.)
>=20
> Slightly longer answer: Because it makes the above transformation and
> things like DrScheme illegal.  Fortunately, the designers of DrScheme
> have taken the approach of ignoring this particular aspect of the
> standard.  (If your program relies on it, it is likely to fail under
> DrScheme.)

Do you have an example that breaks?

This works in DrScheme:

   > (let ((f (lambda (x) x))) (eqv? f f))
   #t

--=20
Jens Axel S=F8gaard
0
usenet8944 (1130)
10/12/2004 10:54:24 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Slightly longer answer: Because it makes the above transformation
> and things like DrScheme illegal.

Why does DrScheme want to break that property? I did not understand
your comments about contract checking.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
0
qrczak (1266)
10/12/2004 10:59:01 PM
Jens Axel S�gaard <usenet@soegaard.net> writes:

> Matthias Blume wrote:
> > Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:
> 
> >>Matthias Blume <find@my.address.elsewhere> writes:
> 
> >>>   (let ((f (lambda (x) x))) (g f f))
> >>>
> >>>cannot legally be transformed into
> >>>
> >>>   (g (lambda (x) x) (lambda (x) x))
> >>>
> >>>because the standard requires g to receive to arguments that compare
> >>>eqv?.
> >>
> >>I don't understand. Why would *any* value be not eqv? to itself?
> > Short answer: What does "itself" mean?  (Answer: Identity on
> > lambdas.
> > This should answer your original question.)
> > Slightly longer answer: Because it makes the above transformation
> > and
> > things like DrScheme illegal.  Fortunately, the designers of DrScheme
> > have taken the approach of ignoring this particular aspect of the
> > standard.  (If your program relies on it, it is likely to fail under
> > DrScheme.)
> 
> Do you have an example that breaks?

Not off the top of my head.  But I can ask Robby Findler when I see
him next time.  I'm sure he has plenty of examples.
Also, see below for a recipe to construct your own.

> This works in DrScheme:
> 
>    > (let ((f (lambda (x) x))) (eqv? f f))
>    #t

Yes, it will work sometimes.  And sometimes it won't.

I bet you can construct an example as follows (but I am unsure about
concrete syntax, so I can't give you actual code):

  Conceptually, use the following code:

     1. (define g (lambda (x y) (eqv? x y)))
        but put a contract on this g that says:
        g is a function mapping two int->int functions to bool

     3. (define f (lambda (x) (+ x 1)))

     4. (g f f)

Matthias
0
find19 (1244)
10/12/2004 11:00:44 PM
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Slightly longer answer: Because it makes the above transformation
> > and things like DrScheme illegal.
> 
> Why does DrScheme want to break that property? I did not understand
> your comments about contract checking.

Because contract checking works by guarding procedure values with
wrappers.  If you pass a function f value to a function g whose contract
says it is to receive an int->int value, what gets actually passed to g is
roughly of the form:

    (lambda (x) (if (integer? x)
                    (let ((res (f x)))
                         (if (integer? res)
                             res
                             (error "argument to g violates contract")))
                    (error "g violates contract")))

This sort of wrapping happens whenever a procedure value travels past
a guard, and identity of the lambda gets lost in the process.

Matthias
0
find19 (1244)
10/12/2004 11:05:38 PM
Matthias Blume <find@my.address.elsewhere> wrote:
> But, unfortunately, the standard did specify the behavior for this
> case:
> 
>    (let ((f (lambda ...))) (eqv? f f))
> 
> It says that it must be #t.  And that is the problem.

Incorrect.

I hope I will be forgiven for injecting a factual statement into
this flame war, but neither the IEEE/ANSI standard nor the R5RS
assert what Matthias Blume claims they assert.

Will
0
cesuraSPAM (401)
10/13/2004 4:24:09 AM
Jens Axel S�gaard <usenet@soegaard.net> wrote in message news:<416c6089$0$299$edfadb0f@dread11.news.tele.dk>...
> Do you have an example that breaks?
> 
> This works in DrScheme:
> 
>    > (let ((f (lambda (x) x))) (eqv? f f))
>    #t

Following Matthias Blume's recipe:

   (require (lib "contract.ss"))
   (define/contract g (-> (-> any? any) (-> any? any) any)
     eqv?)
   (let ((f (lambda (x) x)))
     (g f f))  ;; #f
0
david4255 (7)
10/13/2004 4:40:01 AM
In article <fb74251e.0410122024.28864009@posting.google.com>,
 cesuraSPAM@verizon.net (William D Clinger) wrote:

> Matthias Blume <find@my.address.elsewhere> wrote:
> > But, unfortunately, the standard did specify the behavior for this
> > case:
> > 
> >    (let ((f (lambda ...))) (eqv? f f))
> > 
> > It says that it must be #t.  And that is the problem.
> 
> Incorrect.
> 
> I hope I will be forgiven for injecting a factual statement into
> this flame war, but neither the IEEE/ANSI standard nor the R5RS
> assert what Matthias Blume claims they assert.

If you're going to be snarky it's best to be damn sure you're correct, 
and in this case you aren't.  R5RS does in fact assert precisely what 
Matthias says it does.  Here is the exact text cut and pasted from 
http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%25
_sec_6.1:

(let�((p�(lambda�(x)�x))) 
��(eqv?�p�p))���������������������������������===>�� #t 

rg
0
rNOSPAMon (1927)
10/13/2004 5:49:27 AM
Matthias Blume wrote:

> Because contract checking works by guarding procedure values with
> wrappers.  If you pass a function f value to a function g whose contrac=
t
> says it is to receive an int->int value, what gets actually passed to g=
 is
> roughly of the form:
>=20
>     (lambda (x) (if (integer? x)
>                     (let ((res (f x)))
>                          (if (integer? res)
>                              res
>                              (error "argument to g violates contract"))=
)
>                     (error "g violates contract")))
>=20
> This sort of wrapping happens whenever a procedure value travels past
> a guard, and identity of the lambda gets lost in the process.

Ok - now I see what you were thinking about.

--=20
Jens Axel S=F8gaard
0
usenet8944 (1130)
10/13/2004 7:16:51 AM
David Van Horn wrote:

> Following Matthias Blume's recipe:
>=20
>    (require (lib "contract.ss"))
>    (define/contract g (-> (-> any? any) (-> any? any) any)
>      eqv?)
>    (let ((f (lambda (x) x)))
>      (g f f))  ;; #f

Thanks.

--=20
Jens Axel S=F8gaard

0
usenet8944 (1130)
10/13/2004 7:21:21 AM
Joe Marshall wrote:

>
>   (let* ((a (foo))
>          (b (bar))) ;; assuming a is not free in bar
>     (baz a b))
>
> I know that the author, for whatever reason, thinks it is important
> that (foo) run *before* (bar).
>
> When I see (baz (foo) (bar)) in Scheme code, I *know* that the author
> did not think it important that (foo) be called before (bar).  I know
> this because

I have never stumpled across any unexpected behavior due to order of
evaluation issues in Bigloo. Honestly speaking: the thread made me aware
that it might be important. If someone had asked me yesterday: "do know
whether Scheme (in your case Bigloo) has any order of evaluation" I would
have said: sorry I have never thought about such things; note: I use
Scheme every day.

That said: I hope Bigloo calculates (foo) first  in: (baz (foo) (bar)). I
would expect that things are done from left to right.

So, I mean your tactitc that you assume that the programmer always knows
what he is doing is at least in my case wrong.

A destined order of evaluation in Scheme which is enforced by the
standard would be good. But I would never trade in Scheme for the reason
we are having now. Order of evaluation would somehow stand for a goody
but not necessarily for a feature which makes one a better programmer.

The only bad thing may occur when running the same Scheme code on
different Schme implemenations and every one of them uses its own order
of evaluation techniques. I mean such behaviors are then somewhat spoling
ones joy...

Fensterbrett

0
10/13/2004 7:25:23 AM
Ron Garret <rNOSPAMon@flownet.com> writes:
> In the real world, programmers write (f (g) (h)) not because 
> they really have confidence that g and h are order independent, but 
> because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
> they have a deadline to meet.  

Nonsense. I am very much a real-world programmer and I make a lot of
effort to be sure that there is no order dependence between g and
h. This applies even more in Scheme because I have a lot better
control of side-effects (and the necessity for them) than in the other
languages in which I get paid to program.

> In the real world, the processes that are 
> used to write real code resemble a random walk much more than a 
> mathematically principled methodology, 

Nonsense. There are very definitely semantically principled software
development processes within the OO world. This is not the same as
`mathematically principled', but it is a far cry from `random walk'.

Tell me, how are you ever going to have a `mathematically principled'
approach to software devleopment when the requirements are written by
people with little or no logical training, and who also frequently
don't even know what they really want?

david rush
-- 
The Revolution has begun...Comrade Shivers's helicopter will land on
College Green at 3.14pm. Deployment of the Underground begins soon
thereafter.  Lambda bandanas will be available...Please remain calm
and nobody will get skewered on parentheses. -- sk (on c.l.s)
0
kumoyuki (163)
10/13/2004 10:25:21 AM
Matthias Blume <find@my.address.elsewhere> writes:

>   Conceptually, use the following code:
>
>      1. (define g (lambda (x y) (eqv? x y)))
>         but put a contract on this g that says:
>         g is a function mapping two int->int functions to bool
>
>      3. (define f (lambda (x) (+ x 1)))
>
>      4. (g f f)

Doesn't this wrapping produce larger and slower functions each time
x or y is passed to other function with a contract? Say, g is map.

-- 
   __("<         Marcin Kowalczyk
   \__/       qrczak@knm.org.pl
    ^^     http://qrnik.knm.org.pl/~qrczak/
0
qrczak (1266)
10/13/2004 10:49:25 AM
Ron Garret <rNOSPAMon@flownet.com> wrote:
> If you're going to be snarky it's best to be damn sure you're correct, 
> and in this case you aren't.  R5RS does in fact assert precisely what 
> Matthias says it does.

You're right, and I apologize to you both.  I thought
procedures were treated like characters and numbers,
but they aren't.  Matthias was indeed correct, and he
is also correct that it is unfortunate he is correct.

Will
0
cesuraSPAM (401)
10/13/2004 12:40:47 PM
Marcin 'Qrczak' Kowalczyk <qrczak@knm.org.pl> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> >   Conceptually, use the following code:
> >
> >      1. (define g (lambda (x y) (eqv? x y)))
> >         but put a contract on this g that says:
> >         g is a function mapping two int->int functions to bool
> >
> >      3. (define f (lambda (x) (+ x 1)))
> >
> >      4. (g f f)
> 
> Doesn't this wrapping produce larger and slower functions each time
> x or y is passed to other function with a contract? Say, g is map.

Yes.  And that is another problem with any technique that relies on
wrapping functions.  Leroy-style representation analysis has the same
problem because it destroys space safety.

For DrScheme this is not quite as important because you can take the
stance that it is debugging tool, used only during testing.  And for
that reason it would be good if program's couldn't tell whether they
are being debugged or not.

Matthias
0
find19 (1244)
10/13/2004 12:54:35 PM
Thant Tessman <thant@acm.org> writes:

> Joe Marshall wrote:
>> Thant Tessman <thant@acm.org> writes:
>>
>>>Joe Marshall wrote:
>>>
>>>[...]
>>>
>>>
>>>>Do you think I favor unspecified order of evaluation because it
>>>>confuses people that (erroneously) expect it to be left to right?
>>>
>>>If not, why not fix OofE and simply tell programmers that it's a bad
>>>idea to write code that depends on OofE?
>>>
>> Why not simply tell programmers that it's a bad idea to write code
>> that depends on OofE?  You have to do that anyway.
>
> Because merely telling them will not prevent such code from being written.

So?  I didn't think that preventing this sort of thing was a goal.  I
can't see how to accomplish it if it is.

>> Remind me again what specifying the order of arguments solved?
>
> Code that is buggy in unspecified OofE is merely bad style in fixed
> OofE. 

I disagree.  Code is buggy if the programmer did not intend it to
depend on the order of evaluation, but it nevertheless does.
0
jrm (1310)
10/13/2004 1:55:44 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Joe Marshall <jrm@ccs.neu.edu> writes:
>
>> Thant Tessman <thant@acm.org> writes:
>> 
>> > Joe Marshall wrote:
>> >
>> > [...]
>> >
>> >> Do you think I favor unspecified order of evaluation because it
>> >> confuses people that (erroneously) expect it to be left to right?
>> >
>> > If not, why not fix OofE and simply tell programmers that it's a bad
>> > idea to write code that depends on OofE?
>> >
>> 
>> Why not simply tell programmers that it's a bad idea to write code
>> that depends on OofE?  You have to do that anyway.
>> 
>> Remind me again what specifying the order of arguments solved? 
>

> Here it is again:
>
>    1.  It eliminates non-determinism from the language, making its
>        semantics simpler.

Ok.  I understand the argument, but I don't believe you.  Since `left
to right' order is a subset of `an unspecified order', why not use L2R
as a simplification when talking about semantics?

>    2.  As a result, tests become repeatable across platforms and
>        implementations, which in turn adds relevance to the results of
>        testing.

I believe that Will debunked this in a previous post.

> You must have an awful short-term memory.

It's terrible.  Everyone tells me that definitive arguments have been
put forth, but I can't remember a single one that has not been
countered.

0
jrm (1310)
10/13/2004 1:59:35 PM
Joe Marshall <jrm@ccs.neu.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Joe Marshall <jrm@ccs.neu.edu> writes:
> >
> >> Thant Tessman <thant@acm.org> writes:
> >> 
> >> > Joe Marshall wrote:
> >> >
> >> > [...]
> >> >
> >> >> Do you think I favor unspecified order of evaluation because it
> >> >> confuses people that (erroneously) expect it to be left to right?
> >> >
> >> > If not, why not fix OofE and simply tell programmers that it's a bad
> >> > idea to write code that depends on OofE?
> >> >
> >> 
> >> Why not simply tell programmers that it's a bad idea to write code
> >> that depends on OofE?  You have to do that anyway.
> >> 
> >> Remind me again what specifying the order of arguments solved? 
> >
> 
> > Here it is again:
> >
> >    1.  It eliminates non-determinism from the language, making its
> >        semantics simpler.
> 
> Ok.  I understand the argument, but I don't believe you.  Since `left
> to right' order is a subset of `an unspecified order', why not use L2R
> as a simplification when talking about semantics?

I don't understand what you might mean by "subset".  Maybe you mean
that an implementation that uses l2r is faithful to the spec if the
spec did not prescribe any particular order.  So far so good.  On the
other hand, the set of programs that are correct under l2r is strictly
a superset of programs that are correct under the requirements that
the Scheme standard puts forward.

At this point I'd also like to note that it is /not/ the case that
programs which rely on the order of evaluation of function arguments
are necessarily wrong, and they are certainly not illegal!  Otherwise
there would be no need to go to any length in the semantics to deal
with this issue.  The spec could just say that programs must not
depend on a particular order (which can be formalized relatively
easily), and given this side condition the semantics could just assume
l2r (or any other fixed order).

So, in short, things are even more complicated than just saying
"relying on order is illegal".

> >    2.  As a result, tests become repeatable across platforms and
> >        implementations, which in turn adds relevance to the results of
> >        testing.
> 
> I believe that Will debunked this in a previous post.

Rumors have it that Will is not always correct (although when he isn't
he is usually pretty good at admitting it).

You don't believe me, I don't believe Will in this case (assuming he
really "debunked" the claim -- I can't remember what he really wrote).

It is *obvious* that testing is the easier the more repeatable test
experiments are. The higher the degree of similarity between results
on different implementations/platforms the hig higher the level of
confidence that test results run here mean something for the program
running there.

The best one can argue is that the effect is not as great as some make
it to be.  Incidentally, this parallels the discussion about added
information on programmer intention contained in programs under
unfixed order.  There I also cannot deny the truth of the claim, and I
also think that the benefits of it are blown way out of proportion by
those who use this fact as an argument in favor of unfixed order.

Matthias
0
find19 (1244)
10/13/2004 2:36:16 PM
In article <ckivqh$7u3$1@pixie.nscp.aoltw.net>,
 David Rush <kumoyuki@gmail.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In the real world, programmers write (f (g) (h)) not because 
> > they really have confidence that g and h are order independent, but 
> > because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
> > they have a deadline to meet.  
> 
> Nonsense. I am very much a real-world programmer and I make a lot of
> effort to be sure that there is no order dependence between g and
> h.

Bully for you.  Why do you think that has anything to do with what I 
said?  I did not say that *all* programmers take shortcuts, just that 
some do (and actually I believe that most do, but even that claim can't 
be countered with a single data point).

BTW, I've made this point before, I'll make it again: making, as you put 
it, "a lot of effort to eliminate order dependencies" is not sufficient 
to prevent the negative consequences of unspecified OoE.  You have to 
actually *succeed* in eliminating order dependencies 100% of the time.  
And *that* is something that the vast majority of programmers do not do 
and never will, notwithstanding the possible existence of the odd 
counterexample.

> > In the real world, the processes that are 
> > used to write real code resemble a random walk much more than a 
> > mathematically principled methodology, 
> 
> Nonsense. There are very definitely semantically principled software
> development processes within the OO world.

If we're going to start talking about "semantically principled software 
development processes within the OO world" then we'd better start a new 
thread.  In any case:

> This is not the same as `mathematically principled',

Indeed not.

> but it is a far cry from `random walk'.

I disagree.  But if you really want to have *that* conversation please 
start a new thread.

> Tell me, how are you ever going to have a `mathematically principled'
> approach to software devleopment when the requirements are written by
> people with little or no logical training, and who also frequently
> don't even know what they really want?

Yes, that would be precisely the point I am trying to make.

rg
0
rNOSPAMon (1927)
10/13/2004 3:04:22 PM
cesuraSPAM@verizon.net (William D Clinger) writes:
> You're right, and I apologize to you both.  I thought
> procedures were treated like characters and numbers,
> but they aren't.  Matthias was indeed correct, and he
> is also correct that it is unfortunate he is correct.

Why is it unfortunate? This:

(let�((p�(lambda�(x)�x))) 
��(eqv?�p�p))���������������������������������===>�� #t 

to me looks good. 

From a static analysis/program proving point of view I find it desirable that
a binding is identical to itself.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 4:36:09 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> cesuraSPAM@verizon.net (William D Clinger) writes:
> > You're right, and I apologize to you both.  I thought
> > procedures were treated like characters and numbers,
> > but they aren't.  Matthias was indeed correct, and he
> > is also correct that it is unfortunate he is correct.
> 
> Why is it unfortunate? This:
> 
> (let�((p�(lambda�(x)�x))) 
> ��(eqv?�p�p))���������������������������������===>�� #t 
> 
> to me looks good. 
> 
> From a static analysis/program proving point of view I find it desirable that
> a binding is identical to itself.

You must have not been reading the rest of the thread.
0
find19 (1244)
10/13/2004 6:10:27 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > Why is it unfortunate? This:
> > 
> > (let�((p�(lambda�(x)�x))) 
> > ��(eqv?�p�p))���������������������������������===>�� #t 
> > 
> > to me looks good. 
> > 
> > From a static analysis/program proving point of view I find it desirable
> > that a binding is identical to itself.
> 
> You must have not been reading the rest of the thread.

I have but do not recall this point. Method equivalence in general is hard and
not desirable or necessarily meaningful. 

But is (eqv? p p) unfortunate in any way? I.e. when accessing through the same
binding?

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 8:18:18 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> > Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > > Why is it unfortunate? This:
> > > 
> > > (let�((p�(lambda�(x)�x))) 
> > > ��(eqv?�p�p))���������������������������������===>�� #t 
> > > 
> > > to me looks good. 
> > > 
> > > From a static analysis/program proving point of view I find it desirable
> > > that a binding is identical to itself.
> > 
> > You must have not been reading the rest of the thread.
> 
> I have but do not recall this point. Method equivalence in general is hard and
> not desirable or necessarily meaningful. 

Looks like you have /not/ been reading the rest of the thread.

> But is (eqv? p p) unfortunate in any way?

Yes.  See the rest of the thread, in particular the discussion of DrScheme.

The Scheme report would be better off saying that

  (eqv? p q)

where p and q are procedure values is guaranteed to return #f if p and
q are also distinguishable some other way, and that otherwise nothing
is said about the result at all.  (In other words, a version of eqv?
and eq? that always returns #f for procedures would be conforming.)

This does not invalidate any existing Scheme implementation, but it
validates technology such as DrScheme.  Of course, it also renders eq?
and eqv? totally useless for the purpose of comparing procedure
values, but that is, IMO, how it should be.  Notice that many other
functional and semi-functional languages with generic equality do not
permit equality comparisons on functions at all (usually statically as
part of type checking).

Matthias
0
find19 (1244)
10/13/2004 8:27:34 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > I have but do not recall this point. Method equivalence in general is hard
> > and not desirable or necessarily meaningful.
> 
> Looks like you have /not/ been reading the rest of the thread.

Sigh. 

> > But is (eqv? p p) unfortunate in any way?
> 
> Yes.  See the rest of the thread, in particular the discussion of DrScheme.

What I got out of the discussion of DrScheme is that the attempts of
implementing contracts breaks things. Fine.

But also, the attempts of using contracts is no longer the case of binding
equivalance of (eqv? p p) but instead (eqv? (wrapper-of p) (wrapper-of p)).

I have no problem with this since one then no longer has the static situation
of (let ((p (lamda ...))) (eqv? p p)).

So I still fail to see how things are unfortunate.

Couldn't DrScheme be smarter and change things to be instead:

  (let ((p (wrapper-of (lamda ...))))
    (eqv? p p))

Which would let both the contract and eqv? for bindings work?

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 8:40:28 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> > Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > > I have but do not recall this point. Method equivalence in general is hard
> > > and not desirable or necessarily meaningful.
> > 
> > Looks like you have /not/ been reading the rest of the thread.
> 
> Sigh.

Shall we sigh together a little bit?  :-)

> What I got out of the discussion of DrScheme is that the attempts of
> implementing contracts breaks things. Fine.

Not fine at all.

> But also, the attempts of using contracts is no longer the case of binding
> equivalance of (eqv? p p) but instead (eqv? (wrapper-of p) (wrapper-of p)).

The presence of wrappers is supposed to be transparent to the program.

> I have no problem with this since one then no longer has the static situation
> of (let ((p (lamda ...))) (eqv? p p)).

Others do.

> Couldn't DrScheme be smarter and change things to be instead:
> 
>   (let ((p (wrapper-of (lamda ...))))
>     (eqv? p p))
> 
> Which would let both the contract and eqv? for bindings work?

No.

Think about it!  The contract in question could be arbitrarily
far "down the road".  What R5RS requires is that a procedure's
identity be preserved when the value is passed around.  But passing
the value across a contract boundary will inherently not be able to do
that.

(Actually, one could imagine having low-level support for this, e.g.,
by being able to use some other procedure's location tag when
evaluating a lambda.  This, however, would lead to situations where
procedures that are not operationally equivalent can compare equal.
The whole idea of comparing procedures for equality is, IMNSHO,
wrong-headed.)

Matthias
0
find19 (1244)
10/13/2004 8:50:58 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Think about it!  The contract in question could be arbitrarily
> far "down the road".  What R5RS requires is that a procedure's
> identity be preserved when the value is passed around.  But passing
> the value across a contract boundary will inherently not be able to do
> that.

Yes, I understand. All I get out of this is that DrScheme's implementation of
contracts is broken.

DrScheme is a proper Scheme implementation right? Why can't it not access
low-level support to do what it needs?

> (Actually, one could imagine having low-level support for this, e.g.,
> by being able to use some other procedure's location tag when
> evaluating a lambda.  This, however, would lead to situations where
> procedures that are not operationally equivalent can compare equal.

Or you could do something better. Procedure objects could have an overridable
EQV method (at least internally). Wrapper procedures override EQV to
invoke the EQV method of the procedure they are wrapping.

That way, (eqv? (wrapper p) (wrapper p)) would hold just fine.

This is in fact the usual way to do wrapper objects in the standard languages.

> The whole idea of comparing procedures for equality is, IMNSHO,
> wrong-headed.)

This is the real issue. I only see that a particular implementation of
contracts does not work.

From a theoretical point of view, however, procedures are first-class values,
and as such asking about their identity is a natural thing to do.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 9:06:27 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> Matthias Blume <find@my.address.elsewhere> writes:
> > (Actually, one could imagine having low-level support for this, e.g.,
> > by being able to use some other procedure's location tag when
> > evaluating a lambda.  This, however, would lead to situations where
> > procedures that are not operationally equivalent can compare equal.
> 
> Or you could do something better. Procedure objects could have an overridable
> EQV method (at least internally). Wrapper procedures override EQV to
> invoke the EQV method of the procedure they are wrapping.

To clarify, since I realize the above could be viewed as essentially saying
the same thing:

"procedures that are not operationally equivalent can compare equal"

The actual contract wrappers are not supposed to be visible at the language
level anyway. Furthermore, two different wrapper instances of the same
procedure p would in fact be operationally equivalent.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 9:10:39 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> From a theoretical point of view, however, procedures are first-class values,
> and as such asking about their identity is a natural thing to do.

Nonsense.

What is the difference between identity and equality?  Maybe asking
for equality is a natural thing to do, but answering such a question
is, unfortunately, not computable in general.  Identity, otoh, is an
artifical concept that was slapped on in a totally ad-hoc way -- by
making the evaluation of lambda have a side-effect!  I see no reason
for it being natural or desirable.

Matthias
0
find19 (1244)
10/13/2004 9:11:50 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Furthermore, two different wrapper instances of the same
> procedure p would in fact be operationally equivalent.

False.
0
find19 (1244)
10/13/2004 9:12:41 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> The actual contract wrappers are not supposed to be visible at the language
> level anyway. Furthermore, two different wrapper instances of the same
> procedure p would in fact be operationally equivalent.

God, I gotta stop following up to my own messages.

Two difference wrapper instances *for the same contract* would be
operationally equivalent.

EQV for wrappers need to also take the identify of the wrapper/contract itself
into account. Not a problem.

The point is that I believe that the contract mechanism in DrScheme can be
fixed.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 9:13:21 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> EQV for wrappers need to also take the identify of the wrapper/contract itself
> into account. Not a problem.

Yes a problem!  The program will behave differently according to
whether contract checking is on or off.

> The point is that I believe that the contract mechanism in DrScheme can be
> fixed.

I doubt that very much.

The designers of DrScheme did not find this problem worth fixing.
Maybe identity of lambdas is not so important after all?
0
find19 (1244)
10/13/2004 9:18:24 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
>
>> From a theoretical point of view, however, procedures are first-class values,
>> and as such asking about their identity is a natural thing to do.
>
> Nonsense.
>
> What is the difference between identity and equality?  Maybe asking
> for equality is a natural thing to do, but answering such a question
> is, unfortunately, not computable in general.  Identity, otoh, is an
> artifical concept that was slapped on in a totally ad-hoc way -- by
> making the evaluation of lambda have a side-effect!  I see no reason
> for it being natural or desirable.

It depends on whether you are talking intensionally or extensionally.
I happen to think identity is *not* a property of objects, but rather
of relationships between objects.  As such, EQ? can make sense on
procedures.  (Of course, the mechanism for EQ? is rather kludgy as
defined.)

0
jrm (1310)
10/13/2004 9:48:18 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> 
> > EQV for wrappers need to also take the identify of the wrapper/contract itself
> > into account. Not a problem.
> 
> Yes a problem!  The program will behave differently according to
> whether contract checking is on or off.

Well yes. If contract checking is off, no runtime errors for failed contracts
will occur.

It terms of identity, the scheme code will behave the same in both cases,
since it won't be able to tell the difference between a procedure p and
(wrapper p), since wrappers are not supposed to be visible. 

This *is* what is desired if one has procedure identity.

> > The point is that I believe that the contract mechanism in DrScheme can be
> > fixed.
> 
> I doubt that very much.
> 
> The designers of DrScheme did not find this problem worth fixing.
> Maybe identity of lambdas is not so important after all?

Maybe. I prefer to have a language where if I throw an arbitrary object into a
list, I can ask if *that thing* is in the list or not.

Consider a home-brew implementation of an OO mechanism where one can override
behaviour by keeping data structures of "dispatch" procedures. Identity is
needed to determine whether or not a method is already overridden, etc.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 9:50:26 PM
Matthias Blume <find@my.address.elsewhere> writes:
> What is the difference between identity and equality?  Maybe asking
> for equality is a natural thing to do, but answering such a question
> is, unfortunately, not computable in general.  Identity, otoh, is an
> artifical concept that was slapped on in a totally ad-hoc way -- by
> making the evaluation of lambda have a side-effect!  I see no reason
> for it being natural or desirable.

But identity is all we can get for procedures, since their general equality is
not computable. Identity lets us build language frameworks involving procedure
mechanisms.

In practical terms it lets us build useful things. In theoretical terms the
side effects are essentially hidden.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 9:54:27 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Consider a home-brew implementation of an OO mechanism where one can override
> behaviour by keeping data structures of "dispatch" procedures. Identity is
> needed to determine whether or not a method is already overridden, etc.

I don't understand.  How would identity help?
0
find19 (1244)
10/13/2004 9:58:56 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> In practical terms it lets us build useful things.

Are you saying that you can build things with procedure identity that
you otherwise couldn't?

This would come as a real surpise to someone like me who most of the
time is using a language where one cannot compare procedures for
identity.

In any case, procedure identity is a poor man's approximation to
comparing functions for equality, and as such it is IMO far too
fragile to be useful.

> In theoretical terms the side effects are essentially hidden.

No, they are not.  That is the problem, actually.
0
find19 (1244)
10/13/2004 10:03:46 PM
Thant Tessman wrote:
> Hartmann Schaffer wrote:
> 
>> Thant Tessman wrote:
>>
>>> Joe Marshall wrote:
>>>
>>> [...]
>>>> Do you think I favor unspecified order of evaluation because it
>>>> confuses people that (erroneously) expect it to be left to right?
>>>
>>> If not, why not fix OofE and simply tell programmers that it's a bad 
>>> idea to write code that depends on OofE?
>>
>> wouldn't telling them that the order of evaluation is unspecified the 
>> best way of telling them that?
> 
> Why? Because it carries the extra weight of the threat of buggy code? 
> Joe just said he didn't want to be hostile to newbies.

from the discussion in this thread i got the impression that pretty much 
everybody agrees that code that depends on the OofE is a bad idea. 
personally, i would (as a  newby) find it much more confusing to be told 
that the OofE is strictly specified and to be simultaneously admonished 
to rely on it

hs
0
hs60 (77)
10/13/2004 10:04:16 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> 
> > Consider a home-brew implementation of an OO mechanism where one can override
> > behaviour by keeping data structures of "dispatch" procedures. Identity is
> > needed to determine whether or not a method is already overridden, etc.
> 
> I don't understand.  How would identity help?

Relating it to contracts, consider an implementation whereby (wrapper p)
returned a new wrapper if p had not been wrapped yet before. It p is already
wrapped, then that existing wrapper could be returned, retrieved from some
sort of table.

Procedure comparison using p as a key would be needed to determine if p was
already wrapped.

This approach could also fix DrScheme's contract problem, at the expense of
efficiency.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 10:12:20 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> 
> > In practical terms it lets us build useful things.
> 
> Are you saying that you can build things with procedure identity that
> you otherwise couldn't?

No, only that it is convenient.

> In any case, procedure identity is a poor man's approximation to
> comparing functions for equality, and as such it is IMO far too
> fragile to be useful.
> 
> > In theoretical terms the side effects are essentially hidden.
> 
> No, they are not.  That is the problem, actually.

Do you have other examples besides the DrScheme's contract mechanism that show
the fragility or the bad side effects? I am seriously interested to know.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/13/2004 10:14:56 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> > Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > 
> > > Consider a home-brew implementation of an OO mechanism where one can override
> > > behaviour by keeping data structures of "dispatch" procedures. Identity is
> > > needed to determine whether or not a method is already overridden, etc.
> > 
> > I don't understand.  How would identity help?
> 
> Relating it to contracts, consider an implementation whereby (wrapper p)
> returned a new wrapper if p had not been wrapped yet before. It p is already
> wrapped, then that existing wrapper could be returned, retrieved from some
> sort of table.
>
> Procedure comparison using p as a key would be needed to determine if p was
> already wrapped.

Way too fragile and inefficient.

> This approach could also fix DrScheme's contract problem, at the expense of
> efficiency.

I highly doubt that.

0
find19 (1244)
10/13/2004 10:33:17 PM
Matthias Blume wrote:
> ...
>>>All I want is procedure calls to have a well-defined deterministic
>>>semantics in all cases.  This makes for a simpler semantics, i.e., a
>>>simpler mental model. As a bonus you also get more meaningful results
>>>from testing.
>>
>>for me, the rule that everything must be evaluated before it is used
>>is deterministic enough.
> 
> So you want Scheme to be lazy?

no.  when talking about function arguments, in a non lazy language the 
call establishes the use.

hs
0
hs60 (77)
10/13/2004 10:38:10 PM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> No, only that it is convenient.

I don't find it particularly convenient.  Using it in programs seems
highly contrived, and for the implementer it is highly inconvenient.
0
find19 (1244)
10/13/2004 10:40:20 PM
Hartmann Schaffer <hs@hartmann.schaffernet> writes:

> Matthias Blume wrote:
> > ...
> >>>All I want is procedure calls to have a well-defined deterministic
> >>>semantics in all cases.  This makes for a simpler semantics, i.e., a
> >>>simpler mental model. As a bonus you also get more meaningful results
> >>>from testing.
> >>
> >>for me, the rule that everything must be evaluated before it is used
> >>is deterministic enough.
> > So you want Scheme to be lazy?
> 
> no.  when talking about function arguments, in a non lazy language the
> call establishes the use.

And in a language with observable side effects and, e.g., a
left-to-right order of evaluation, the argument to the right
establishes a use of (the effect of) the argument to the left.

So it all depends on what one considers a "use".  In other words,
invoking the notion of "before it is used" doesn't shed any new light
on the issue.  Different rules on evaluation order = different notions
of "use".

Matthias
0
find19 (1244)
10/13/2004 10:44:17 PM
Excuse me a moment, folks, while I talk to myself.

> You're right, and I apologize to you both.  I thought
> procedures were treated like characters and numbers,
> but they aren't.

You toothless bagbiter!  Cretinous loser!  Imbecilic peabrain!
Ignorant moron!  Repeater of cliched epithets!  You idiot who
doesn't even know how to type the accent in "clich�d"!

Your excuse would be lame even if we were talking about EQ?,
but we were talking about EQV?, you pathetic zipperhead!

Sheesh.

Will
0
cesuraSPAM (401)
10/14/2004 12:17:22 AM
Hartmann Schaffer wrote:

[...]

> from the discussion in this thread i got the impression that pretty much 
> everybody agrees that code that depends on the OofE is a bad idea. 
> personally, i would (as a  newby) find it much more confusing to be told 
> that the OofE is strictly specified and to be simultaneously admonished 
> to rely on it

The reasons it's a bad idea are only indirectly related to OofE itself. 
Unspecified OofE only matters when evaluating the arguments causes side 
effects that are order-dependent. Side effects (especially remote side 
effects) are bad because they separate cause and effect both in space 
and time, making it harder to figure out what's going on. Unspecified 
OofE is only one of many ways of obscuring side effects. If the side 
effects are obvious and otherwise inconvenient-to-avoid (like I/O), 
there's nothing wrong with relying on fixed OofE any more than than 
relying on side effects in the first place.

But most importantly, code might depend on OofE unintentionally 
regardless of whether it's fixed or not. At least fixed OofE makes it 
easier to figure out what a program is really doing.

-thant
0
thant (332)
10/14/2004 12:58:31 AM
=?ISO-8859-1?Q?Jens_Axel_S=F8gaard?= <usenet@soegaard.net> writes:
> Matthias Blume wrote:
> > This sort of wrapping happens whenever a procedure value travels past
> > a guard, and identity of the lambda gets lost in the process.

And since the identity of lambda is part of Scheme, DrScheme's contract
mechanism is broken in this regard, since it does not preserve it.

So it's not a serious enough bug in practice to require fixing. Fine.
Certainly the current implementation is dead simple, which has its own
advantages.

But it could be fixed relatively easily, I think.

At the very least, the DrScheme contract mechanism's failure to preserve the
identity of lambda does not illustrate that lambda identity as a concept is
problematic, only that the contract implementation is problematic.

*Any* naive wrapping mechanism will destroy simple eqv? semantics. That does
not mean that identity of records and lists (for example) is a bad idea.

We need (or at least I do) more fundamental examples as to why lambda identity
is bad in principle.

-- 
Cheers,                                        The Rhythm is around me,
                                               The Rhythm has control.
Ray Blaak                                      The Rhythm is inside me,
rAYblaaK@STRIPCAPStelus.net                    The Rhythm has my soul.
0
rAYblaaK (362)
10/14/2004 5:52:03 AM
In article <m1wtxuw8bv.fsf@tti5.uchicago.edu>,
Matthias Blume  <find@my.address.elsewhere> wrote:
> Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> 
> > No, only that it is convenient.
> 
> I don't find it particularly convenient.  Using it in programs seems
> highly contrived, and for the implementer it is highly inconvenient.

It can be occasionally useful for optimizations:

http://google.com/groups?selm=afdimg$mh$1@la.iki.fi


Lauri Alanko
la@iki.fi
0
la (473)
10/14/2004 6:41:43 AM
> Tell me, how are you ever going to have a `mathematically principled'
> approach to software devleopment when the requirements are written by
> people with little or no logical training, and who also frequently
> don't even know what they really want?

It is always possible to have a 'mathematically principled' approach,
when one doesn't ask the question, "does it make sense?". 

However, a lot of effort must be taken to make the requirements analysis
a success. And my experience is, that if the requirements have been 
thorougly analysed, a set of construction principles can be derived from
them, for which a  'mathematical precision' can be reached.

-- 
Hans Oesterholt-Dijkema

0
hdnews (142)
10/14/2004 8:02:13 AM
Ron Garret <rNOSPAMon@flownet.com> writes:
> In article <ckivqh$7u3$1@pixie.nscp.aoltw.net>,
>  David Rush <kumoyuki@gmail.com> wrote:
> 
> > Ron Garret <rNOSPAMon@flownet.com> writes:
> > > In the real world, programmers write (f (g) (h)) not because 
> > > they really have confidence that g and h are order independent, but 
> > > because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
> > > they have a deadline to meet.  
> > 
> > Nonsense. I am very much a real-world programmer and I make a lot of
> > effort to be sure that there is no order dependence between g and
> > h.
> 
> Bully for you.  Why do you think that has anything to do with what I 
> said?  

Because your use of the word 'programmers' could be reasonably
believed to be universally quantified; especially since the only
qualification you made was 'in the real world'. Hence a single
counter-example is sufficient to disprove the thesis.

In the thread context, this is all about levels of trust. You appear
to trust programmers to consistently do the wrong thing. I however,
like the approach advocated by the estimable Mr. Naggum:

    ... it's just that in C++ and the like, you don't trust _anybody_,
    and in CLOS you basically trust everybody.  the practical result
    is that thieves and bums use C++ and nice people use CLOS.

> > Tell me, how are you ever going to have a `mathematically principled'
> > approach to software devleopment when the requirements are written by
> > people with little or no logical training, and who also frequently
> > don't even know what they really want?
> 
> Yes, that would be precisely the point I am trying to make.

Well under those circumstances, the amount of error introduced by the
occasional OoE mistake is so small as to be nonexistent. At least that
is *my* experience in developing real-world software.

david rush
-- 
No matter how far down the wrong road you've gone, turn back.
	-- Turkish proverb
0
kumoyuki (163)
10/14/2004 10:22:01 AM
Matthias Blume <find@my.address.elsewhere> writes:
> The Scheme report would be better off saying that
> 
>   (eqv? p q)
> 
> where p and q are procedure values is guaranteed to return #f if p and
> q are also distinguishable some other way, and that otherwise nothing
> is said about the result at all.  (In other words, a version of eqv?
> and eq? that always returns #f for procedures would be conforming.)
<chop/>
> Of course, it also renders eq? and eqv? totally useless for the
> purpose of comparing procedure values, but that is, IMO, how it
> should be. 

I feel that I should point out that this then breaks the notion of
object identity in a naive closure-based OO implementation (such as
YASOS). Mind you, I'm not as keen on OO models of reuse as I once was,
but it is nice that the superset expressivity of FP can be shown so
easily in Scheme.

david rush
-- 
Constructivism - mathematical activism
Intuitionism - mathematical solipsism
        -- Bill Taylor (on alt.math.recreational)
0
kumoyuki (163)
10/14/2004 10:28:31 AM
Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:

> =?ISO-8859-1?Q?Jens_Axel_S=F8gaard?= <usenet@soegaard.net> writes:
> > Matthias Blume wrote:
> > > This sort of wrapping happens whenever a procedure value travels past
> > > a guard, and identity of the lambda gets lost in the process.
> 
> And since the identity of lambda is part of Scheme, DrScheme's contract
> mechanism is broken in this regard, since it does not preserve it.

If the goal was to preserve Scheme semantics, yes.  If the goal was to
build a sensible langage, no.

> But it could be fixed relatively easily, I think.

Why don't you show how then?

> At the very least, the DrScheme contract mechanism's failure to preserve the
> identity of lambda does not illustrate that lambda identity as a concept is
> problematic, only that the contract implementation is problematic.

See above.  (And identity of lambda is problematic on its own anyway.)

> *Any* naive wrapping mechanism will destroy simple eqv? semantics.

Yes.

> That does not mean that identity of records and lists (for example)
> is a bad idea.

Actually, I think it is, but that's a different story.

> We need (or at least I do) more fundamental examples as to why lambda identity
> is bad in principle.

Because it is inherently imperative, and there is almost no gain in
expressive power, so the usual arguments in favor of imperative
features do not hold.

0
find19 (1244)
10/14/2004 1:14:45 PM
Thant Tessman wrote:

[...]

> The reasons [relying on fixed OofE are] a bad idea are only indirectly
> related to OofE itself. Unspecified OofE only matters when evaluating
> the arguments causes side effects that are order-dependent. Side
> effects (especially remote side effects) are bad because they
> separate cause and effect both in space and time, making it harder to
> figure out what's going on. Unspecified OofE is only one of many ways
> of obscuring side effects. If the side effects are obvious and
> otherwise inconvenient-to-avoid (like I/O), there's nothing wrong
> with relying on fixed OofE any more than than relying on side effects
> in the first place.

I was distracted when I wrote this. Replace "Unspecified OofE" with just
plain "OofE."

-thant

0
thant (332)
10/14/2004 1:24:10 PM
In article <cklk09$5ko$1@pixie.nscp.aoltw.net>,
 David Rush <kumoyuki@gmail.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> > In article <ckivqh$7u3$1@pixie.nscp.aoltw.net>,
> >  David Rush <kumoyuki@gmail.com> wrote:
> > 
> > > Ron Garret <rNOSPAMon@flownet.com> writes:
> > > > In the real world, programmers write (f (g) (h)) not because 
> > > > they really have confidence that g and h are order independent, but 
> > > > because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
> > > > they have a deadline to meet.  
> > > 
> > > Nonsense. I am very much a real-world programmer and I make a lot of
> > > effort to be sure that there is no order dependence between g and
> > > h.
> > 
> > Bully for you.  Why do you think that has anything to do with what I 
> > said?  
> 
> Because your use of the word 'programmers' could be reasonably
> believed to be universally quantified;

It could much more reasonably be believed not to be.  Which it wasn't.


> In the thread context, this is all about levels of trust. You appear
> to trust programmers to consistently do the wrong thing. I however,
> like the approach advocated by the estimable Mr. Naggum:
> 
>     ... it's just that in C++ and the like, you don't trust _anybody_,
>     and in CLOS you basically trust everybody.  the practical result
>     is that thieves and bums use C++ and nice people use CLOS.

I've sworn off arguing with Erik Naggum, even by proxy.  But I will 
point out that 1) trusting people not to intentionally break abstraction 
barriers unless they have a damn good reason is very different from 
trusting people never to make a mistake and write code that happens to 
have an OoE dependency, and 2) I would think that an environment without 
security mechanism would tend to *attract* thieves and bums rather than 
repel them.


> > > Tell me, how are you ever going to have a `mathematically principled'
> > > approach to software devleopment when the requirements are written by
> > > people with little or no logical training, and who also frequently
> > > don't even know what they really want?
> > 
> > Yes, that would be precisely the point I am trying to make.
> 
> Well under those circumstances, the amount of error introduced by the
> occasional OoE mistake is so small as to be nonexistent. At least that
> is *my* experience in developing real-world software.

Would you be willing to bet your career that no one on your programming 
team will ever make such a mistake?

rg
0
rNOSPAMon (1927)
10/14/2004 1:35:26 PM
Lauri Alanko <la@iki.fi> writes:

> In article <m1wtxuw8bv.fsf@tti5.uchicago.edu>,
> Matthias Blume  <find@my.address.elsewhere> wrote:
> > Ray Blaak <rAYblaaK@STRIPCAPStelus.net> writes:
> > 
> > > No, only that it is convenient.
> > 
> > I don't find it particularly convenient.  Using it in programs seems
> > highly contrived, and for the implementer it is highly inconvenient.
> 
> It can be occasionally useful for optimizations:
> 
> http://google.com/groups?selm=afdimg$mh$1@la.iki.fi

For this, as you note yourself, you still need to be able to check for
equality "the slow way" if the shortcut says "false".  But for
procedure values that is not possible.

It's better not to rely on this misfeature and do things right
instead.
0
find19 (1244)
10/14/2004 2:22:31 PM
David Rush <kumoyuki@gmail.com> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> > The Scheme report would be better off saying that
> > 
> >   (eqv? p q)
> > 
> > where p and q are procedure values is guaranteed to return #f if p and
> > q are also distinguishable some other way, and that otherwise nothing
> > is said about the result at all.  (In other words, a version of eqv?
> > and eq? that always returns #f for procedures would be conforming.)
> <chop/>
> > Of course, it also renders eq? and eqv? totally useless for the
> > purpose of comparing procedure values, but that is, IMO, how it
> > should be. 
> 
> I feel that I should point out that this then breaks the notion of
> object identity in a naive closure-based OO implementation (such as
> YASOS).

That notion of object identity could *trivially* be restored by
slightly changing object representation from "procedure" to "pair of
procedure and identity".  Of course, that's what procedures currently
are by default.  It just so happens that the default is wrong: One
almost never needs identity for procedures -- and having to maintain
it is a nuisance to implementors.   And when it is needed, it is almost
trivial to home-cook.  The home-cook method also has the advantage of
being explicit, so the compiler knows what's going on.

> but it is nice that the superset expressivity of FP can be shown so
> easily in Scheme.

You have shown nothing.

0
find19 (1244)
10/14/2004 2:26:59 PM
cesuraSPAM@verizon.net (William D Clinger) writes:

> Excuse me a moment, folks, while I talk to myself.
>
>> You're right, and I apologize to you both.  I thought
>> procedures were treated like characters and numbers,
>> but they aren't.
>
> You toothless bagbiter!  

Wouldn't this be a bag-gnawer?
0
jrm (1310)
10/14/2004 3:05:49 PM
Ron Garret wrote:

> But I will
> point out that 1) trusting people not to intentionally break abstraction
> barriers unless they have a damn good reason is very different from
> trusting people never to make a mistake and write code that happens to
> have an OoE dependency, 

It could be argued, though, that it is not so different,  
in that depending on OoE does break an abstraction barrier on a 
par with, for argument's sake, depending
on the order of elements in a set ADT.

The abstraction that is being broken, in this case, is the 
requirement of the current Scheme standard that certain code
transformations be permitted with respect to procedure calls  
(this is similar in spirit to asserting that for, e.g., a set ADT, 
one has (insert a (insert b s)) = (insert b (insert a s))).
This expectation that functions calls not be used for sequencing
is rather ingrained in some of us (perhaps not you) and used by
various optimizing compilers.  

You can certainly change the procedure call "abstraction"
by declaring fixed OoE, but inexperienced (and experienced) 
programmers would likely continue to act according to this 
expectation when refactoring code even if you were to fix OoE.  
So while one would eliminate one class of bugs, 
one would create an atmosphere that invites another kind of bugs, 
not to mention a whole new way of writing obfuscated code.
An additional (addmittedly subjective) advantage of the current 
state of affairs is that it implicitly encourages a more 
"functional" style. 
So it is not at all clear whether it would be a *net* improvement.
It certainly would not be cost-free, as has been argued by some.   

> Would you be willing to bet your career that no one on your programming
> team will ever make such a mistake?

In critical applications where determinism is important, I would 
strongly consider using an implementation that fixes OoE, especially if I 
were to work with inexperienced programmers (but then, should I
use inexperienced programmers for critical applications?).  
Since in these cases portability is seldom an issue,
I would not impose the burden of fixed OoE on all implementations
by changing the current standard.  Especially since it is obviously not 
universally considered to be a good idea.  

A.
0
andre9567 (120)
10/14/2004 3:51:20 PM
Thant Tessman wrote:
> Hartmann Schaffer wrote:
> 
> [...]
> 
>> from the discussion in this thread i got the impression that pretty 
>> much everybody agrees that code that depends on the OofE is a bad 
>> idea. personally, i would (as a  newby) find it much more confusing to 
>> be told that the OofE is strictly specified and to be simultaneously 
>> admonished to rely on it

i left out a "not" here
> 
> The reasons it's a bad idea are only indirectly related to OofE itself. 
> Unspecified OofE only matters when evaluating the arguments causes side 
> effects that are order-dependent.

didn't you mean "when side effects in the evaluation of one argument 
have an effect on the value of later evaluated arguments"?

> ...
> Unspecified 
> OofE is only one of many ways of obscuring side effects.

what do you mean by "obscuring side effects"?  i would suspect that 
different compilation parameters (e.g. optimization levels) would make 
it more likely to reveal that such code exists when the order of 
evaluation is unspecified

> If the side 
> effects are obvious and otherwise inconvenient-to-avoid (like I/O), 
> there's nothing wrong with relying on fixed OofE any more than than 
> relying on side effects in the first place.

imo (i admit this is a taste question) i find code like
   (f (read) (read) (read))
less readable than having a few reads into suitably named variables 
followed by a call to f with those variables as arguments.  but what i 
find more disturbing is that a fixed order of evaluation has a negative 
impact on optimization opportunities for a compiler, so i see two 
conflicting goals, one of them imo of questionable merit

> But most importantly, code might depend on OofE unintentionally 
> regardless of whether it's fixed or not.

if the order is not fixed, this would be a bug, and if it is fixed you 
can rely on quite a few people doing it intentionally ("the language 
spec say the order is left to right, so what is wrong with relying on 
it?").  since there seems to be a wide agreement that relying on the 
order of evaluation for side effects ...

> At least fixed OofE makes it 
> easier to figure out what a program is really doing.

at the point where you figure out what the program is doing, you also 
have figured out that you rely on the OofE for side effects.  if that is 
a violation of language specs, you have found the bug and know how to fix it

hs
0
hs60 (77)
10/14/2004 6:53:22 PM
Hartmann Schaffer wrote:


> [...] if the order is not fixed, this would be a bug, and if it is fixed you 
> can rely on quite a few people doing it intentionally [...]

If the code unintentionally relies on OofE it's a bug regardless of 
whether OofE is fixed or not, and has just as much a chance of working 
by accident in either situation. If the code intentionally relies on 
fixed OofE there's nothing guaranteeing the code won't work in a 
language with unspecified OofE regardless of the fact that it's a bug. 
The only thing distinguishing the two situations is that it is simply 
not a bug to rely on fixed OofE in a language that specified fixed OofE. 
Why is this bad if not for the fact that someone is getting away with a 
style of programming with which one disapproves?

In other words, it's one thing to argue that OofE should be left 
unspecified for performance considerations (although I'm skeptical of 
the sincerity of such arguments given other foregone performance 
opportunities). But all these other arguments really do boil down to the 
desire to punish ignorance and bad style.

Regardless, this thread is going in circles yet again...

-thant

0
thant (332)
10/14/2004 9:35:47 PM
Ron Garret <rNOSPAMon@flownet.com> wrote:

> David Rush <kumoyuki@gmail.com> wrote:
....
> > Well under those circumstances, the amount of error introduced by the
> > occasional OoE mistake is so small as to be nonexistent. At least that
> > is *my* experience in developing real-world software.
>
> Would you be willing to bet your career that no one on your
> programming team will ever make such a mistake?

Of course, almost all Schemes in fact have a fixed order of evaluation, so
presumably you're worrying about the case where a career-destroying mistake
with OofE is made while porting a mission-critical Scheme app from one
implementation to another? Please, be serious.

In any case, given that David has just pointed out what a minimal risk this
has proved to be in the real world, why are you picking on this issue to bet
careers over?  Are you willing to bet your career that no-one on your
programming team will ever refactor an expression and thus introduce an
order of evaluation bug because OofE was silently depended on?  What's the
difference between those two scenarios (aside from the fact that in the
unspecified OofE case, you have more information to go on?)

Millions of C and C++ programmers have "bet their careers" on the
unspecified order case, for decades.  Those languages have plenty of
problems and limitations, but unspecified OofE is very low on that list.
Devoted fans of those languages occasionally wonder how Schemers can ever
bet anything on their language, given that in the default case, Scheme makes
no guarantees against type errors at runtime.  But somehow, people "bet
their careers" on such languages, too - not so many careers are bet over
Scheme, but plenty are bet over Python.

The argument by fear is particularly silly in this case.

Anton


0
anton58 (1240)
10/15/2004 6:04:34 AM
Joe Marshall wrote:
> Thant Tessman <thant@acm.org> writes:

[...]

>>Code that is buggy in unspecified OofE is merely bad style in fixed
>>OofE. 
> 
> 
> I disagree.  Code is buggy if the programmer did not intend it to
> depend on the order of evaluation, but it nevertheless does.

Not in the case where one relies on it deliberately. To do so in Scheme 
is a bug. To do so in a language with fixed OofE is not a bug--which 
seems to bother some people to no end.

-thant

0
thant (332)
10/15/2004 12:09:20 PM
In article <SLJbd.4724$SZ5.958@newsread2.news.atl.earthlink.net>,
 "Anton van Straaten" <anton@appsolutions.com> wrote:

> Ron Garret <rNOSPAMon@flownet.com> wrote:
> 
> > David Rush <kumoyuki@gmail.com> wrote:
> ...
> > > Well under those circumstances, the amount of error introduced by the
> > > occasional OoE mistake is so small as to be nonexistent. At least that
> > > is *my* experience in developing real-world software.
> >
> > Would you be willing to bet your career that no one on your
> > programming team will ever make such a mistake?
> 
> Of course, almost all Schemes in fact have a fixed order of evaluation, so
> presumably you're worrying about the case where a career-destroying mistake
> with OofE is made while porting a mission-critical Scheme app from one
> implementation to another?

That is one scenario.  It is not the only one.  Someone in this thread 
mentioned a Scheme implementation whose properties are such that its OoE 
changes every time it compiles itself.

> Please, be serious.

I am being serious.

> In any case, given that David has just pointed out what a minimal risk this
> has proved to be in the real world, why are you picking on this issue to bet
> careers over?

Because with all due respect, I do not consider David's experience to 
represent the last word on this issue.

> Are you willing to bet your career that no-one on your
> programming team will ever refactor an expression and thus introduce an
> order of evaluation bug because OofE was silently depended on?

The situation on the ground is that people are actually quite paranoid 
about such changes once the code has been certified as working.  They 
are also quite paranoid (with good reason) about changing compilers 
precisely because the language they are using (C mostly) does not 
provide enough guarantees to allow code to be reliably ported from one 
compiler to another.  This causes very serious bottlenecks in the code 
development process, because the compiler that has entrenched itself in 
the flight code development process (at least here at JPL) is not gcc.

> What's the
> difference between those two scenarios (aside from the fact that in the
> unspecified OofE case, you have more information to go on?)

The difference is that refactoring requires affirmative action on the 
part of someone on my team, and will be manifest in the revision control 
system.  Changing OoE can be done by my Scheme implementation silently 
behind my back.

> Millions of C and C++ programmers have "bet their careers" on the
> unspecified order case, for decades.  Those languages have plenty of
> problems and limitations, but unspecified OofE is very low on that list.

That's because that problem is dwarfed by all the other problems that C 
and C++ have.  But once you solve all those problems, as Scheme has, the 
remaining issues come to the fore.

> Devoted fans of those languages occasionally wonder how Schemers can ever
> bet anything on their language, given that in the default case, Scheme makes
> no guarantees against type errors at runtime.  But somehow, people "bet
> their careers" on such languages, too - not so many careers are bet over
> Scheme, but plenty are bet over Python.

Python, being a single-implementation language, effectively has a fixed 
OoE even if the language spec doesn't mandate it.  (I don't actually 
know whether the Python spec does or doesn't.)

But as an aside, I predict that it is only a matter of time before you 
read in comp.risks about some disaster or other that is caused by 
someone cutting and pasting Python code and screwing up the indentation 
as a result.  (I've had this same argument with the Python folks.)

> The argument by fear is particularly silly in this case.

I disagree.  When an opportunity presents itself to prevent potential 
catastrophe at very low cost it's not silly to take advantage of it 
*before* you have a case study to point at.

rg
0
rNOSPAMon (1927)
10/15/2004 1:39:19 PM
Ron Garret <rNOSPAMon@flownet.com> writes:
>  David Rush <kumoyuki@gmail.com> wrote:
> > In the thread context, this is all about levels of trust. You appear
> > to trust programmers to consistently do the wrong thing. I however,
> > like the approach advocated by the estimable Mr. Naggum:
> > 
> >     ... it's just that in C++ and the like, you don't trust _anybody_,
> >     and in CLOS you basically trust everybody.  the practical result
> >     is that thieves and bums use C++ and nice people use CLOS.
> 
> I've sworn off arguing with Erik Naggum, even by proxy.  

A fully understandable sentiment...

> point out that 1) trusting people not to intentionally break abstraction 
> barriers unless they have a damn good reason is very different from 
> trusting people never to make a mistake and write code that happens to 
> have an OoE dependency, 

Not really. In fact, the case is that I only trust people to break
abstraction barriers intentionally, it's the unintentional violations
that are the problems. I believe that fixed OoE makes unintentional
abstraction boundary violations easier to commit.

> 2) I would think that an environment without 
> security mechanism would tend to *attract* thieves and bums rather than 
> repel them.

This has not been my experience. Apparently I am not alone in that
experience. Perhaps you have worked with many thieves and bums?

david rush
-- 
You do not truly know someone until you fight them
	-- Seraph, _The Matrix: Reloaded_
0
kumoyuki (163)
10/15/2004 7:03:39 PM
Matthias Blume <find@my.address.elsewhere> writes:

> Joe Marshall <jrm@ccs.neu.edu> writes:

> > Remind me again what specifying the order of arguments solved? 

> Here it is again:
> 
>    1.  It eliminates non-determinism from the language, making its
>        semantics simpler.

Really?  Determinism does not necessarily imply simplicity.  I would
claim that the statement "These things must all be done, in this
specific order, before this next thing happens" is less simple than
saying "These things must all be done before this next thing happens."

>    2.  As a result, tests become repeatable across platforms and
>        implementations, which in turn adds relevance to the results of
>        testing.

So, basically, every behavior that is currently left unspecified in
Scheme should become exactly specified?  After all, every unspecified
behavior leaves wiggle room for implementors to produce implementations
where things behave differently from other implementations.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/16/2004 6:28:31 AM
Ron Garret <rNOSPAMon@flownet.com> writes:

> The arguments for unspecified OoE apply only in an ideal world where 
> programmers have perfect knowledge and never make mistakes.

It seems just as much to me that the arguments for specified order of
evaluation are based on a notion that the more that is specified in a
language, the fewer opportunities will exist for expressing mistakes.
Perhaps we can create NewScheme, where bugthink is doubleplusungood?

> In the real world programmers rarely have complete knowledge, and
> rarely have the time necessary to fully explore all ramifications of
> their design decisions.

And I would go beyond that to say that programmers should assume their
knowledge is imperfect and use practices that detect or at least defend
against their inevitable mistakes.

> In the real world, programmers write (f (g) (h)) not because 
> they really have confidence that g and h are order independent, but 
> because it's quicker to type than (let* ((g (g)) (h (h))) (f g h)), and 
> they have a deadline to meet.  In the real world, the processes that are 
> used to write real code resemble a random walk much more than a 
> mathematically principled methodology, and they rely on the reliable 
> reproducibility of the behavior of software from one run to the next, or 
> from one compilation session to the next.  It's not ideal, but that's 
> the way it is.

If a programmer is in an environment where he is really not allowed to
know things like (h) happening before (g) will cause a problem, or that
in (f (g) (h)) there is no guarantee that (g) happens before (h), then
is there really any hope that language design changes will keep such
lack of knowledge from creating bugs?

Perfect knowledge may not be possible, but I don't think it's
unreasonable for a programmer to be expected to know what behaviors are
or are not guaranteed by the programming languge he uses, and to use
methods that accurately specify the behavior he intends.  If programmers
are under such pressure that they code based merely on what is fastest
to type, without the opportunity to understand what their code actually
means or does, it will not matter how carefully specified or
deterministic their programming language is, because under those
circumstances it is clearly not language features that cause their bugs.

In essence, you say ambiguity causes bugs, so if we reduce ambiguity, we
reduce the possibility of bugs.  But bugs are expressions of wrong
behavior -- and that wrongness may come from things like wrong
specifications, bad programming, failure to anticipate consequences, or
exposure to circumstances outside the original expectations.  Ambiguity
is not the same as wrongness.  A program can be precisely wrong or
ambiguously right, just as it can be ambiguously wrong or precisely
right.

The choice to leave evaluation order of function arguments unspecified
in Scheme was intended to allow the freedom to evaluate function
arguments in parallel and not just in sequence, and that freedom has
also been used to allow compilers to produce better code than they
otherwise might, or interpreters to work more efficiently than they
otherwise might.  If computing hardware keeps going the way it seems to
be going, where computing power is increased by parallelism and not just
increasing the speed of single processors, that lack of specification
may allow for more efficient use of parallelism than would otherwise be
possible if sequential ordering was required.  The ambiguity that you
decry for its "nondeterminism" also gives you the efficiency you want
for the kinds of critical applications you claim to be doing.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/16/2004 8:31:10 AM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:

> Matthias Blume <find@my.address.elsewhere> writes:
> 
> > Joe Marshall <jrm@ccs.neu.edu> writes:
> 
> > > Remind me again what specifying the order of arguments solved? 
> 
> > Here it is again:
> > 
> >    1.  It eliminates non-determinism from the language, making its
> >        semantics simpler.
> 
> Really?  Determinism does not necessarily imply simplicity.  I would
> claim that the statement "These things must all be done, in this
> specific order, before this next thing happens" is less simple than
> saying "These things must all be done before this next thing happens."

Just look at the way it is currently "specified", keeping in mind that
the specificiation is actually wrong because the trouble it would take
to get it right was not deemed worthwhile.

Specifying a particular order of evaluation is considerably simpler
than leaving it open.  For one, if everything is deterministic, you
don't have to account for the possibility of multiple different
outcomes.

> >    2.  As a result, tests become repeatable across platforms and
> >        implementations, which in turn adds relevance to the results of
> >        testing.
> 
> So, basically, every behavior that is currently left unspecified in
> Scheme should become exactly specified?

Ideally, yes.
0
find19 (1244)
10/16/2004 1:03:51 PM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:

> And I would go beyond that to say that programmers should assume their
> knowledge is imperfect and use practices that detect or at least defend
> against their inevitable mistakes.

How do you defend against the possibility of problems related to
unspecified order of evaluation?  Answer: by avoiding it.  So I
program defensively by writing (let* ((a A) (b B) ...) (f a b ...))
instead of (f A B ...).  If this is what you advocate, why does it
matter to you that (f A B ...) as a language construct has specific
properties?  (After all, you are not using it.)  If, OTOH, that is not
what you are suggest, then how do you think you would defend against
"inevitable mistakes" here?

> The choice to leave evaluation order of function arguments unspecified
> in Scheme was intended to allow the freedom to evaluate function
> arguments in parallel and not just in sequence,

No, it was not.  Read the spec!  It /specifically/ forbids
(inherently) parallel execution by requiring evaluation to be
consistent with some sequential order.

Matthias
0
find19 (1244)
10/16/2004 1:16:37 PM
In article <87brf3xdwx.fsf@localhost.efn.org>,
 Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:

> Ron Garret <rNOSPAMon@flownet.com> writes:
> 
> > The arguments for unspecified OoE apply only in an ideal world where 
> > programmers have perfect knowledge and never make mistakes.
> 
> It seems just as much to me that the arguments for specified order of
> evaluation are based on a notion that the more that is specified in a
> language, the fewer opportunities will exist for expressing mistakes.

Yes.

> Perhaps we can create NewScheme, where bugthink is doubleplusungood?

Huh?  (I understand the reference, but not the point you're trying to 
make.)

> > In the real world programmers rarely have complete knowledge, and
> > rarely have the time necessary to fully explore all ramifications of
> > their design decisions.
> 
> And I would go beyond that to say that programmers should assume their
> knowledge is imperfect and use practices that detect or at least defend
> against their inevitable mistakes.

Should, yes.  Do, no.

> If a programmer is in an environment where he is really not allowed to
> know things like (h) happening before (g) will cause a problem, or that
> in (f (g) (h)) there is no guarantee that (g) happens before (h), then
> is there really any hope that language design changes will keep such
> lack of knowledge from creating bugs?

Yes.  (BTW, it's not that they are not "allowed" to know, it's simply 
that for one reason or another they do not know.)

> Ambiguity is not the same as wrongness.

I never said it was.  It just increases the probability of wrongness.

> The choice to leave evaluation order of function arguments unspecified
> in Scheme was intended to allow the freedom to evaluate function
> arguments in parallel and not just in sequence

First, that's not true.  Second, nothing prevents an implementation from 
doing things in parallel if the results are the same as they would have 
been if they had been done in sequence (e.g. in the side-effect-free 
case).

> and that freedom has
> also been used to allow compilers to produce better code than they
> otherwise might, or interpreters to work more efficiently than they
> otherwise might.

The actual benefit of this in realistic situations is far from clear.

> The ambiguity that you
> decry for its "nondeterminism" also gives you the efficiency you want
> for the kinds of critical applications you claim to be doing.

That safety should win over efficiency is a no brainer as far as I'm 
concerned.  (I'm actually a bit surprised that I have to argue this in a 
newsgroup devoted to a dialect of Lisp.)

rg
0
rNOSPAMon (1927)
10/16/2004 2:07:03 PM
Ron Garret <rNOSPAMon@flownet.com> writes:

> In article <87brf3xdwx.fsf@localhost.efn.org>,
>  Steve VanDevender <stevev@hexadecimal.uoregon.edu> wrote:
> > If a programmer is in an environment where he is really not allowed to
> > know things like (h) happening before (g) will cause a problem, or that
> > in (f (g) (h)) there is no guarantee that (g) happens before (h), then
> > is there really any hope that language design changes will keep such
> > lack of knowledge from creating bugs?

> Yes.  (BTW, it's not that they are not "allowed" to know, it's simply 
> that for one reason or another they do not know.)

I maintain that if programmers, for whatever reason, do not know things
like those while in the process of writing software, then it is not the
fault of their programming language that they cannot write reliable
software.  You are talking about programming in a chronically
dysfunctional environment, and blaming tools for faults that really come
from lack of knowledge, design and communication.

> > Ambiguity is not the same as wrongness.

> I never said it was.  It just increases the probability of wrongness.

I think I've figured out one of the fundamental differences in mindset
here.

I am actually no longer an applications programmer.  I'm a system
administrator.  I still do programming, and I work with lots of other
people's software, but the environment I work in has had an effect on
the approach I take to programming.

I work in an environment where, more often than not, sequential behavior
cannot be safely assumed, and must be explicitly enforced when desired.
Instructions may execute in sequence within a single process, but the
overall rate of execution may vary greatly.  Multiple instances of the
same process may take different amounts of time to run and finish in an
order different than they were started.  Network data emitted
sequentially from a sender may arrive out of order (and sometimes not at
all) at the receiver.

Not only have I learned not to depend on my environment to give me
perfectly predictable behavior, but I've learned to program in ways that
make non-determinism a non-issue.  Why don't I care about the evaluation
order of function arguments in Scheme?  Because I'm not used to
depending on any order beyond that which I explicitly create or which my
language explicitly guarantees for me.  Because I have learned that
hidden side effects cause problems for me and the other programmers who
might use my code, and how to avoid using side effects unnecessarily.

I've also had to use a great many different computer architectures, and
port code between them frequently.  Many of the ambiguities in
specification for languages like C, C++, and Scheme are what have
allowed them to be implemented on so many different architectures and
live through generations of computing change.  If C had made the exact
specification that a char must be 8 bits, short and int must be 16 bits,
and long must be 32 bits, this certainly might have made software much
more easily portable and reliable.  I know I have suffered all the pains
of moving code between 16- and 32-bit architectures, and 32- and 64-bit
architectures.  But C works on 64-bit architectures specifically because
the only guarantee it provides here is that sizeof(char) <=
sizeof(short) <= sizeof(int) <= sizeof(long).  The process of learning
how to make portable software that has fewer and more explicit
dependencies on its environment can be painful, but the techniques you
learn in the process also lead to better software.

When people claim that this certain lack of specification in Scheme
leads to bugs, my answer is, isn't it better that programmers learn to
code in ways that work reliably even when some underlying behaviors are
not dependable?  The programmer who has learned not to depend on
specific evaluation order is a programmer who has learned to think more
carefully about the underlying behavior of his program; not only will
his code be more portable, it will be more reliable because it was
explicitly designed to be, instead of just reliable by accident.

In the specific case we've been arguing about, one side says that the
ambiguity in R5RS regarding order of evaluation of arguments in function
application leads to non-deterministic behavior, which leads to bugs.
But determinism is only repeatability, not reliability.  Behavior that
is non-deterministic but consistently within specified bounds is
reliable.  And safety does not come just from repeatability, but from
robustness in the face of unpredictable behavior.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/17/2004 1:06:16 AM
Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:

> I work in an environment where, more often than not, sequential behavior
> cannot be safely assumed, and must be explicitly enforced when desired.
> Instructions may execute in sequence within a single process, but the
> overall rate of execution may vary greatly.  Multiple instances of the
> same process may take different amounts of time to run and finish in an
> order different than they were started.  Network data emitted
> sequentially from a sender may arrive out of order (and sometimes not at
> all) at the receiver.

Yes, programming parallel or concurrent systems is *hard* because
dealing with non-determinism is *hard*.  And that's precisely why it
is a bad idea to gratuituously add more non-determinism to one's
tools.  The suggestion that added (unnecessary) non-determinism
doesn't hurt is as silly as the suggestion that I might as well walk
from home to downtown given that I have to walk to the train station
anyway.

Matthias
0
find19 (1244)
10/17/2004 1:37:46 AM
Matthias Blume wrote:
>>arguments in parallel and not just in sequence,
> 
> 
> No, it was not.  Read the spec!  It /specifically/ forbids
> (inherently) parallel execution by requiring evaluation to be
> consistent with some sequential order.
> 

I can't just let this one go by.  Requiring evaluation to be consistent 
with some sequential order does *not* prevent parallel execution.  It 
just requires that the results of the parallel execution be equivalent 
to some sequential one.

This is essentially a more precise statement of "though shalt not have 
side effects and expect sanity".  See also similar statements used in 
database theory and the C in ACID.

	Scott
0
scgmille (240)
10/17/2004 5:26:45 AM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> >>arguments in parallel and not just in sequence,
> > No, it was not.  Read the spec!  It /specifically/ forbids
> > (inherently) parallel execution by requiring evaluation to be
> > consistent with some sequential order.
> > 
> 
> I can't just let this one go by.  Requiring evaluation to be
> consistent with some sequential order does *not* prevent parallel
> execution.  It just requires that the results of the parallel
> execution be equivalent to some sequential one.

True, but largely irrelevant.  It's a *huge* restriction if you want
to do parallel execution!  Show me one realistic example where all of
the following is true:

    1. arguments are executed in parallel
    2. the result is guaranteed to be equivalent to some sequential order
       (Scheme report requirements)
    3. the result is /not/ guaranteed to be equivalent to left-to-right
       order

All I want is that the sequential order which evaluation has to be
consistent with be fixed.

Matthias
0
find19 (1244)
10/17/2004 5:44:59 AM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Matthias Blume wrote:
>>
>>>>arguments in parallel and not just in sequence,
>>>
>>>No, it was not.  Read the spec!  It /specifically/ forbids
>>>(inherently) parallel execution by requiring evaluation to be
>>>consistent with some sequential order.
>>>
>>
>>I can't just let this one go by.  Requiring evaluation to be
>>consistent with some sequential order does *not* prevent parallel
>>execution.  It just requires that the results of the parallel
>>execution be equivalent to some sequential one.
> 
> 
> True, but largely irrelevant.  It's a *huge* restriction if you want
> to do parallel execution!  Show me one realistic example where all of
> the following is true:

First of all.  In your previous post, your exact words were 
"specifically forbids".  So my response is completely relevant, since it 
absolutely refutes your assertion.

> 
>     1. arguments are executed in parallel
>     2. the result is guaranteed to be equivalent to some sequential order
>        (Scheme report requirements)

Given these first two requirements, the answer is all purely functional 
programs.  Most programs I write in Scheme are this way.  But then you 
say...

>     3. the result is /not/ guaranteed to be equivalent to left-to-right
>        order

Your argumentative style amuses me.  In defense of your position, you 
change the scope of the argument.  In the current Scheme status-quo, 
point 3 is irrelevant since the standard doesn't require it to be 
equivalent to a left to right order.  But if you twist the ground rules 
to include it, perhaps your statement about the near impossibility of 
parallel execution might be true.

Alas it is not.  Lets say the system is evaluating (f <a> <b> <c>), and 
can determine that only <c> involves side effects.  This is reasonable 
for example in a whole-program compiler like Stalin.  It is then free to 
evaluate <c> first, followed by <a> and <b> in parallel.  This would be 
equivalent to some sequential order of evaluations, namely <c>, <b>, 
<a>, or <c>, <a>, <b>.

Similarly, even if it knows that all three involve side effects, but 
that the side effects don't interfere with the execution trees of each 
other, than it can execute all three in parallel, and the results would 
be equivalent to any sequential order of execution.

If the compiler is correct in its analysis, then it doesn't even 
increase the complexity of human analysis, since the human can correctly 
the equivalent sequential OoE, including the left to right one, and 
analyze away.

	Scott
0
scgmille (240)
10/17/2004 3:27:44 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> >>Matthias Blume wrote:
> >>
> >>>>arguments in parallel and not just in sequence,
> >>>
> >>>No, it was not.  Read the spec!  It /specifically/ forbids
> >>>(inherently) parallel execution by requiring evaluation to be
> >>>consistent with some sequential order.
> >>>
> >>
> >>I can't just let this one go by.  Requiring evaluation to be
> >>consistent with some sequential order does *not* prevent parallel
> >>execution.  It just requires that the results of the parallel
> >>execution be equivalent to some sequential one.
> > True, but largely irrelevant.  It's a *huge* restriction if you want
> > to do parallel execution!  Show me one realistic example where all of
> > the following is true:
> 
> First of all.  In your previous post, your exact words were
> "specifically forbids".  So my response is completely relevant, since
> it absolutely refutes your assertion.

Ok, if you want to mince words, you are right.

What I meant, of course, was that it forbids executions that are
/inherently/ parallel.

> >     1. arguments are executed in parallel
> >     2. the result is guaranteed to be equivalent to some sequential order
> >        (Scheme report requirements)
> 
> Given these first two requirements, the answer is all purely
> functional programs.  Most programs I write in Scheme are this way.
> But then you say...
> 
> >     3. the result is /not/ guaranteed to be equivalent to left-to-right
> >        order
> 
> Your argumentative style amuses me.

Glad you are enjoying it.

>  In defense of your position, you
> change the scope of the argument.

No, absolutely not.  Maybe you have not read the whole argument, given
that you come in rather lately, though.

>  In the current Scheme status-quo,
> point 3 is irrelevant since the standard doesn't require it to be
> equivalent to a left to right order.

But we are discussing whether point 3) might be a better language
design (or, at least, whether it would not be any worse that the
current one).  The "can be executed in parallel" argument was brought
forward to defend the position that unspecified order is good.

> But if you twist the ground rules to include it, perhaps your
> statement about the near impossibility of parallel execution might
> be true.

That was not at all what I was getting at.

> Alas it is not.  Lets say the system is evaluating (f <a> <b> <c>),
> and can determine that only <c> involves side effects.  This is
> reasonable for example in a whole-program compiler like Stalin.  It is
> then free to evaluate <c> first, followed by <a> and <b> in parallel.
> This would be equivalent to some sequential order of evaluations,
> namely <c>, <b>, <a>, or <c>, <a>, <b>.

.... or <a> <b> <c>.

> Similarly, even if it knows that all three involve side effects, but
> that the side effects don't interfere with the execution trees of each
> other, than it can execute all three in parallel, and the results
> would be equivalent to any sequential order of execution.

.... including l2r.

> If the compiler is correct in its analysis, then it doesn't even
> increase the complexity of human analysis, since the human can
> correctly the equivalent sequential OoE, including the left to right
> one, and analyze away.

In other words, if the compiler can do it for /some/ sequential order,
it can do it for l2r.

And that was exactly my point.

Cheers,
Matthias
0
find19 (1244)
10/17/2004 3:55:28 PM
Matthias Blume <find@my.address.elsewhere> writes:

> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > First of all.  In your previous post, your exact words were
> > "specifically forbids".  So my response is completely relevant, since
> > it absolutely refutes your assertion.
> 
> Ok, if you want to mince words, you are right.
> 
> What I meant, of course, was that it forbids executions that are
> /inherently/ parallel.

Sorry for following up to myself.

But I have to take this back.  You are wrong.  I wrote "inherently"
even the first time around.

Matthias
0
find19 (1244)
10/17/2004 4:17:33 PM
Matthias Blume wrote:

> 
> In other words, if the compiler can do it for /some/ sequential order,
> it can do it for l2r.
> 
> And that was exactly my point.

Hmmm.  There are definitely situations where L2R won't be the
fastest way to do it.  Given a 1-processor machine, there is
no advantage at all in parallel execution in separate threads.
Given a >1 processor machine, it's fairly easy to come up with
a scenario of dependencies where the additional constraint of
L2R will cause things to be delayed that, allowed to choose
another ordering, won't be delayed.

For example, if 3 or more CPU's are available to the process
and you have dependencies a->c, b->c, c->d, then l2r can never
use more than 2 of the CPU's as it has to evaluate [ab, c, d].
But any-ordering can evaluate [abd, c], using 3 CPU's and less
linear time.

On the whole, I think I prefer specified OofE simply so that
testing is more reliable.  The average machine is still a uni-
processor, so this kind of implicit parallelization normally
doesn't give this kind of advantage.  Although picking OofE
can still save register spills and pipeline stalls, speeding
up execution even in a uniprocessor, I think having a reliable
OofE so that runs have the same effect as tests is worth it.

If we wanted a language where OofE doesn't matter, we should
not have made a language with mutation operators.

				Bear


0
bear (1219)
10/17/2004 7:20:44 PM
Ray Dillinger wrote:
> Matthias Blume wrote:
> 
>>
>> In other words, if the compiler can do it for /some/ sequential order,
>> it can do it for l2r.
>>
>> And that was exactly my point.
> 
> 
> Hmmm.  There are definitely situations where L2R won't be the
> fastest way to do it.  Given a 1-processor machine, there is
> no advantage at all in parallel execution in separate threads.
> Given a >1 processor machine, it's fairly easy to come up with
> a scenario of dependencies where the additional constraint of
> L2R will cause things to be delayed that, allowed to choose
> another ordering, won't be delayed.
 >
> On the whole, I think I prefer specified OofE simply so that
> testing is more reliable.  The average machine is still a uni-
> processor, so this kind of implicit parallelization normally
> doesn't give this kind of advantage.  Although picking OofE
> can still save register spills and pipeline stalls, speeding
> up execution even in a uniprocessor, I think having a reliable
> OofE so that runs have the same effect as tests is worth it.

The average machine will very quickly be multiprocessor.  All CPU 
vendors are hitting a uniprocessor wall (due primarily to heat and 
cost), and within 2 years greater than 50% of all new CPUs will be at 
least dual core.

> If we wanted a language where OofE doesn't matter, we should
> not have made a language with mutation operators.

I disagree.  Scheme provides explicit ordering constructs to neatly deal 
with the exceptional case of mutation.
	
	Scott
0
scgmille (240)
10/17/2004 8:13:15 PM
Matthias Blume <find@my.address.elsewhere> writes:
> Steve VanDevender <stevev@hexadecimal.uoregon.edu> writes:
> > So, basically, every behavior that is currently left unspecified in
> > Scheme should become exactly specified?
> 
> Ideally, yes.

I can sympathize with that PoV, but there is an alternative one which
I think is more in line with the notion of Scheme as a free
society. RnRS has always been a "report" more than a standard. I take
this to mean that it is supposed to be reflective of the
implementation practice in the community rather than prescriptive w/rt
required functionality.

And yes, this can be considered a misfeature, but it also makes a nice
kind of sense, too.

david rush
-- 
If you're stuck at the level of wanting to point at a picture and 
click, you've got to understand that you're basically at the same 
level as a preverbal child...
	-- bear (on comp.lang.scheme)
0
kumoyuki (163)
10/17/2004 9:52:22 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> I disagree.  Scheme provides explicit ordering constructs to neatly
> deal with the exceptional case of mutation.

Unfortunately, side-effects are /not at all/ the exception is Scheme.
0
find19 (1244)
10/17/2004 10:07:52 PM
Matthias Blume <find@my.address.elsewhere> writes:

> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> > I disagree.  Scheme provides explicit ordering constructs to neatly
> > deal with the exceptional case of mutation.
> 
> Unfortunately, side-effects are /not at all/ the exception is Scheme.

And here's the other schism, between Scheme as a functional language and
Scheme as an imperative language.

I tend to think of Scheme as a functional language with some optional
imperative capabilities like mutation (which I obviously don't
completely avoid).  In a purely functional language, order of evaluation
of function arguments would be a total non-issue; in the presence of
mutation, it only becomes an issue if mutation is used as a sort of
covert communication channel between different functions or expressions.
When I use mutation, I tend to use it in a "functional" way, such as for
temporary private state.  Many of the other things I might once have
used mutation for in other poorer languages, such as passing
"out-of-band" information between functions, are usually better
expressed in Scheme in other ways.

-- 
Steve VanDevender  "I ride the big iron"  http://hexadecimal.uoregon.edu/
stevev@hexadecimal.uoregon.edu  PGP keyprint 4AD7AF61F0B9DE87 522902969C0A7EE8
Little things break, circuitry burns / Time flies while my little world turns
Every day comes, every day goes / 100 years and nobody shows -- Happy Rhodes
0
stevev (36)
10/17/2004 11:43:16 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>I disagree.  Scheme provides explicit ordering constructs to neatly
>>deal with the exceptional case of mutation.
> 
> 
> Unfortunately, side-effects are /not at all/ the exception is Scheme.

Thats your opinion.

In my experience, little of my code apart from I/O utilizes 
side-effects.  For example, in the 30k lines of Scheme code in SISC, 
only 768 lines contain a datastructure side effect.  There are 
approximately 3200 definitions.  From a spot check, the the average 
function contains three such setters.  That accounts for about 8% of the 
functions in SISC.

This is all very unscientific, but no more so than your opinion.

	Scott
0
scgmille (240)
10/18/2004 2:02:04 AM
Steve VanDevender wrote:
> Matthias Blume <find@my.address.elsewhere> writes:
> 
> 
>>"Scott G. Miller" <scgmille@freenetproject.org> writes:
>>
>>
>>>I disagree.  Scheme provides explicit ordering constructs to neatly
>>>deal with the exceptional case of mutation.
>>
>>Unfortunately, side-effects are /not at all/ the exception is Scheme.
> 
> 
> And here's the other schism, between Scheme as a functional language and
> Scheme as an imperative language.

> When I use mutation, I tend to use it in a "functional" way, such as for
> temporary private state.  Many of the other things I might once have
> used mutation for in other poorer languages, such as passing
> "out-of-band" information between functions, are usually better
> expressed in Scheme in other ways.

An excellent point.  Virtually all of the procedures I looked at for my 
past post used setters internally as you describe.  It would be trivial 
for a compiler to notice this as well.

	Scott
0
scgmille (240)
10/18/2004 2:03:52 AM
In article <xMCdnT1u6IKrue7cRVn-tA@giganews.com>,
 "Scott G. Miller" <scgmille@freenetproject.org> wrote:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> > 
> >>I disagree.  Scheme provides explicit ordering constructs to neatly
> >>deal with the exceptional case of mutation.
> > 
> > 
> > Unfortunately, side-effects are /not at all/ the exception is Scheme.
> 
> Thats your opinion.

No, it's what r5rs says:

"A wide variety of programming paradigms, including imperative, 
functional, and message passing styles, find convenient expression in 
Scheme."

Note that imperative is even listed first.

rg
0
rNOSPAMon (1927)
10/18/2004 2:53:08 AM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> >>I disagree.  Scheme provides explicit ordering constructs to neatly
> >>deal with the exceptional case of mutation.
> > Unfortunately, side-effects are /not at all/ the exception is
> > Scheme.
> 
> Thats your opinion.

No, it is a fact.

> In my experience, little of my code apart from I/O utilizes
> side-effects.

I did not talk about utilization.  I talked about the effects that are
there.

>  For example, in the 30k lines of Scheme code in SISC,
> only 768 lines contain a datastructure side effect.  There are
> approximately 3200 definitions.  From a spot check, the the average
> function contains three such setters.  That accounts for about 8% of
> the functions in SISC.

Trust me, I know all that.  And it does not contradict what I said
since I was not talking about how often programmers actually /want/ to
use effects.  In Scheme they end up using effects anyway all the time,
often involuntarily, because there is no choice.  (My own Lisp- and
Scheme code, including the code used in my various Lisp- and Scheme
implementations, also rarely utilized side effects.)

Even when effects are not utilized, they are still there.  For the
compiler to know whether or not they are there for a purpose or just
because there wasn't any way around them (because the language did not
have adequate effect-free constructs) is very hard.  For that reason I
consider it poor language design when effects are be part of the
semantics of nearly every single language construct.  Incidentally,
some of the arguments here in favor of leaving the order of evaluation
unspecified in certain cases seem to be designed to offset some of the
ill effects (no pun intended) of having too many effects in the
language.

So, that last paragraph consisted mostly of opinions, and I do not
claim it to be scientific.  Otherwise, please, stop contradicting me
on things which are simple facts just because you did not read and
think about what I actually wrote carefully enough.

Matthias
0
find19 (1244)
10/18/2004 5:51:26 AM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Matthias Blume wrote:
>>
>>>"Scott G. Miller" <scgmille@freenetproject.org> writes:
>>>
>>>
>>>>I disagree.  Scheme provides explicit ordering constructs to neatly
>>>>deal with the exceptional case of mutation.
>>>
>>>Unfortunately, side-effects are /not at all/ the exception is
>>>Scheme.
>>
>>Thats your opinion.
> 
> 
> No, it is a fact.
> 
> 
>>In my experience, little of my code apart from I/O utilizes
>>side-effects.
> 
> 
> I did not talk about utilization.  I talked about the effects that are
> there.
> 
> 
>> For example, in the 30k lines of Scheme code in SISC,
>>only 768 lines contain a datastructure side effect.  There are
>>approximately 3200 definitions.  From a spot check, the the average
>>function contains three such setters.  That accounts for about 8% of
>>the functions in SISC.
> 
> 
> Trust me, I know all that.  And it does not contradict what I said
> since I was not talking about how often programmers actually /want/ to
> use effects.  In Scheme they end up using effects anyway all the time,
> often involuntarily, because there is no choice.

Can you provide some evidence please?  This sounds pretty dubious to me.

	Scott
0
scgmille (240)
10/18/2004 1:06:18 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Can you provide some evidence please?  This sounds pretty dubious to me.

As a Scheme implementer, you should know.

Here is a short list of Scheme constructs which according to Scheme
semantics have effects:

  procedure creation (LAMBDA)
  CONS
  CAR
  CDR
  LET
  LET*
  LETREC
  procedure entry when there is at least one formal parameter
  variable reference
  VECTOR
  VECTOR-REF
  LIST?

Looks like a pretty comprehensive collection to me.  (Notice that this
list does not even contain the usual suspects such as SET!, SET-CAR!,
or CALL/CC.)

Before you jump in: Yes, I know that in some cases the compiler can
prove that some of these imperative constructs can be replaced with
their pure counterparts.  In some cases this is even relatively easy.
(Example: Binding and reference to local variables that do not have
SET! in scope.)

But the general point stands: There are way too many constructs that
have effects. The claim that most programmers do not take "advantage"
of these effects does not make it any better; in fact, it only
makes it worse.

Matthias
0
find19 (1244)
10/18/2004 2:33:49 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Can you provide some evidence please?  This sounds pretty dubious to me.
> 
> 
> As a Scheme implementer, you should know.
> 
> Here is a short list of Scheme constructs which according to Scheme
> semantics have effects:
> 
>   procedure creation (LAMBDA)
>   CONS
>   CAR
>   CDR
>   LET
>   LET*
>   LETREC
>   procedure entry when there is at least one formal parameter
>   variable reference
>   VECTOR
>   VECTOR-REF
>   LIST?
> 

Yep.  Pretty dubious.  Allocation is not an 'effect' that is relevant to 
this discussion.  Side effects must visible from separate call trees at 
a call site to affect the results of computation.

> Looks like a pretty comprehensive collection to me.  (Notice that this
> list does not even contain the usual suspects such as SET!, SET-CAR!,
> or CALL/CC.)
Thats funny, since none of the former procedures are relevant to an OoE 
discussion, but all of the latter do.

> 
> Before you jump in: Yes, I know that in some cases the compiler can
> prove that some of these imperative constructs can be replaced with
> their pure counterparts.  In some cases this is even relatively easy.
> (Example: Binding and reference to local variables that do not have
> SET! in scope.)
"cons" is an imperative construct?

	Scott
0
scgmille (240)
10/18/2004 5:53:31 PM
Scott G. Miller wrote:
> Matthias Blume wrote:
> 
>> "Scott G. Miller" <scgmille@freenetproject.org> writes:
>>
>>
>>> Can you provide some evidence please?  This sounds pretty dubious to me.
>>
>>
>>
>> As a Scheme implementer, you should know.
>>
>> Here is a short list of Scheme constructs which according to Scheme
>> semantics have effects:
>>
>>   procedure creation (LAMBDA)
>>   CONS
>>   CAR
>>   CDR
>>   LET
>>   LET*
>>   LETREC
>>   procedure entry when there is at least one formal parameter
>>   variable reference
>>   VECTOR
>>   VECTOR-REF
>>   LIST?
>>
> 
> Yep.  Pretty dubious.  Allocation is not an 'effect' that is relevant to 
> this discussion.  Side effects must visible from separate call trees at 
> a call site to affect the results of computation.

Let me clarify.  Allocation is an effect, but only side-effects have any 
bearing on the question of order of evaluation.

	Scott
0
scgmille (240)
10/18/2004 5:56:40 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> >>Can you provide some evidence please?  This sounds pretty dubious to me.
> > As a Scheme implementer, you should know.
> > Here is a short list of Scheme constructs which according to Scheme
> > semantics have effects:
> >   procedure creation (LAMBDA)
> >   CONS
> >   CAR
> >   CDR
> >   LET
> >   LET*
> >   LETREC
> >   procedure entry when there is at least one formal parameter
> >   variable reference
> >   VECTOR
> >   VECTOR-REF
> >   LIST?
> > 
> 
> Yep.  Pretty dubious.  Allocation is not an 'effect' that is relevant
> to this discussion.

Of course it is relevant.

> Side effects must visible from separate call
> trees at a call site to affect the results of computation.

They are.

> "cons" is an imperative construct?

Of course. (The Scheme variety, that is.)  It allocates two fresh
cells (thus extending the store) and initializes them.  Cons cells
have identity.  Therefore, one can distinguish between the results of
(cons 'a 'b) and (cons 'a 'b).  If CONS were pure, the results would
be indistinguishable.

Matthias
0
find19 (1244)
10/18/2004 6:00:01 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Let me clarify.  Allocation is an effect, but only side-effects have
> any bearing on the question of order of evaluation.

False.  Think "call/cc".
0
find19 (1244)
10/18/2004 6:00:56 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Let me clarify.  Allocation is an effect, but only side-effects have
>>any bearing on the question of order of evaluation.
> 
> 
> False.  Think "call/cc".

I explicitly acknowledged call/cc as an exception in my last mail.

Now if you please, create a function call which uses cons in a way that 
produces a different result from two different evaluation orders.

	Scott
0
scgmille (240)
10/18/2004 6:02:17 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> >>Let me clarify.  Allocation is an effect, but only side-effects have
> >>any bearing on the question of order of evaluation.
> > False.  Think "call/cc".
> 
> I explicitly acknowledged call/cc as an exception in my last mail.

I must have missed that.  Did you mean the thing about only mutation
and call/cc being relevant to OoE issues?  Well, that's -- in some
sense -- right.  However, the mere presence of mutation and call/cc in
the language is what makes the other effects relevant.  Obviously,
allocating mutable store is an effect only because there is the
potential for mutation.  And creating objects with identity is an
effect only if there is some potential for observing object identity.
Object identity is relevant to OofE issues only if there is a way of
observing evaluation order.

So, yes, without SET!, without SET-CxR!, without CALL/CC, without EQ?,
and so on, none of the things in my list would be considered having
effects.  But since we are dealing with Scheme here, they do have effects.

> Now if you please, create a function call which uses cons in a way
> that produces a different result from two different evaluation orders.

I guess you want me to do this without also using SET! and friends or
CALL/CC.  Well, that's, indeed, not possible.  But if CONS didn't have
an effect, then /even in the presence of such constructs/ one should
not be able to detect whether

    (f (cons 'a 'b) (g))

gets evaluated l2r or r2l.

Now try

    (define (g)
       (call/cc (lambda (k) k)))

    (define (f x y)
       (if (pair? y)
           (eq? x y)
           (y x)))

With l2r you get #t, with r2l you get #f.  (Notice that the boolean
value here is the result of comparing the result of (cons 'a 'b) to
"itself".)

Matthias
0
find19 (1244)
10/18/2004 7:08:23 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Matthias Blume wrote:
>>
>>>"Scott G. Miller" <scgmille@freenetproject.org> writes:
>>>
>>>
>>>>Let me clarify.  Allocation is an effect, but only side-effects have
>>>>any bearing on the question of order of evaluation.
>>>
>>>False.  Think "call/cc".
>>
>>I explicitly acknowledged call/cc as an exception in my last mail.
> 
> 
> I must have missed that.  Did you mean the thing about only mutation
> and call/cc being relevant to OoE issues?  Well, that's -- in some
> sense -- right.  However, the mere presence of mutation and call/cc in
> the language is what makes the other effects relevant.  Obviously,
> allocating mutable store is an effect only because there is the
> potential for mutation.  And creating objects with identity is an
> effect only if there is some potential for observing object identity.
> Object identity is relevant to OofE issues only if there is a way of
> observing evaluation order.
> 
> So, yes, without SET!, without SET-CxR!, without CALL/CC, without EQ?,
> and so on, none of the things in my list would be considered having
> effects.  But since we are dealing with Scheme here, they do have effects.
> 
> 
>>Now if you please, create a function call which uses cons in a way
>>that produces a different result from two different evaluation orders.
> 
> 
> I guess you want me to do this without also using SET! and friends or
> CALL/CC.  Well, that's, indeed, not possible.  But if CONS didn't have
> an effect, then /even in the presence of such constructs/ one should
> not be able to detect whether
> 
>     (f (cons 'a 'b) (g))
> 
> gets evaluated l2r or r2l.
> 
So you agree that the procedures in your first list are irrelevant to an 
OoE discussion.  Excellent.



> Now try
> 
>     (define (g)
>        (call/cc (lambda (k) k)))
> 
>     (define (f x y)
>        (if (pair? y)
>            (eq? x y)
>            (y x)))
> 
> With l2r you get #t, with r2l you get #f.  (Notice that the boolean
> value here is the result of comparing the result of (cons 'a 'b) to
> "itself".)
> 
I'm well aware the call/cc is able to detect such distinctions.  But you 
implied that the majority of Scheme code was 'incompatible' with an 
unspecified order of evaluation because most of Scheme has effects. 
Thanks for agreeing that its really only a small number of procedures.



	Scott
0
scgmille (240)
10/18/2004 7:33:10 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> So you agree that the procedures in your first list are irrelevant to
> an OoE discussion.

No, I do not agree.  As long as the other list is there, the first
list is not irrelevant.
0
find19 (1244)
10/18/2004 7:37:35 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>So you agree that the procedures in your first list are irrelevant to
>>an OoE discussion.
> 
> 
> No, I do not agree.  As long as the other list is there, the first
> list is not irrelevant.

Its not enough that the second list exists.  It must also represent
the lion's share of Scheme programming.

	Scott
0
scgmille (240)
10/18/2004 8:59:24 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > 
> >>So you agree that the procedures in your first list are irrelevant to
> >>an OoE discussion.
> > No, I do not agree.  As long as the other list is there, the first
> > list is not irrelevant.
> 
> Its not enough that the second list exists.  It must also represent
> the lion's share of Scheme programming.

One instance can foul things up.  As a result, the mere presence of
these constructs in the language means that, e.g., the semantics of
CONS is not irrelevant to the OoE discussion because it makes the
order /potentially/ observable.  In short, this is /not/ a question of
degrees.
0
find19 (1244)
10/18/2004 9:24:45 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Matthias Blume wrote:
>>
>>>"Scott G. Miller" <scgmille@freenetproject.org> writes:
>>>
>>>
>>>>So you agree that the procedures in your first list are irrelevant to
>>>>an OoE discussion.
>>>
>>>No, I do not agree.  As long as the other list is there, the first
>>>list is not irrelevant.
>>
>>Its not enough that the second list exists.  It must also represent
>>the lion's share of Scheme programming.
> 
> 
> One instance can foul things up.  As a result, the mere presence of
> these constructs in the language means that, e.g., the semantics of
> CONS is not irrelevant to the OoE discussion because it makes the
> order /potentially/ observable.  In short, this is /not/ a question of
> degrees.

The entire question is a question of degrees.  Your position is that the 
order should be fixed, so that analysis is easier, and people can rely 
on it.  The analysis position has been adequately discussed.  The 
position that people want to rely on the order is only valid so long as 
people more often need to rely on an order (these people are using let* 
currently) than not.  Many have argued that this is not the case. 
Looking at all the Scheme code I've ever encountered, this seems 
patently obvious.


	Scott
0
scgmille (240)
10/19/2004 12:06:10 AM
Matthias Blume <find@my.address.elsewhere> writes:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> > Its not enough that the second list exists.  It must also represent
> > the lion's share of Scheme programming.
> 
> One instance can foul things up.  As a result, the mere presence of
> these constructs in the language means that, e.g., the semantics of
> CONS is not irrelevant to the OoE discussion because it makes the
> order /potentially/ observable.  In short, this is /not/ a question of
> degrees.

Well actually it is. The original argument was about *human* behavior
in creating bugs. Humans are astonishingly good at dealing with noisy
data that drives computers into NP-complete epileptic seizures. I
agree that all of the issues you raised are relevant for compilers,
but in practice, they cause problems for people in a *very* small
number of cases.

david rush
-- 
Communism is inequality, but not as property is. Property is
exploitation of the weak by the strong. Communism is exploitation of
the strong by the weak.
	-- What is Property? (Pierre-Joseph Proudhon)
0
kumoyuki (163)
10/19/2004 10:08:38 AM
David Rush <kumoyuki@gmail.com> writes:

> I agree that all of the issues you raised are relevant for
> compilers, but in practice, they cause problems for people in a
> *very* small number of cases.

Yes.  But people aren't the ones translating the program to fast,
low-level code.  Compilers are.  So ultimately the compiler has to
answer the question of whether or not certain reorderings are legal.
For this it is not a matter of degrees.

When the compiler sees CONS it has to assume that it is allocating
mutable store (or it would have to do a thorough-enough flow analysis
to convince itself otherwise).  To know that CONS may be reordered in
certain ways it must analyze the context and be sure that there is no
call to CALL/CC lurking, etc.  The human argument, at best, gives an
estimate on the probability of these things.  But to the compiler this
matters only if we give it permission to generate incorrect code with
a certain (hopefully low) probability.

Matthias

0
find19 (1244)
10/19/2004 1:15:17 PM
Matthias Blume wrote:
> David Rush <kumoyuki@gmail.com> writes:
> 
> 
>>I agree that all of the issues you raised are relevant for
>>compilers, but in practice, they cause problems for people in a
>>*very* small number of cases.
> 
> 
> Yes.  But people aren't the ones translating the program to fast,
> low-level code.  Compilers are.  So ultimately the compiler has to
> answer the question of whether or not certain reorderings are legal.
> For this it is not a matter of degrees.
> 
> When the compiler sees CONS it has to assume that it is allocating
> mutable store (or it would have to do a thorough-enough flow analysis
> to convince itself otherwise).  To know that CONS may be reordered in
> certain ways it must analyze the context and be sure that there is no
> call to CALL/CC lurking, etc.  The human argument, at best, gives an
> estimate on the probability of these things.  But to the compiler this
> matters only if we give it permission to generate incorrect code with
> a certain (hopefully low) probability.
> 
Thats only true if you fix the order of evaluation.  If you don't, then 
its perfectly fine for the compiler to reorder it however it sees fit, 
since the programmer's use of a side effect or call/cc is a bug.

So which is it really?  The humans or the compiler?  As an implementer, 
I'm much happier with the current state of affairs for both humans and 
machines.

	Scott

0
scgmille (240)
10/19/2004 2:50:51 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> Matthias Blume wrote:
> > David Rush <kumoyuki@gmail.com> writes:
> > 
> >>I agree that all of the issues you raised are relevant for
> >>compilers, but in practice, they cause problems for people in a
> >>*very* small number of cases.
> > Yes.  But people aren't the ones translating the program to fast,
> > low-level code.  Compilers are.  So ultimately the compiler has to
> > answer the question of whether or not certain reorderings are legal.
> > For this it is not a matter of degrees.
> > When the compiler sees CONS it has to assume that it is allocating
> > mutable store (or it would have to do a thorough-enough flow analysis
> > to convince itself otherwise).  To know that CONS may be reordered in
> > certain ways it must analyze the context and be sure that there is no
> > call to CALL/CC lurking, etc.  The human argument, at best, gives an
> > estimate on the probability of these things.  But to the compiler this
> > matters only if we give it permission to generate incorrect code with
> > a certain (hopefully low) probability.
> > 
> Thats only true if you fix the order of evaluation.  If you don't,
> then its perfectly fine for the compiler to reorder it however it sees
> fit, since the programmer's use of a side effect or call/cc is a bug.

No.  It is true generally.  Whether or not the compiler /knows/ it can
reorder without changing the meaning of the program does not depend on
fixing or unfixing the order.  Only whether it is entitled to /assume/
so.  (That is what I have been saying earlier: Unfixing the order
seems to be an attempt to overcome some of the difficulties caused by
Scheme being overly imperative.  At least that's what some of the
supporters of unfixed order seem to suggest.  Whether or not it is
historically accurate is a different question.)

Also, notice that if the compiler has an easier time reasoning about
order-independence, it can also reorder things like LET* -- which may
be there not to indicate ordering requirements but merely as a
consequence of other coding preferences that the programmer might
have.

> So which is it really?  The humans or the compiler? 

Both.

> As an implementer, I'm much happier with the current state of
> affairs for both humans and machines.

You are?  Ok, more power to you.

I never really liked unfixed order as a user of the language, and as
an implementer I came to realize that the current state of affairs
makes things virtually no simpler.  In fact, is a major pain in the
neck to try and take "advantage" of unfixed order.
(That's part of the reason why I became a user and an implementer of a
different language.)


Matthias
0
find19 (1244)
10/19/2004 3:19:28 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>Matthias Blume wrote:
>>
>>>David Rush <kumoyuki@gmail.com> writes:
>>>
>>>
>>>>I agree that all of the issues you raised are relevant for
>>>>compilers, but in practice, they cause problems for people in a
>>>>*very* small number of cases.
>>>
>>>Yes.  But people aren't the ones translating the program to fast,
>>>low-level code.  Compilers are.  So ultimately the compiler has to
>>>answer the question of whether or not certain reorderings are legal.
>>>For this it is not a matter of degrees.
>>>When the compiler sees CONS it has to assume that it is allocating
>>>mutable store (or it would have to do a thorough-enough flow analysis
>>>to convince itself otherwise).  To know that CONS may be reordered in
>>>certain ways it must analyze the context and be sure that there is no
>>>call to CALL/CC lurking, etc.  The human argument, at best, gives an
>>>estimate on the probability of these things.  But to the compiler this
>>>matters only if we give it permission to generate incorrect code with
>>>a certain (hopefully low) probability.
>>>
>>
>>Thats only true if you fix the order of evaluation.  If you don't,
>>then its perfectly fine for the compiler to reorder it however it sees
>>fit, since the programmer's use of a side effect or call/cc is a bug.
> 
> 
> No.  It is true generally.  Whether or not the compiler /knows/ it can
> reorder without changing the meaning of the program does not depend on
> fixing or unfixing the order.  Only whether it is entitled to /assume/
> so.  (That is what I have been saying earlier: Unfixing the order
> seems to be an attempt to overcome some of the difficulties caused by
> Scheme being overly imperative.  At least that's what some of the
> supporters of unfixed order seem to suggest.  Whether or not it is
> historically accurate is a different question.)

All compilers assume the program is correct, and that the programmer is 
capable of writing to specification.  If reordering expressions changes 
the meaning when the order is unspecified, then the program was buggy. 
Simple as that.

And I view the goal of an unspecified OoE as catering to functional 
program, not trying to overcome the difficulties of being overly 
imperative.  After all, a fixed OoE only affects imperative programming, 
and for the worse.


> Also, notice that if the compiler has an easier time reasoning about
> order-independence, it can also reorder things like LET* -- which may
> be there not to indicate ordering requirements but merely as a
> consequence of other coding preferences that the programmer might
> have.
> 
Sure.  Obviously the compiler is allowed to do more work if it wants to, 
but with an unspecified OoE is doesn't have to be near omniscient, it 
just has to trust that the programmer is mostly competent.

BTW, I'm all for adding a construct which fixes the order of evaluation 
of a procedure call without introducing new lexical scope.

> I never really liked unfixed order as a user of the language, and as
> an implementer I came to realize that the current state of affairs
> makes things virtually no simpler.  In fact, is a major pain in the
> neck to try and take "advantage" of unfixed order.
> (That's part of the reason why I became a user and an implementer of a
> different language.)

Really?  I find it incredibly convenient.  SISC takes advantage of 
unspecified order in a number of ways;  constant propogation, letrec 
lifting, its lazy continuation fixup, and a host of minor source 
equivalence transforms such as:

(begin a (f (begin b c) d) e) => (begin b (f c d) e)

Which can lead to further optimizations, like opening up the ability to 
inline, or further constant folding, or dead code elimination, etc, etc, 
etc.

	Scott
0
scgmille (240)
10/19/2004 5:06:40 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> All compilers assume the program is correct, and that the programmer
> is capable of writing to specification.  If reordering expressions
> changes the meaning when the order is unspecified, then the program
> was buggy. Simple as that.

If that would indeed be so, then RnRS didn't have to go to any length
defining the semantics of programs that depend on the order of
evaluation.  The fact that it does shows that such programs are not
automatically considered buggy, so it is not "simple as that".

> Really?  I find it incredibly convenient.  SISC takes advantage of
> unspecified order in a number of ways; constant propogation, letrec
> lifting, its lazy continuation fixup, and a host of minor source
> equivalence transforms such as:
> 
> (begin a (f (begin b c) d) e) => (begin b (f c d) e)

First of all, I assume you meant

    (begin a b (f c d) e)

Second, by Scheme rules this transformation is wrong in the general case.
(I am assuming that b, c, and d are non-trivial expression.)

Matthias
0
find19 (1244)
10/19/2004 8:47:58 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>All compilers assume the program is correct, and that the programmer
>>is capable of writing to specification.  If reordering expressions
>>changes the meaning when the order is unspecified, then the program
>>was buggy. Simple as that.
> 
> 
> If that would indeed be so, then RnRS didn't have to go to any length
> defining the semantics of programs that depend on the order of
> evaluation.  The fact that it does shows that such programs are not
> automatically considered buggy, so it is not "simple as that".
> 

Yes, they are buggy.  They have meaning, but the meaning doesn't match 
the programmers intention.  Most people consider that a bug.
>>Really?  I find it incredibly convenient.  SISC takes advantage of
>>unspecified order in a number of ways; constant propogation, letrec
>>lifting, its lazy continuation fixup, and a host of minor source
>>equivalence transforms such as:
>>
>>(begin a (f (begin b c) d) e) => (begin b (f c d) e)
> 
> 
> First of all, I assume you meant
> 
>     (begin a b (f c d) e)
> 
> Second, by Scheme rules this transformation is wrong in the general case.
> (I am assuming that b, c, and d are non-trivial expression.)

That may not have been the best example.  But please do explain why that 
is wrong in the general case.  Here's another one.  I've placed 
arbitrarily complicated expressions in <>:

(begin <v>
        (let ((a <w>)
              (b <x>)
              (c <y>))
           (f c a))
=>
(begin <v> <x> (f <y> <w>))

There are two things happening here.  First, the compiler recognizes 
that b is unreferenced in the body of the let, and pushes its expression 
up to the begin (since it may still have side-effects).  Second, it sees 
that a and b are referenced only once and can therefor fold them into 
the function call on f, even though the bindings are reversed.

If OoE were fixed, neither step would be possible without first proving 
that there were no interdependencies in the arguments.

The single reference may seem contrived, but this regularly happens as 
expressions are refactored in and out of let bodies, or through code 
generation in macros or other programs.


	Scott
0
scgmille (240)
10/19/2004 9:21:59 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> > If that would indeed be so, then RnRS didn't have to go to any
> > length
> > defining the semantics of programs that depend on the order of
> > evaluation.  The fact that it does shows that such programs are not
> > automatically considered buggy, so it is not "simple as that".
> > 
> 
> Yes, they are buggy.  They have meaning, but the meaning doesn't match
> the programmers intention.  Most people consider that a bug.

How do you know the programmer's intention?  And why does the Scheme
report try to define the (set of possible) meaning(s) of such programs
instead of simply declaring them illegal?  (C, at least, does the
latter, IIRC.)

> >>(begin a (f (begin b c) d) e) => (begin b (f c d) e)
> > First of all, I assume you meant
> >     (begin a b (f c d) e)
> > Second, by Scheme rules this transformation is wrong in the general
> > case.
> > (I am assuming that b, c, and d are non-trivial expression.)
> 
> That may not have been the best example.  But please do explain why
> that is wrong in the general case.

It is wrong because in the first example it is illegal for the
compiler to execute d between d and c.  In the second form this
restriction is lifted.

> Here's another one.  I've placed arbitrarily complicated expressions
> in <>:
> 
> (begin <v>
>         (let ((a <w>)
>               (b <x>)
>               (c <y>))
>            (f c a))
> =>
> (begin <v> <x> (f <y> <w>))

Again, in the general case this is wrong.  However, in many specific
cases it is right (and a compiler would know it to be right).  In
particular, if <y> or <w> have an effect that interferes with the
effect of fetching the value of f, then the reordering is illegal.  In
the first version of the code it is guaranteed that <y> and <w> get
executed before f is evaluated, in the second version this is no
longer the case.

Now you are batting 0-for-2 already.  Are you going to admit that
things aren't nearly as "convenient" as you claim them to be (and
certainly not "incredibly convenient")?

[By the way, I find this transformation particularly unconvincing since
compilers usually go the other way around by going to forms where all
intermediate results are named (e.g., A-NF or CPS).]

Matthias
0
find19 (1244)
10/19/2004 9:40:39 PM
Matthias Blume wrote:
> "Scott G. Miller" <scgmille@freenetproject.org> writes:
> 
> 
>>>If that would indeed be so, then RnRS didn't have to go to any
>>>length
>>>defining the semantics of programs that depend on the order of
>>>evaluation.  The fact that it does shows that such programs are not
>>>automatically considered buggy, so it is not "simple as that".
>>>
>>
>>Yes, they are buggy.  They have meaning, but the meaning doesn't match
>>the programmers intention.  Most people consider that a bug.
> 
> 
> How do you know the programmer's intention?  And why does the Scheme
> report try to define the (set of possible) meaning(s) of such programs
> instead of simply declaring them illegal?  (C, at least, does the
> latter, IIRC.)
> 
> 
>>>>(begin a (f (begin b c) d) e) => (begin b (f c d) e)
>>>
>>>First of all, I assume you meant
>>>    (begin a b (f c d) e)
>>>Second, by Scheme rules this transformation is wrong in the general
>>>case.
>>>(I am assuming that b, c, and d are non-trivial expression.)
>>
>>That may not have been the best example.  But please do explain why
>>that is wrong in the general case.
> 
> 
> It is wrong because in the first example it is illegal for the
> compiler to execute d between d and c.  In the second form this
> restriction is lifted.

It is equivalent for the compiler to execute b (you meant B right?) 
before the function if its order of evaluation was going to be (1, 2, 0)
anyway.  But I'll concede the point.


> 
> Now you are batting 0-for-2 already.  Are you going to admit that
> things aren't nearly as "convenient" as you claim them to be (and
> certainly not "incredibly convenient")?
> 
No, I don't think so.  I'm just posing hypotheticals.  Thanks for 
clearing them up.  There are plenty of legal reorderings that I haven't 
tried to show since they're perfectly trivial.  In particular, move the 
binding for f in the last example and its legal.

But the real question is, why impose a burden on the compiler to prove 
nondependence in a language where a sizable majority of programs have none?

At any rate, its becoming clear that arguing with you is 
non-terminating.  The burden of proof is yours if you want to change the 
status quo, and your argument is for increased compiler complexity, 
roughly equal analyzability, decreased program clarity, decreased 
expressiveness, and decreased tool utility.

If you want all that, you're free to use other languages (or do you 
already?).  I'd prefer to keep Scheme flexible.

	Scott
0
scgmille (240)
10/19/2004 10:44:25 PM
"Scott G. Miller" <scgmille@freenetproject.org> writes:

> > Now you are batting 0-for-2 already.  Are you going to admit that
> > things aren't nearly as "convenient" as you claim them to be (and
> > certainly not "incredibly convenient")?
> > 
> No, I don't think so.  I'm just posing hypotheticals.  Thanks for
> clearing them up.  There are plenty of legal reorderings that I
> haven't tried to show since they're perfectly trivial.

Yes, there are some legal reorderings.

The sample size is not big enough to judge how frequent they are -- if
we assume you picked your examples at random.  But I think that you
picked them specifically to show legal transformations, and you
managed to pick incorrectly each time even though correctness was your
only constraint.  At least this seems to indicate that useful legal
transformations aren't as plentiful as you try to make us believe.

> But the real question is, why impose a burden on the compiler to prove
> nondependence in a language where a sizable majority of programs have
> none?

Because for a lot of interesting reorderings the compiler has to do
this sort of reasoning anyway.  Scheme is oddly sitting on the fence
here, imposing certain constraints while not imposing others -- making
the distinction for no apparent reason.  (C is actually a little bit
better in this respect -- provided you buy into unfixed order in the
first place.)

On the other hand, for a lot of other reorderings (especially if the
language has fewer effects) the reasoning is easy enough even under a
fixed order, so for those there is no good reason for an unfixed
order.

> At any rate, its becoming clear that arguing with you is
> non-terminating.

What do you want from me?  You want me to just say "you are right"
when you really are not?  Are you out of relevant things to say, given
that you now attack me personally?

In any case, it takes two to have a non-terminating argument.  And I
did not ask you to argue with me.  In fact, I'd prefer it if you
didn't.  If what you say at least were technically correct, we might
have a useful discussion.  But you keep contradicting me on things
that are facts, and you make technically incorrect claims.

The argument would have been over if you had managed to make a
convincing case.  Being technically correct in what you say would have
been a start.  Also, there are many matters of opinion in what I say,
and I am perfectly capable to agree to disagree on those.  Just don't
try to give a /proof/ that your opinion is "right", because it will
just end up being a logically flawed construction.

Anyhow, you shall have your wish: This is the last thing I say to you
on this matter.

Matthias
0
find19 (1244)
10/19/2004 11:19:22 PM
Matthias Blume <find@my.address.elsewhere> wrote:
> Matthias Blume <find@my.address.elsewhere> writes:
> 
>> "Scott G. Miller" <scgmille@freenetproject.org> writes:
>> > First of all.  In your previous post, your exact words were
>> > "specifically forbids".  So my response is completely relevant, since
>> > it absolutely refutes your assertion.
>> 
>> Ok, if you want to mince words, you are right.
>> 
>> What I meant, of course, was that it forbids executions that are
>> /inherently/ parallel.
> 
> Sorry for following up to myself.
> 
> But I have to take this back.  You are wrong.  I wrote "inherently"
> even the first time around.

There's no mincing words about it, and your meaningless "inherently"
qualifier doesn't change anything. You botched the whole parallelism
thing last time this came up, and you obviously didn't learn anything
from it.
-- 
Bradd W. Szonye
http://www.szonye.com/bradd
0