March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> On my machine, Tango does 4.3 seconds and the following phobos program (with Walter's readln) does 5.4 seconds:
> 
> #!/usr/bin/env rundmd
> import std.stdio;
> 
> void main() {
>    char[] line;
>    while (readln(line)) {
>      write(line);
>    }
> }
> 
> where write is a function that isn't yet in phobos, of the following implementation:
> 
> size_t write(char[] s) {
>    return fwrite(s.ptr, 1, s.length, stdout);
> }

On my Windows machine, using fwrite like that makes phobos twice as fast as the version using fputs.  But tango is still twice as fast as that.
March 29, 2007
Bill Baxter wrote:
> John Reimer wrote:
>> On Thu, 29 Mar 2007 15:19:40 +0900, Bill Baxter wrote:
>>
>>> kris wrote:
>>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>> - Tango is for D programmers; not C programmers.
>>> D programmers sometimes like to call 3rd party code written in other languages, and pretty much any interop in D has to happen via C compatibility.  E.g. pyD.  So I'm guessing if my D code calls on some Python code that prints to the console that somewhere down the line that eventually ends up on C's stdout.  I could be wrong, but at least that's why I *think* Andrei and Walter keep saying that C compatibility is important.
>>
>>
>> It's only important for those that are determined to use it, perhaps
>> because of persistant programming style or unrelenting attachment to C++
>> methods (where C and C++ seemed to keep an unholy matrimony). I'd hate to
>> see a D library infected with a C compatibility requirement -- support for
>> ugly C design decisions would most certainly taint Tango for the worse. I
>> believe Tango was made to help D step beyond that.
> 
> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.

That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.

Andrei
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Bill Baxter wrote:
>>
>> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.
> 
> That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.

Which interface?  And are you talking about input or output?


Sean
March 29, 2007
Sean Kelly wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Bill Baxter wrote:
>>>
>>> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.
>>
>> That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.
> 
> Which interface?  And are you talking about input or output?

Cout. The thing is that the design using the syntax Cout(a)(b) is conducive to two separate calls to the library. I recall this has been briefly discussed here.

Andrei
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Sean Kelly wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Bill Baxter wrote:
>>>>
>>>> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.
>>>
>>> That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.
>>
>> Which interface?  And are you talking about input or output?
> 
> Cout. The thing is that the design using the syntax Cout(a)(b) is conducive to two separate calls to the library. I recall this has been briefly discussed here.

Of course that could easily be fixed if either struct destructors or scope class returning were to be added to the language. Then you could just return something with a destructor that releases the lock.
March 29, 2007
kris wrote:
> Sean Kelly wrote:
> [snip]
>> I must be missing something.  Why is the following not acceptable?
>>
>>     import tango.io.Console;
>>
>>     void main()
>>     {
>>         char[] name;
>>         Cout( "Please enter your name: " ).flush;
>>         Cin.nextLine( name );
>>         Cout( "Hello, " )( name )( "!" );
>>     }
> 
> 
> 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);
>     }

Ah, also, the last line is translated into:

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

D does not specify evaluation order, so the code might end up printing "Hello, " before reading the standard input. It's funny this does not happen exactly because of buffering, but the program has no control over the buffering so it should assume flushing could happen at any time. So the correct code is:

auto name = Cin.get;
Cout("Hello, ")(name);


Andrei
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
>> Sean Kelly wrote:
>> [snip]
>>> I must be missing something.  Why is the following not acceptable?
>>>
>>>     import tango.io.Console;
>>>
>>>     void main()
>>>     {
>>>         char[] name;
>>>         Cout( "Please enter your name: " ).flush;
>>>         Cin.nextLine( name );
>>>         Cout( "Hello, " )( name )( "!" );
>>>     }
>>
>>
>> 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);
>>     }
> 
> Ah, also, the last line is translated into:
> 
> Cout.opCall("Hello, ").opCall(Cin.get);
> 
> D does not specify evaluation order, so the code might end up printing "Hello, " before reading the standard input.

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.  If this is untrue then I'd love to know the reasoning.  Perhaps an aggressive inlining mechanism could violate this?


Sean
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Sean Kelly wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Bill Baxter wrote:
>>>>
>>>> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.
>>>
>>> That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.
>>
>> Which interface?  And are you talking about input or output?
> 
> Cout. The thing is that the design using the syntax Cout(a)(b) is conducive to two separate calls to the library. I recall this has been briefly discussed here.

Just making sure we were on the same page.  In my experience, raw output is typically used for logging--that's about the only case I can think of where the random interleaving of messages is acceptable.  Tango has a separate logging facility which performs synchronization for exactly this purpose: tango.util.log.  Perhaps this particular critique would be more appropriately applied to the logging package?


Sean
March 29, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> kris wrote:
> 
>> Sean Kelly wrote:
>> [snip]
>>
>>> I must be missing something.  Why is the following not acceptable?
>>>
>>>     import tango.io.Console;
>>>
>>>     void main()
>>>     {
>>>         char[] name;
>>>         Cout( "Please enter your name: " ).flush;
>>>         Cin.nextLine( name );
>>>         Cout( "Hello, " )( name )( "!" );
>>>     }
>>
>>
>>
>> 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);
>>     }
> 
> 
> Ah, also, the last line is translated into:
> 
> Cout.opCall("Hello, ").opCall(Cin.get);
> 
> D does not specify evaluation order, so the code might end up printing "Hello, " before reading the standard input. It's funny this does not happen exactly because of buffering, but the program has no control over the buffering so it should assume flushing could happen at any time. So the correct code is:
> 
> auto name = Cin.get;
> Cout("Hello, ")(name);

Well aware of that, thanks. BTW: evaluation order has been clarified before, on a similar topic.
March 29, 2007
Frits van Bommel wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Sean Kelly wrote:
>>> Andrei Alexandrescu (See Website For Email) wrote:
>>>> Bill Baxter wrote:
>>>>>
>>>>> I believe the current discussion is only about under-the-hood implementation issues.  So I don't think you have to worry about any D libraries exposing (good or bad) C/C++ design decisions to users.  Tango is going to expose the same D interface no matter how it's implemented under the hood.
>>>>
>>>> That's great, however the interface has a problem too: it does not produce atomic strings in multithreaded programs.
>>>
>>> Which interface?  And are you talking about input or output?
>>
>> Cout. The thing is that the design using the syntax Cout(a)(b) is conducive to two separate calls to the library. I recall this has been briefly discussed here.
> 
> Of course that could easily be fixed if either struct destructors or scope class returning were to be added to the language. Then you could just return something with a destructor that releases the lock.

Struct destructors will be added, but typesafe variadics are already in. I think Cout(a, b) is the most natural interface to offer.


Andrei