stdio line-streaming revisited
Chris Nicholson-Sauls
ibisbasenji at gmail.com
Thu Mar 29 07:46:05 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.
>
> 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
> _
>
>
> However, if the inner 'opCall' is called first the screen will show ...
>
> Please enter your name: Hello, _
>
> 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.
>
> 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;
>
> That is of course, if I'd really used stdin/stdout in that manner at all
> <G>
>
I'd do something like...
import tango .io .Console ;
import tango .io .Stdout ;
char[] userName ;
Stdout ("Please enter your name: "c) .flush ;
userName = Cin.get();
Stdout .formatln("Hello, {}.", userName) .flush ;
That's closer to my usage patterns with Tango. (I'm a bigger fan of Stdout than Cout in
most cases, partly because I use plenty of format strings.)
-- Chris Nicholson-Sauls
More information about the Digitalmars-d
mailing list