www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Whisper Syntax

reply Ben Phillips <Ben_member pathlink.com> writes:
This is a question I would like to put out there to all of those that support
whisper syntax. Why is it preferable over writef-like syntax?

Why use something like

stdout(a)(b)(c)(d)(e)(f);

instead of

writef(a, b, c, d, e, f);

or if you are using a stream something like

stream.write(a, b, c, d, e, f);

??? To me the writef syntax is natural because it's just normal method call
syntax, whereas whisper syntax is not natural at all. I can't think of a case
where whisper syntax would be preferable over something as natural (and elegant
imo) as that of writef.
Dec 11 2005
next sibling parent reply JT <JT_member pathlink.com> writes:
Im just curious why its called 'Whisper', whats the story behind this? :D
Dec 11 2005
next sibling parent clayasaurus <clayasaurus gmail.com> writes:
JT wrote:
 Im just curious why its called 'Whisper', whats the story behind this? :D
 

I did a quick google search and I think it has to do with the syntax of the whisper programming language. http://tinyurl.com/9yats
Dec 11 2005
prev sibling parent "Kris" <fu bar.com> writes:
The name came about from the usage of the parens (as in the way a writer 
uses parens).  It looks as though someone is whispering things.

Another option at the time was "psssst" ~ but that didn't quite have the 
same ring to it ;-)

- Kris


"JT" <JT_member pathlink.com> wrote in message 
news:dnhevh$2ag6$1 digitaldaemon.com...
 Im just curious why its called 'Whisper', whats the story behind this? :D


 

Dec 11 2005
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ben Phillips" <Ben_member pathlink.com> wrote in message 
news:dnhd71$2635$1 digitaldaemon.com...
 This is a question I would like to put out there to all of those that 
 support
 whisper syntax. Why is it preferable over writef-like syntax?

 Why use something like

 stdout(a)(b)(c)(d)(e)(f);

 instead of

 writef(a, b, c, d, e, f);

 or if you are using a stream something like

 stream.write(a, b, c, d, e, f);

 ??? To me the writef syntax is natural because it's just normal method 
 call
 syntax, whereas whisper syntax is not natural at all. I can't think of a 
 case
 where whisper syntax would be preferable over something as natural (and 
 elegant
 imo) as that of writef.

