December 09, 2005
"Manfred Nowak" <svv1999@hotmail.com> wrote
> Moreover the behaviour of the whisper notation is undefined according to the specs, which clearly state that the order of all expression evaluations are undefined if not explicitely defined---and no definition for the whisper notation is given.

That's an interesting point.

I'll counter it by noting that the compiler has little choice about the order of evaluation here:

classRef.method1().method2().method3();

It clearly cannot evaluate right to left, so it must start at the lhs. An implementation might then execute each method in random order, but what's the point? Further, method1() may return a reference to a different class reference, which means that it must be evaluated before method2() can be invoked. And so on. It's akin to unwrapping the expression like so:

auto a = classRef.method1();
auto b = a.method2();
b.method3();

It may be that D documentation does not explicitly state this behaviour, but it perhaps should?  Of course, DMD does a fine job optimizing such back-to-back calls. I understand GDC does a fine job also.


> | Stdout(CR; "files:"; CR);

This is a perfectly valid approach also. Mango.io was around long before D gained typeinfo for variadic arguments, so the option wasn't available then. Mango.io does use the variadic approach for printf() style formatting, so both are present for comparative purposes. On reflection, mango.io would still have chosen "whisper" for general purposes, since it's more flexible.

- Kris


"Manfred Nowak" <svv1999@hotmail.com> wrote in message news:Xns9727D45B325B1svv1999hotmailcom@63.105.9.61...
> John Demme wrote:
> [...]
>> This was originally called the "Whisper" notation.  It's rather nice, and I like it. What do y'all think?
>
> I do not find it that nice, because the whisper notation restricts the power of D to regular expressions over arguments lists, whereas context free languages over arguments lists are possible.
>
> I have written on that several month ago and proposed to drop this restriction by using
>
> | Stdout (CR; "files:"; CR);
>
> instead of
>
> | Stdout (CR) ("files:") (CR);
>
>
> Moreover the behaviour of the whisper notation is undefined according to the specs, which clearly state that the order of all expression evaluations are undefined if not explicitely defined---and no definition for the whisper notation is given.
>
> Therefore Mango is not portable at present between compilers. To make
> it portable instead of "Stdout(CR)("files:")(CR);" Mango should
> contain
>
> | ((Stdout(CR))("files:"))(CR);
>
> which is probably what is meant. Still I would prefer
>
> | Stdout(CR; "files:"; CR);
>
> or similar which on my opinion is as well more readable as freeing the full power of D.
>
> -manfred


December 09, 2005
On Fri, 9 Dec 2005 12:52:54 -0800, Kris wrote:


> It may be that D documentation does not explicitly state this behaviour, but it perhaps should?

Yes, that would clear things up nicely.

I guess that a statement such as

    b + c + d;

could evaluate to

    b.opAdd(c).opAdd(d)

or

    d.opAdd(c).opAdd(b)

but once the evaluation was set, the execution would proceed in left to right order.

-- 
Derek Parnell
Melbourne, Australia
10/12/2005 7:57:43 AM
December 09, 2005
Kris wrote:
> "Manfred Nowak" <svv1999@hotmail.com> wrote
>> Moreover the behaviour of the whisper notation is undefined according
>> to the specs, which clearly state that the order of all expression
>> evaluations are undefined if not explicitely defined---and no
>> definition for the whisper notation is given.
> 
> That's an interesting point.
> 
> I'll counter it by noting that the compiler has little choice about the order of evaluation here:
> 
> classRef.method1().method2().method3();
> 
> It clearly cannot evaluate right to left, so it must start at the lhs. An implementation might then execute each method in random order, but what's the point? Further, method1() may return a reference to a different class reference, which means that it must be evaluated before method2() can be invoked. And so on. It's akin to unwrapping the expression like so:
> 
> auto a = classRef.method1();
> auto b = a.method2();
> b.method3();
> 
> It may be that D documentation does not explicitly state this behaviour, but it perhaps should?  Of course, DMD does a fine job optimizing such back-to-back calls. I understand GDC does a fine job also.

I think it should.  The C++ spec states that "postfix expressions group left to right" and opCall is clearly a postfix expression.  Also, it seems to be a primary design goal of D to preserve C/C++ expression syntax rules whenever possible as not doing so would be confusing and would lead to subtle bugs when porting code.


Sean
December 09, 2005
In article <gf10ceogj4nu.1k0swchr1kpfj.dlg@40tude.net>, Derek Parnell says...
>
>On Fri, 9 Dec 2005 12:52:54 -0800, Kris wrote:
>
>
>> It may be that D documentation does not explicitly state this behaviour, but it perhaps should?
>
>Yes, that would clear things up nicely.
>
>I guess that a statement such as
>
>    b + c + d;
>
>could evaluate to
>
>    b.opAdd(c).opAdd(d)
>
>or
>
>    d.opAdd(c).opAdd(b)
>
>but once the evaluation was set, the execution would proceed in left to right order.
>
>-- 
>Derek Parnell
>Melbourne, Australia
>10/12/2005 7:57:43 AM

