stdio line-streaming revisited

kris foo at bar.com
Fri Mar 30 00:19:56 PDT 2007


Derek Parnell wrote:
> On Thu, 29 Mar 2007 22:40:34 -0700, Walter Bright wrote:
> 
> 
>>kris wrote:
>>
>>>   Cout.opCall("Hello, ").opCall(Cin.get);
>>
>>Given:
>>	a.f(b,c);
>>can be equivalently written as:
>>	f(a,b,c);
>>
>>we can transform:
>>	Cout.opCall("Hello, ").opCall(Cin.get);
>>into:
>>	opCall(opCall(Cout,"Hello, "), Cin.get);
>>
>>And it is transformed that way, because the optimizer/back end knows 
>>nothing about member functions. They're just more function calls.
>>
>>The nested opCall will get called before the outer opCall, but otherwise 
>>the order is undefined (and will change depending on the function 
>>calling convention, whether it is a virtual call or not, etc.). 
> 
> 
> Now that makes sense. I can see now why the W&A show is concerned. In fact,
> the call-chaining example seems to flesh out to ...
> 
>    opCall(opCall(Cout,"Hello, "), get(Cin));
> 
> which means that either the 'get' could be called first or the inner
> 'opCall' could be called first. One can never be sure.

No problemo


> This would mean that the sequence example given by Kris ...
> 
>     Cout ("Please enter your name: ").flush;
>     Cout ("Hello, ") (Cin.get);
> 
> gets transformed in to 
> 
>     flush( opCall( Cout, "Please enter your name: "));
>     opCall( opCall( Cout, "Hello, "), get(Cin));
> 
> The first statement will end up displaying the text on the console, leaving
> the cursor to the right of the ':' character. Now if the 'get' is called
> next, the user types in her name, say "mavis" and the screen will show ...
> 
>   Please enter your name: mavis
>   _
> 
> and then the inner 'opCall' is run which will show (assuming a flush) ...
> 
>   Please enter your name: mavis
>   Hello, mavis
>   _

Yes, although the second newline does not exist


> However, if the inner 'opCall' is called first the screen will show ...
> 
>   Please enter your name: Hello, _

That's where the tricky example is fooling everyone. In short, the 
example operates "correctly" (at least, on Win32) regardless of which 
way the execution occurs. In other words, it is not dependent upon 
execution order. It makes no assumptions there whatsoever ;)


> 
> and the user types in her name and we get ...
> 
>   Please enter your name: Hello, mavis
>   mavis
>   _
> 
> 
> So the order is reasonable important to sort out.

That may be so, but as long as call-chaining operates in a left to right 
order, Tango doesn't care about which order parameters are evaluated. 
Again, the example is leading everyone on a wild goose chase. If there's 
one thing I'll regret from this NG, it will be posting that trivial bit 
of mind-bending

> 
> Being the conservative procedural type of coder, I would have probably have
> coded ...
> 
>     char[] userName;
>     Cout ("Please enter your name: ").flush;
>     userName = Cin.get();
>     Cout ("Hello, ");
>     Cout (userName);
>     Cout.flush;
> 
> Actually, now that I think about it, I'd really do ...
> 
>     char[] userName;
>     char[] myResponse;
> 
>     Cout ("Please enter your name: ");
>     Cout.flush;
>     userName = Cin.get();
>     myResponse = std.string.format("Hello, %s\n", userName);
>     Cout.( myResponse );
>     Cout.flush;

And I would generally do

     Cout ("Please enter your name: ") ();
     auto name = Cin.get;
     Cout ("Hello, ")(name) ();

Which amounts to the same thing, I expect?


> That is of course, if I'd really used stdin/stdout in that manner at all
> <G>

Bingo! It blows me away just how much attention the lowly console is 
recieving :)



More information about the Digitalmars-d mailing list