March 29, 2007
jcc7 wrote:
> == Quote from kris (foo@bar.com)'s article
>> jcc7 wrote:
>>> == Quote from kris (foo@bar.com)'s article
>>>
>>>> Frits van Bommel wrote:
>>>> [snip]
>>>>
>>>>> What I'm trying to say here is basically this: you shouldn't rely on the
>>>>> order of evaluation of parameters. Not even if one of them happens to be
>>>>> used as 'this' for the method in question.
>>>> Absolutely agree. Yet, without wishing to go off on a tangent, we're
>>>> talking about call-chaining and not parameter evaluation-order. These

Actually, we *were* talking about parameter evaluation-order in this subthread. From the post I was replying to:
---
We discussed this a long time ago and came to the conclusion that while the D spec does not guarantee *evaluation order* for this scenario, it seems impossible for it to be anything other than left to right because the chained calls rely on the return value from previous calls
---
(emphasis added)

>>>> are different things, and there was a painfully long thread on exactly
>>>> this subject a year or two ago.
>>>> Walter closed that one by stating call-chaining can only realistically
>>>> evaluate from left to right (or something to that effect) and that's
>>>> what D does.
[snip]

Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.

> http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=31264

(Assuming that's the correct thread)

The closest thing to "Walter closed that one by stating call-chaining can only realistically evaluate from left to right" I can find is this post[1]:
---
Walter Bright Wrote:
> "Manfred Nowak" <svv1999@hotmail.com> wrote in message
> news:Xns9727D45B325B1svv1999hotmailcom@63.105.9.61...
> > 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.
>
> I've been intending for a while now to revise that to make the order of
> evaluation explicit. The undefined order of evaluation does not offer many
> benefits, and causes a lot of headaches.
>
> But there are two different things here: order of evaluation, and operator
> precedence. D operator precedence is clearly defined. For example:
>
>     a + b + c
>
> is defined to be:
>
>     (a + b) + c
>
> There is no ambiguity. The order of evaluation ambiguity comes from the
> order a, b, and c are evaluated. For example, for:
>
> void a() { writefln("a"); }
> void b() { writefln("b"); }
> void c() { writefln("c"); }
> ...
> a() + b() + c()
>
> may output one of:
>
> abc
> acb
> bac
> bca
> cab
> cba
---

All he said was that the translation from expression to explicit opAdd calls is fixed by operator precedence, and that he was thinking about defining order of evaluation for the parameters in an expression. However, nowhere did I see *how* he intended to define it, nor that he ever did so.


[1]: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=31263
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
[snip]
>> Nobody claimed that it "guaranteedly" (whatever that means) does in the general case, so let's please move on?
>>
>> The only thing asserted is that call-chaining is evaluated in left-to-right order. I think we can safely put that back to bed again
> 
> 
> You wrote this:
> 
> -----------------------
> There used to be a tango/example like this variation:
> 
>     import tango.io.Console;
> 
>     void main()
>     {
>         Cout ("Please enter your name: ").flush;
>         Cout ("Hello, ") (Cin.get);
>     }
> -----------------------
> 
> The code is incorrect. Point blank. Right?

It operates just fine due to the underlying mechanisms, so "point blank" is making a big drama out of it. It does not illustrate good practice, however. If you wish to write a book about that, be my guest :-D
March 29, 2007
Frits van Bommel wrote:
> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.

That's not at stake here, as far as I'm aware?

> All he said was that the translation from expression to explicit opAdd calls is fixed by operator precedence, and that he was thinking about defining order of evaluation for the parameters in an expression. However, nowhere did I see *how* he intended to define it, nor that he ever did so.

Then I suggest you ask Walter? Please do so on a different thread, since this one has too many topics already? :)
March 29, 2007
kris wrote:
> Frits van Bommel wrote:
>> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.
> 
> That's not at stake here, as far as I'm aware?

My understanding is that it was brought up by yourself in an attempt to explain that Cout("Hello, ")(Cin.get) will work properly. There was an old thread mentioned, which deals with another problem entirely. So that doesn't apply. Now I understand that argument has been dropped entirely, and that now there is an argument that Cout("Hello, ")(Cin.get) works due to some other unmentioned reasons.

Cout("Hello, ", Cin.get) would remain correct in any instance if it existed.


Andrei
March 29, 2007
kris wrote:
> Frits van Bommel wrote:
>> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.
> 
> That's not at stake here, as far as I'm aware?

What I meant to say was that in 'Cout ("Hello, ") (Cin.get);' there's no guarantee that Cin.get will evaluate before Cout("hello, "). (though it _is_ guaranteed that sending that value to the output buffer will happen after the string gets sent)
Just because "Hello, " is somewhat unlikely to fill up the output buffer right after a flush (as it was in the code sample in question) doesn't mean it's okay to first output that and *then* ask for the name to put after it. At least, IMHO.
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> As long as it's not in the language definition, you can't count on it. I think this is a language defect anyhow; I am lobbying Walter to define left-to-right order of evaluation in all cases.

It's problematical to define the order of function argument evaluation, because some calling conventions push left-to-right, others right-to-left.