the order of evaluation can make a difference even without side effects
Example (contrived):

class A { B opAdd(C);   A opAdd(A) };
class C { C opAdd(C);   A opAdd(B) };
class B {  };

A a;
B b;
C c;

auto a2 = a + (b + c);  // a2 is A
auto c2 = (a + b) + c;  // c2 is C

auto q  = a + b + c;    // q is A or C??



December 09, 2005
Derek Parnell wrote:

[...]
> As the sequence of evaluation is not defined (in the general
> case), this might output ...
> 
>   world hello
> 
> in some implementations of D.

Very true.

The pitfall here is that some seem to think, that if an evaluation in one phase is possible it must also be done in one phase.

But according to the specs the compiler is not forbidden to use two phases:

First phase: determine the functions to be called for every list of
arguments. I.e. in the example given:
  Stdout.opCall(CR), Stdout.opCall("hello"), ...

Second phase: execute the functions determined in phase one on their associated arguments lists *in any order*

-manfred
December 09, 2005
Kris wrote:

[...]
> An implementation might then execute each method in
> random order, but what's the point?
[...]

Other way round: what's the point to not define the order?

Because the compiler might see optimizations and adaptions to the underlying hardware which now everyone is unable to imagine.

Future is always unpredictable ;-)

Therefore Walters decision to not define the order is correct in the general case. If you want it defined split the expression by using parentheses or temporal variables.

If in the latter case one wants syntactical sugar one should state it as such.

-manfred
December 10, 2005
"Manfred Nowak" <svv1999@hotmail.com> wrote
>
> The pitfall here is that some seem to think, that if an evaluation in one phase is possible it must also be done in one phase.
>
> But according to the specs the compiler is not forbidden to use two phases:
>
> First phase: determine the functions to be called for every list of
> arguments. I.e. in the example given:
>  Stdout.opCall(CR), Stdout.opCall("hello"), ...
>
> Second phase: execute the functions determined in phase one on their associated arguments lists *in any order*

~~~~~~~~~~~~~~~~~~~~~~~~~~~

There's no doubt that *your* example above could be reordered, but we're not discussing such an example; are we. Said example appears to have confused chaining with comma-seperated expressions. They are quite different animals. Returning to the relevant example:

classRef.method1().method2().method3();

Each dereferenced lValue *cannot be determined* until the appropriate call has been made. You see?  The expression evaluates deterministically, because of one simple observation: the very act of retrieving each subsequent lValue has the "side effect" of executing each method in the desired order. Again, to unwind:

auto a = classRef.method1();
auto b = a.method2();
b.method3();

That is; method2 cannot be called until method1 returns an lValue. Method3 cannot be called until method2 returns an lValue. These are cleary ordered, and this is what chaining effects ... something entirely different from what you appear to be stating.

To address your example, these two expressions are not equivalent ~ they're barely even related:

1)  classRef.method1().method2().method3();

2)  classRef.method1(), classRef.method2(), classRef.method3();

Does that help?


December 10, 2005
BCS wrote:

[...]
> auto q  = a + b + c;    // q is A or C??

very nice example :-)

... and this is also a severe blow onto the secureness of the whisper notation.

-manfred
December 10, 2005
Kris wrote:

[...]
> To address your example, these two expressions are not equivalent ~ they're barely even related:
> 
> 1)  classRef.method1().method2().method3();
> 
> 2)  classRef.method1(), classRef.method2(), classRef.method3();
> 
> Does that help?

No. I see your arguments as beeing totally contradictory.

The evaluation order under 1) is undefined per defintition, whereas the order of evaluation under 2) is defined by left to right evaluation and in addition returning the type of the rightmost assignexpression.

If you cannot recognize the contradiction to your own argument given in the part cited with [...] it is useless to post any further.

-manfred
December 10, 2005
Derek Parnell wrote:
> On Fri, 9 Dec 2005 12:52:54 -0800, Kris wrote:
> 
>>It may be that D documentation does not explicitly state this behaviour, but it perhaps should? 
> 
> 
> Yes, that would clear things up nicely.
> 
> I guess that a statement such as 
> 
>     b + c + d;
> 
> could evaluate to
> 
>     b.opAdd(c).opAdd(d)
> 
> or
> 
>     d.opAdd(c).opAdd(b)
> 
Doubtful. It is not clear in the spec, but I bet in D the operator evaluation order is well-defined, and is the same as C/C++. Thus "b + c + d" evaluates to:
  ((b + c) + d)
and then to the corresponding opAdd's. And the function call operator sequences evaluate left to right too.
What is not well defined, both in C/C++ and in D are the expression *components* order of evaluation. Stuff like (straight from the docs):
  i = ++i;
  c = a + (a = b);
  func(++i, ++i);
which is an ambiguity that you *can not even* resolve with parenthesis.


-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to be... unnatural."