I don't think the syntax is too ugly or hard to follow, but it makes it somewhat easier to write the functions. Consider what you'd have to do if you used variadic args: class Something { public void opCall(...) { for(uint i = 0; i < _arguments.length; i++) { if(_arguments[i] == typeid(byte)) { // cast, output, use the std.stdarg.va_arg function to increment the arg ptr } else if(_arguments[i] == typeid(ubyte)) { // cast, output, use the std.stdarg.va_arg function to increment the arg ptr } // .... for every type } } } This puts a lot of RTTI overhead in the opCall implementation, especially if you're writing an output stream opCall which has to support a ton of types. Consider, then, the "Whisper" method: class Something { public Something opCall(byte b) { // output b; return this; } public Something opCall(ubyte b) { // output b; return this; } } The correct function is selected at compile time rather than having to determine the input values' types for each parameter to the function. The only disadvantage of the Whisper method is the overhead of calling the opCalls for each parameter instead of making one call for a group of parameters, but it'd have to be tested to see if the price of RTTI testing with the single-function method would eliminate any gains made by only calling the opCall once.
Dec 11 2005
prev sibling parent "Kris" <fu bar.com> writes:
"Ben Phillips" <Ben_member pathlink.com> wrote in message 
news:dnhd71$2635$1 digitaldaemon.com...
 This is a question I would like to put out there to all of those that 
 support
 whisper syntax. Why is it preferable over writef-like syntax?

 Why use something like

 stdout(a)(b)(c)(d)(e)(f);

 instead of

 writef(a, b, c, d, e, f);

I'll have a go at answering this, Ben, with my personal observations. Others will no-doubt have alternative perspectives. First, I'll crib some text from a prior post: ~~~~~~~~~~~~~~~~~ Yes, that's the general idea. The mango.io package is based partly upon a set of buffered readers and writers. At their heart, the readers and writers support a chaining put/get syntax; similar to how you describe it: class Writer { Writer put (int) {} Writer put (char[]) {} Writer put (dchar[]) {} ... } class Reader { Reader get (inout int) {} Reader get (inout char[]) {} Reader get (inout dchar[]) {} ... } These are aliased both as opCall() and opShl()/opShr(). Obviously, this supports the C++ iostream syntax: Writer write; Reader read; write << 10 << "green bottles"; read >> count >> description. But, more to the point, it supports what we affectionately call "whisper" syntax in Mango: void foo (Writer write, Reader read) { char[] materials; int time, cost; write (time) (cost) (materials); read (time) (cost) (materials); } Some nice aspects of this particular approach are: 1) the syntax is identical for both read & write operations. The compiler takes care of providing the appropriate source or target reference. The only different is the verb used (write vs read). You can use the verbs input/output instead, if that rocks your boat :-) 2) it is thoroughly type-safe. At compile-time! 3) default arguments can be passed as part of the call. 4) it is quite efficient. DMD does a fine job optimizing this style of programming. It's faster than extracting type-info from varargs. 5) the approach supports an obvious and natural way to be explicit about transcoding (between char/wchar/wdchar content). 6) it is flexible and highly extensible. For example, the syntax is just the same whether you're working with text or binary I/O 7) an empty set of parenthesis maps quite naturally to a "flush" operation :-) e.g: write (time) (cost) (materials) (); 8) there's nothing that restricts one from using printf() syntax instead. For example, the text oriented DisplayWriter additionally has print() and println() methods. Stdout is an instance of DisplayWriter. 9) it becomes trivial to map a user-class to the I/O system ~ i.e. ============== class ContractJob : IWritable, IReadable { char[] materials; int time, cost; void write (IWriter output) { output (time) (cost) (materials); } void read (IReader input) { input (time) (cost) (materials); } } ContractJob job1; ContractJob job2; write (job1) (job2) (); read (job1) (job2); =============== 10) "whisper" is a cool name :-p You can read more about Mango I/O in the source code, such as here: http://trac.dsource.org/projects/mango/browser/trunk/mango/io/Buffer.d http://trac.dsource.org/projects/mango/browser/trunk/mango/io/Writer.d http://trac.dsource.org/projects/mango/browser/trunk/mango/io/Reader.d ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Now I'll try to identify a distinction. For my purposes, there are really two types of I/O in general usage ~ where one is a special case of the other. 1) raw data I/O 2) formatted, or readable, I/O; though I'll try to keep things simple by avoiding XML et. al. Whisper syntax is all about the first instance. Through subclassing, it handles things like endian issues, class serialization, and so on. Formatted I/O, and output in particular, is a really useful thing to have. Witness the various remarks from Walter about printf() and why it was still around in D for ages. Console output is perhaps the predominant area for such things, though files used to be written this way also. I find printf() formatting invaluable for console output also, but prefer something more robust for the long-term ~ logging APIs are one solution there. I should also note that, IMO, all the nice little formatting capabilites in printf() should actually be exposed as a cohesive and efficient set of discrete functions; for usage in areas other than console interaction. Mango.convert takes care of this by exposing each discrete function that the formatter uses. That's simply a design choice. Anyway, I find there's a delineation between #1 & #2, but with some overlap. Of course, it would be great to blend the two camps together. Mango.io has experimented in this area by adding print() and println() methods to a writer subclass called DisplayWriter ~ which avoids some concerns such as redundant buffering. Someone mentioned earlier that they thought Walter had "rejected" the idea of using opCall. In retrospect (after reading Justin's link), it's clear to me Walter felt that typesafe varargs were a better way to handle formatted output. I, for one, fully agree! So he added typesafe varargs, and I assume moved onto better things. Yet, formatted output is not the focus of "whisper", which is why mango.io has significant support for formatting and tokenizing *as a seperate entity* from raw I/O. I really want to point out two things that may get lost here: 1) whisper gets compile-time type-safety applied, and is truly symmetrical in usage. 2) Strewth! it's just an I/O package! I really just can't believe all the fuss and bad feeling over this ~ it's like mango.io were holding someone's child for randsom! Everyone, get over it :-) And, if you like the notions, then please lend a hand with the Mango project ~ the more the merrier ;-) (*cough*) So, in summary, mango.io leverages both approaches. It's horses-for-courses all over again. Does that help? - Kris
Dec 11 2005