Not impossible, though.
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
> 
>> Frits van Bommel wrote:
>>
>>> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.
>>
>>
>> That's not at stake here, as far as I'm aware?
> 
> 
> My understanding is that it was brought up by yourself in an attempt to explain that Cout("Hello, ")(Cin.get) will work properly. There was an old thread mentioned, which deals with another problem entirely. So that doesn't apply. Now I understand that argument has been dropped entirely, and that now there is an argument that Cout("Hello, ")(Cin.get) works due to some other unmentioned reasons.

Then I politely suggest you are either badly confused, being entirely disengeneous, or are drunk ;-)

There never was any argument of which you claim. I simply noted that eval-order had been clarified before, using your usage of "eval-order" from within the same post. If you revisit, you'll see that was actually  referring to call-chaining instead, so there's perhaps a misuse of terms:

   Cout.opCall("Hello, ").opCall(Cin.get);

As you can see, there is only one parameter passed to each call, and therefore the order of /parameter/ eval is "not at stake here" (as I noted to Frits). What I had referred to vis-a-vis the prior thread was simply that call-chaining had been resolved in terms of eval-order. It evaluated left to right.

I'd try to help you understand all of the 'questions' you've recently brought up, but you don't appear to be the slightest bit interested in trying to understand much; sadly. I'm open to real discussion if that's what you'd prefer, yet your demeanour has been and continues to be that of someone with a hidden adgenda or with a axe to grind. If you'll drop that attitute forthwith, I'll be happy to continue
March 29, 2007
Frits van Bommel wrote:
> kris wrote:
> 
>> Frits van Bommel wrote:
>>
>>> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.
>>
>>
>> That's not at stake here, as far as I'm aware?
> 
> 
> What I meant to say was that in 'Cout ("Hello, ") (Cin.get);' there's no guarantee that Cin.get will evaluate before Cout("hello, "). (though it _is_ guaranteed that sending that value to the output buffer will happen after the string gets sent)
> Just because "Hello, " is somewhat unlikely to fill up the output buffer right after a flush (as it was in the code sample in question) doesn't mean it's okay to first output that and *then* ask for the name to put after it. At least, IMHO.

Yes, I agree. Call chaining is always left to right, though; it's just not written down in the spec at this time (along with several other things?)

I don't think anyone ever said that it was good practice to rely on some implementation idiom. The fact that this operates is merely interesting, and not something to start a war over ;-)
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> 
> So what's the recommended use of Cout?
> 
> (a) If you do stdio, use Cout (and don't forget to flush Cout manually every time you plan to read from Cin).

Oh right, this is what tie() is for with iostreams.  It's come up before in the past, though I can't recall if any conclusions were reached. I'll admit that the current behavior is a tad confusing here though.

> (b) But not for multithreaded programs that do stdio. For those, use the logger facility. If you want multithreaded output to stdout, copy the code from http://www.dsource.org/projects/tango/wiki/ChapterLogging into your program. Be careful that that code might be incorrect; the manual doesn't specify. If it is correct, be careful with what you do inside that code, because you could deadlock yourself.

To be fair, this is mostly a documentation issue.  Though it may be that the logger could be made easier to use for your example.  I'll have to look at the logger in more detail before I say any more--I've only used it a handful of times.

> (c) And not for programs linking with anything that uses C's stdio. For those, use Phobos.

Perhaps more accurately "programs that expect to mix output to the same device as linked libraries using C's stdio."  I can't recall ever needing this option, YMMV (and it obviously does).  One option might be to create a CStdioCondiuit or some such that uses C library calls instead of platform calls for IO.  Then the user could choose the appropriate one.

I think it's also perhaps worth noting that Tango is truly intended to be as much of an application framework as it is a collection of useful tools.  In fact, some non-essential features have been deliberately excluded to avoid discouraging third-party development.  I would also personally consider C stdio integration to be a specialized need for the typical D programmer, and therefore it is arguably not appropriate as the default configuration for Tango's IO layer if doing so incurs design or performance penalties (both of which seem to be the case, based on recent experimentation).  Therefore, I am not convinced that C integrated IO should be the default behavior for Tango's Cin/Cout, and feel it may be better offered as a separate conduit or handled some other way.  My opinion may well change if this proves to be a real issue for many people, but that's my gut feeling at the moment.


Sean
March 29, 2007
Frits van Bommel wrote:
> kris wrote:
>> Frits van Bommel wrote:
>>> Yes, call-chaining can only evaluate left-to-right, but the parameters *passed* to the calls can be evaluated in any order.
>>
>> That's not at stake here, as far as I'm aware?
> 
> What I meant to say was that in 'Cout ("Hello, ") (Cin.get);' there's no guarantee that Cin.get will evaluate before Cout("hello, "). (though it _is_ guaranteed that sending that value to the output buffer will happen after the string gets sent)

Oh right, this makes perfect sense.  In my original post I had meant the  order with respect to call chaining, not that Cin.get aberration ;-)

> Just because "Hello, " is somewhat unlikely to fill up the output buffer right after a flush (as it was in the code sample in question) doesn't mean it's okay to first output that and *then* ask for the name to put after it. At least, IMHO.

Agreed.


Sean