## D - formatted output trial balloon

"Walter" <walter digitalmars.com> writes:
Since with () overloading class objects can now look like functions, I've
been toying with the idea of using this for formatted I/O. Here's a trial
mockup of what it might look like:

-----------------------------------------------
import std.string;
import std.c.stdio;
import std.c.stdlib;

class Stdout
{
Stdout opCall(int i)
{
printf("%d", i);
return this;
}

Stdout opCall(char[] format, ...)
{
va_list ap;
ap = cast(va_list)&format;
ap += format.size;
vprintf(format, ap);
return this;
}

Stdout nl()
{
printf("\n");
return this;
}
}

void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}
-------------------------------------------

(Note that it retains the power of printf!) The issue here is how the syntax
stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.
Nov 05 2003
"Walter" <walter digitalmars.com> writes:
Andy Friesen also had very close to this idea earlier. -Walter

D/17402
Nov 05 2003
Andy Friesen also had very close to this idea earlier. -Walter

D/17402

Or, C++ has type-safe 'format' library http://boost.org/libs/format/doc/format.html which cout << format("%|04| *%|=7|*\n") % 100 % "foo"; prints "0100 * foo *" and linefeed. operator % is used here. (maybe % of "%d" or "%s"... is the origin) But i prefer Andy's operator~ approach. Since ~ already has the meaning "concatination", i think it's quite natural.
Nov 06 2003
"Walter" <walter digitalmars.com> writes:
"Kazuhiro Inaba" <Kazuhiro_member pathlink.com> wrote in message
news:bodpsg$n5e$1 digitaldaemon.com...
Andy Friesen also had very close to this idea earlier. -Walter

D/17402

Or, C++ has type-safe 'format' library http://boost.org/libs/format/doc/format.html which cout << format("%|04| *%|=7|*\n") % 100 % "foo"; prints "0100 * foo *" and linefeed. operator % is used here. (maybe % of "%d" or "%s"... is the origin) But i prefer Andy's operator~ approach. Since ~ already has the meaning "concatination", i think it's quite

Thanks for the boost link. The ~ certainly does look better. One of my problems with the format() function, though, is it creates and returns a string, which then gets output. This results in double-buffering, something I want to avoid (for efficiency reasons).
Nov 06 2003
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:

stdout ~ "asdf" ~ ("%d", foo);

operator.

Walter wrote:
"Kazuhiro Inaba" <Kazuhiro_member pathlink.com> wrote in message
news:bodpsg$n5e$1 digitaldaemon.com...

Andy Friesen also had very close to this idea earlier. -Walter

D/17402

Or, C++ has type-safe 'format' library http://boost.org/libs/format/doc/format.html which cout << format("%|04| *%|=7|*\n") % 100 % "foo"; prints "0100 * foo *" and linefeed. operator % is used here. (maybe % of "%d" or "%s"... is the origin) But i prefer Andy's operator~ approach. Since ~ already has the meaning "concatination", i think it's quite

natural. Thanks for the boost link. The ~ certainly does look better. One of my problems with the format() function, though, is it creates and returns a string, which then gets output. This results in double-buffering, something I want to avoid (for efficiency reasons).

Nov 06 2003
"Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boecta$1kbb$1 digitaldaemon.com...

stdout ~ "asdf" ~ ("%d", foo);

operator.

Unfortunately, the way overloading works, I don't see how I could make () be a parameter list rather than a parenthesized expression.
Nov 06 2003
"Jan-Eric Duden" <jeduden whisset.com> writes:
tuples would help here :)

--
Jan-Eric Duden
"Walter" <walter digitalmars.com> wrote in message
news:boep4t$26nb$1 digitaldaemon.com...
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boecta$1kbb$1 digitaldaemon.com...

stdout ~ "asdf" ~ ("%d", foo);

operator.

Unfortunately, the way overloading works, I don't see how I could make ()

a parameter list rather than a parenthesized expression.

Nov 07 2003
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Can you expand on this?  Is this an issue particular to your compiler
implementation, or something else?

Walter wrote:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boecta$1kbb$1 digitaldaemon.com...

stdout ~ "asdf" ~ ("%d", foo);

operator.

Unfortunately, the way overloading works, I don't see how I could make () be a parameter list rather than a parenthesized expression.

Nov 07 2003
"Walter" <walter digitalmars.com> writes:
In general, a~b is overloaded by looking at the types of a and the types of
b. The type of a here is Stdout. The type of b, however, is the type of foo.
That isn't going to use the overload of ().

"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:bogq3g$21fv$1 digitaldaemon.com...
Can you expand on this?  Is this an issue particular to your compiler
implementation, or something else?

Walter wrote:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boecta$1kbb$1 digitaldaemon.com...

stdout ~ "asdf" ~ ("%d", foo);

operator.

Unfortunately, the way overloading works, I don't see how I could make

a parameter list rather than a parenthesized expression.

Nov 08 2003
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I'm sorry, maybe I wasn't clear in what I was suggesting.  I was
suggesting that the following expression:
stdout ~ ("%d", foo);
would call the following member function:
class Stdout {
Stdout cat(char[], int);
}
whereas simple uses (without parens) would get mapped to single-argument
versions of cat().  So this line:
stdout ~ "asdf" ~ ("%d", foo);
would be exactly equivalent to
stdout.cat("asdf").cat("%d", foo);

Russ

Walter wrote:
In general, a~b is overloaded by looking at the types of a and the types of
b. The type of a here is Stdout. The type of b, however, is the type of foo.
That isn't going to use the overload of ().

stdout ~ "asdf" ~ ("%d", foo);

Nov 10 2003
"Charles Sanders" <sanders-consulting comcast.net> writes:
I like it!  Im not a fan of the .nl() though it looks inconsistent, not sure
how else to handle it though.

C

"Walter" <walter digitalmars.com> wrote in message
news:boc9me$1g2b$1 digitaldaemon.com...
Since with () overloading class objects can now look like functions, I've
been toying with the idea of using this for formatted I/O. Here's a trial
mockup of what it might look like:

-----------------------------------------------
import std.string;
import std.c.stdio;
import std.c.stdlib;

class Stdout
{
Stdout opCall(int i)
{
printf("%d", i);
return this;
}

Stdout opCall(char[] format, ...)
{
va_list ap;
ap = cast(va_list)&format;
ap += format.size;
vprintf(format, ap);
return this;
}

Stdout nl()
{
printf("\n");
return this;
}
}

void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}
-------------------------------------------

(Note that it retains the power of printf!) The issue here is how the

stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.

Nov 05 2003
"Ben Hinkle" <bhinkle4 juno.com> writes:
Note .nl() is the same as ("\n") if that's any better.

-Ben

"Charles Sanders" <sanders-consulting comcast.net> wrote in message
news:bocf1q$1o62$1 digitaldaemon.com...
I like it!  Im not a fan of the .nl() though it looks inconsistent, not

how else to handle it though.

C

"Walter" <walter digitalmars.com> wrote in message
news:boc9me$1g2b$1 digitaldaemon.com...

been toying with the idea of using this for formatted I/O. Here's a

mockup of what it might look like:

-----------------------------------------------
import std.string;
import std.c.stdio;
import std.c.stdlib;

class Stdout
{
Stdout opCall(int i)
{
printf("%d", i);
return this;
}

Stdout opCall(char[] format, ...)
{
va_list ap;
ap = cast(va_list)&format;
ap += format.size;
vprintf(format, ap);
return this;
}

Stdout nl()
{
printf("\n");
return this;
}
}

void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}
-------------------------------------------

(Note that it retains the power of printf!) The issue here is how the

stdout("foo")("bar") looks. In C++ it would look like

which I don't find appealing.

Nov 05 2003
Charles Sanders wrote:

I like it!  Im not a fan of the .nl() though it looks inconsistent, not sure
how else to handle it though.

C

stdout("hello")(" world")(47)(endl)("bar")("%06i\n", 62);
Nov 05 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:bocj2a$1tns$2 digitaldaemon.com...
Charles Sanders wrote:

I like it!  Im not a fan of the .nl() though it looks inconsistent, not

how else to handle it though.

Instead of nl you could have a constant, ie endl

Yah.
stdout("hello")(" world")(47)(endl)("bar")("%06i\n", 62);

Why on earth would you go to all the trouble to replace printf, and end up supporting the same bad technique anyway in all its untype-safe glory? That last bit should be some kind of integer formatting function or object. Sean
Nov 05 2003
"Charles Sanders" <sanders-consulting comcast.net> writes:
But what would endl be defined as, an arbitrary number ?  How would it know
i didnt actually want to output that specific number ?

C
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:bocj2a$1tns$2 digitaldaemon.com...
Charles Sanders wrote:

I like it!  Im not a fan of the .nl() though it looks inconsistent, not

how else to handle it though.

C

stdout("hello")(" world")(47)(endl)("bar")("%06i\n", 62);

Nov 05 2003
Andy Friesen <andy ikagames.com> writes:
Charles Sanders wrote:

But what would endl be defined as, an arbitrary number ?  How would it know
i didnt actually want to output that specific number ?

C

A typedeffed value. Or some sort of unique mutator object. -- andy
Nov 05 2003
"Charles Sanders" <sanders-consulting comcast.net> writes:
Whats a mutator object ?

C

"Andy Friesen" <andy ikagames.com> wrote in message
news:bocnr5$25gn$2 digitaldaemon.com...
Charles Sanders wrote:

But what would endl be defined as, an arbitrary number ?  How would it

i didnt actually want to output that specific number ?

C

A typedeffed value. Or some sort of unique mutator object. -- andy

Nov 06 2003
Andy Friesen <andy ikagames.com> writes:
Charles Sanders wrote:
Whats a mutator object ?

C

err.... I think C++ calls them maniuplators. Interface StreamManipulator { void manipulate(Stream s); } class Stream { ... Stream opCall(StreamManipulator manipulator) { manipulator.manipulate(this); return this; } } Basically, it's a polymorphic way to allow an object to manipulate how the stream does things. Manpulators can be used to change how the stream formats certain types of values. So, you could do something like stdout("X is equal to ")(floatFormat(8,3))(x); Where floatFormat returns a manipulator that tells stdout how to format x. (assuming x is a float) of course, stdout could simply have an overload for opCall that accepts three arguments instead of one. opCall(float f, int space, int precision) Mutators are probably still a good idea, though, as creating them doesn't require changes to the source of the stream class. -- andy
Nov 06 2003
Charles Sanders wrote:

But what would endl be defined as, an arbitrary number ?  How would it know
i didnt actually want to output that specific number ?

C
"J Anderson" <REMOVEanderson badmama.com.au> wrote in message
news:bocj2a$1tns$2 digitaldaemon.com...

Charles Sanders wrote:

I like it!  Im not a fan of the .nl() though it looks inconsistent, not

how else to handle it though.

C

stdout("hello")(" world")(47)(endl)("bar")("%06i\n", 62);

or function (endl()). -Anderson
Nov 05 2003
In article <bocoep$26eh$2 digitaldaemon.com>, J Anderson says...
Charles Sanders wrote:

But what would endl be defined as, an arbitrary number ?  How would it know
i didnt actually want to output that specific number ?
[...]

I'd be defined as a constant char or constant char[] or constant char*, or function (endl()).

I suggest to create a special class Stdout.NLClass, define endl as a const Stdout.NLClass object, and define an opCall with a Stdout.NLClass parameter that does the job. Ciao
Nov 05 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
I'm sorry, but I think the introduction of global variables purely for
syntactic sugaring is a slippery slope that none of us will like hitting the
bottom of.

In general, if you need global variables, your design is flawed.

"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message
news:bocv12$2g8q$1 digitaldaemon.com...
In article <bocoep$26eh$2 digitaldaemon.com>, J Anderson says...
Charles Sanders wrote:

But what would endl be defined as, an arbitrary number ?  How would it

i didnt actually want to output that specific number ?
[...]

I'd be defined as a constant char or constant char[] or constant char*, or function (endl()).

I suggest to create a special class Stdout.NLClass, define endl as a const Stdout.NLClass object, and define an opCall with a Stdout.NLClass

does the job.

Ciao

Nov 06 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:

Anyway it's not a global variable, it's a global constant.  Similar to PI or
whatever.  Are you saying those are always bad too?

Sean

"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:bod14n$2ka4$1 digitaldaemon.com...
I'm sorry, but I think the introduction of global variables purely for
syntactic sugaring is a slippery slope that none of us will like hitting

bottom of.

In general, if you need global variables, your design is flawed.

Nov 09 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:

Nov 09 2003
Charles Sanders:
But what would endl be defined as, an arbitrary number ?  How would it know
i didnt actually want to output that specific number ?

This should work: typedef uint SpecialChar; enum: SpecialChar { endl = 0, tab = 1, ... } So endl won't be confused with uints. But we can also use this: version(linux) const char endl = '\n'; version(Win32) const char[] endl = "\r\n"; But I don't like Stdout(...)(...)(...). I'd like Stdout.print(...)(...)(...) instead, though I understand that it's harder to implement. There should be: file.print(...)(...)(...); // write formatted data file.scan(...)(...)(...); // read formatted data file.write(...)(...)(...); // write raw data file.read(...)(...)(...); // read raw data I'll try to write something that works... Dario
Nov 06 2003
Something like this will work:
Nov 06 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
He he. That's as much counter-semantic operator overloading as I like to
see.

Bravo!

"Dario" <Dario_member pathlink.com> wrote in message
news:bodm0g$he4$1 digitaldaemon.com...
Something like this will work:

Nov 06 2003
Oops, an empty message...
I swear I wrote something in it! :-O

Something like this should work:
_
_  const char[] endl = "\r\n";
_
_  struct Write
_  {   private Stream stream;
_      Write opCall(char x) {
_          stream.rawWrite(&x, x.size);
_          return *this;
_      }
_      Write opCall(char[] x) {
_          stream.rawWrite(x, x.length);
_          return *this;
_      }
_  }
_
_  class Stream
_  {   union
_      {   private Stream self;
_          Write write;
_      }
_      this() { self = this; }
_      abstract void rawWrite(void*, uint);
_  }
_
_  class File: Stream
_  {   HANDLE fd;
_      this(HANDLE fd) { this.fd = fd; }
_      void rawWrite(void* bf, uint sz)
_      {   uint wr;
_          WriteFile(fd, bf, sz, &wr, null);
_      }
_  }
_
_  void main()
_  {   File stdout = new File(GetStdHandle(-11));
_      stdout.write("Hello")('!')(endl);
_  }

I realize that this code looks tricky and cumbersome.
And it isn't perfect too: a reference to the stream
is kept though it shouldn't be necessary.

Notice how the const char[] endl fits well.
I guess it can be useful to write portable code too.
Dario
Nov 06 2003
In article <bocf1q$1o62$1 digitaldaemon.com>, Charles Sanders says...
I like it!  Im not a fan of the .nl() though it looks inconsistent, not sure
how else to handle it though.

C

I agree. ("\n") seems a little cleaner to me. Also, would it make sense to declare Stdout static in stdio so you don't need to instantiate it each time? -Jon
"Walter" <walter digitalmars.com> wrote in message
news:boc9me$1g2b$1 digitaldaemon.com...
Since with () overloading class objects can now look like functions, I've
been toying with the idea of using this for formatted I/O. Here's a trial
mockup of what it might look like:

-----------------------------------------------
import std.string;
import std.c.stdio;
import std.c.stdlib;

class Stdout
{
Stdout opCall(int i)
{
printf("%d", i);
return this;
}

Stdout opCall(char[] format, ...)
{
va_list ap;
ap = cast(va_list)&format;
ap += format.size;
vprintf(format, ap);
return this;
}

Stdout nl()
{
printf("\n");
return this;
}
}

void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}
-------------------------------------------

(Note that it retains the power of printf!) The issue here is how the

stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.

Nov 05 2003
"Walter" <walter digitalmars.com> writes:
"Jonathan Andrew" <Jonathan_member pathlink.com> wrote in message
news:bocl5e$21g8$1 digitaldaemon.com...
Also, would it make sense to
declare Stdout
static in stdio so you don't need to instantiate it each time?

Yes, of course. There'd be an abstract class forming the base of it, then there'd be Stdout deriving from it and sending its output to the console. stdout would be some global static. There'd also be another derivation from the base class which would enable buffered output to a file, and output to a string, etc. I can make all that work, so the question is do people like the ()() approach, or does it just stink? Andy suggests using ~ instead, that certainly has an appeal, but I'm a bit concerned though about sinking into the C++ << quagmire <G>.
Nov 05 2003
Helmut Leitner <helmut.leitner wikiservice.at> writes:
Walter wrote:
I can make all that work, so the question is do people like the ()()
approach, or does it just stink? Andy suggests using ~ instead, that
certainly has an appeal, but I'm a bit concerned though about sinking into
the C++ << quagmire <G>.

I dislike both, especially the ~. If you use the ()() syntax, then it must be a general language feature, that can be used for any function, e. g. MoveTo(x1,y1); DrawTo(x2,y1)(x2,y2)(x1,y2)(x1,y1); If it is that way, it may be ok. It won't hurt, if it isn't used with io in the end. If it is only usable with opCall, then it is an ugly hack. On the other hand it doesn't solve the inefficiency problem of "C++ <<", effecitivly producing a flood of func(this,fmt[,type]) calls. And it is not searchable. And what is the advantage over: stream.print(...)(...)(...); ? Even if you do this, these are still open problems - to pass a variable number of arguments safely - to get a generic interface to pass - any arry => ArrayInfoStruct - any primitive (now "Type", should be "Prim[itive]") => PrimInfoStruct - any object, array or primitive => TypeInfoStruct It would be no good to fix the io problem without taking these into account. -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
Nov 05 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
Any function that returns itself should work like that, but how the heck
would you specify the signature of a function that returns itself?!?

(int,int)(*)(int,int)(*)(int,int)(*)(int,int)(*)(int,int)(*)(int,int)
DrawTo(int x,int y) { Line(opx,opy,x,y); opx = x; opy = y; return DrawTo; }

It doesn't even seem that typedef will help here.

Sean

"Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
news:3FA9F16C.9DF16013 wikiservice.at...
Walter wrote:
I can make all that work, so the question is do people like the ()()
approach, or does it just stink? Andy suggests using ~ instead, that
certainly has an appeal, but I'm a bit concerned though about sinking

the C++ << quagmire <G>.

I dislike both, especially the ~. If you use the ()() syntax, then it must be a general language feature, that can be used for any function, e. g. MoveTo(x1,y1); DrawTo(x2,y1)(x2,y2)(x1,y2)(x1,y1); If it is that way, it may be ok. It won't hurt, if it isn't used with io

If it is only usable with opCall, then it is an ugly hack.

On the other hand it doesn't solve the inefficiency problem of "C++ <<",
effecitivly producing a flood of
func(this,fmt[,type])
calls.

And it is not searchable.

And what is the advantage over:
stream.print(...)(...)(...);
?

Even if you do this, these are still open problems
- to pass a variable number of arguments safely
- to get a generic interface to pass
- any arry                                             =>

- any primitive (now "Type", should be "Prim[itive]")  =>

- any object, array or primitive                       =>

It would be no good to fix the io problem without taking these into
account.

--
Helmut Leitner    leitner hls.via.at
Graz, Austria   www.hls-software.com

Nov 06 2003
"Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <palmer.sean verizon.net> wrote in message
news:boe65h$19t4$1 digitaldaemon.com...
Any function that returns itself should work like that, but how the heck
would you specify the signature of a function that returns itself?!?

You can't. But you *can* make it work with a so-called function object, which is an object with the () operator overloaded. This works now in D.
Nov 08 2003
"Walter" <walter digitalmars.com> writes:
"Helmut Leitner" <helmut.leitner wikiservice.at> wrote in message
news:3FA9F16C.9DF16013 wikiservice.at...
Walter wrote:
I can make all that work, so the question is do people like the ()()
approach, or does it just stink? Andy suggests using ~ instead, that
certainly has an appeal, but I'm a bit concerned though about sinking

the C++ << quagmire <G>.

Ok.
If you use the ()() syntax, then it must be a general language feature,
that can be used for any function, e. g.

MoveTo(x1,y1);
DrawTo(x2,y1)(x2,y2)(x1,y2)(x1,y1);

If it is that way, it may be ok. It won't hurt, if it isn't used with io

If it is only usable with opCall, then it is an ugly hack.

It won't work at all with functions, but it will work with function objects (i.e. opCall).
On the other hand it doesn't solve the inefficiency problem of "C++ <<",
effecitivly producing a flood of
func(this,fmt[,type])
calls.

I'm not sure why C++'s way fares so poorly. What it won't need to do is have a specialized parser for printf's format string, which takes time.
And it is not searchable.

It is by searching for 'stdout'.
And what is the advantage over:
stream.print(...)(...)(...);
?

()() won't work with plain old functions.
Even if you do this, these are still open problems
- to pass a variable number of arguments safely

Use (var1)(var2)(var3) etc.
- to get a generic interface to pass
- any arry                                             =>

- any primitive (now "Type", should be "Prim[itive]")  =>

- any object, array or primitive                       =>

It would be no good to fix the io problem without taking these into
account.

Yes, that needs work.
Nov 08 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:bojg4f$2qpr$1 digitaldaemon.com...
On the other hand it doesn't solve the inefficiency problem of "C++ <<",
effecitivly producing a flood of
func(this,fmt[,type])
calls.

I'm not sure why C++'s way fares so poorly. What it won't need to do is

a specialized parser for printf's format string, which takes time.

We went over a way to reduce that inefficiency at one point. We actually did measure considerable overhead in the printf string parsing, in our game at one point, the font drawing function was routing everything thru sprintf. The signature of the draw function was: void Font::Draw(Vc3, Color, char const*, ...); When we changed Font().Draw(Vc3(40,50), Color::red, "My big long string"); to: Font().Draw(Vc3(40,50), Color::red, "%s", "My big long string"); we got a huge savings. Sean
Nov 09 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
"Walter" <walter digitalmars.com> wrote in message
news:bocp61$27of$1 digitaldaemon.com...
"Jonathan Andrew" <Jonathan_member pathlink.com> wrote in message
news:bocl5e$21g8$1 digitaldaemon.com...
Also, would it make sense to
declare Stdout
static in stdio so you don't need to instantiate it each time?

Yes, of course. There'd be an abstract class forming the base of it, then there'd be Stdout deriving from it and sending its output to the console. stdout would be some global static. There'd also be another derivation

the base class which would enable buffered output to a file, and output to

string, etc.

I can make all that work, so the question is do people like the ()()
approach, or does it just stink? Andy suggests using ~ instead, that
certainly has an appeal, but I'm a bit concerned though about sinking into
the C++ << quagmire <G>.

It's ugly, but at least it's not (mis)using operators. I take it that the reason you want to use it is because it will do an atomic write with a result of all the individual expressions?
Nov 05 2003
"Walter" <walter digitalmars.com> writes:
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:bocre8$2avm$1 digitaldaemon.com...
I take it that the reason you want to use it is because it will do an

write with a result of all the individual expressions?

I like it because it can work without double buffering of the intermediate results. It can be as efficient as printf().
Nov 08 2003
Andy Friesen <andy ikagames.com> writes:
Walter wrote:

Since with () overloading class objects can now look like functions, I've
been toying with the idea of using this for formatted I/O. Here's a trial
mockup of what it might look like:

[...]

(Note that it retains the power of printf!) The issue here is how the syntax
stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.

I think () is a bit too busy. '~' may be better, since it's a lot less hoggish in terms of eyeball-space. Plus, D already uses it to indicate concatenation. stdout ~ "Hello " ~ "world" ~ 47 ~ endl ~ "bar" ~ format("%06i\n", 62); -- andy
Nov 05 2003
Andy Friesen wrote:

[snip]

I think () is a bit too busy.  '~' may be better, since it's a lot
less hoggish in terms of eyeball-space.  Plus, D already uses it to
indicate concatenation.

stdout ~ "Hello " ~ "world" ~ 47 ~ endl ~ "bar" ~ format("%06i\n", 62);

-- andy

you've got bidirectional streams how would that be handled?
Nov 05 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
More operating overloading gunk. Hate it hate it hate it. Once again the
evil zombie iostreams are sent to plague us, just wearing another head

Gilbert Grump

"Andy Friesen" <andy ikagames.com> wrote in message
news:bocnlc$25gn$1 digitaldaemon.com...
Walter wrote:

been toying with the idea of using this for formatted I/O. Here's a

mockup of what it might look like:

[...]

(Note that it retains the power of printf!) The issue here is how the

stdout("foo")("bar") looks. In C++ it would look like

which I don't find appealing.

I think () is a bit too busy. '~' may be better, since it's a lot less hoggish in terms of eyeball-space. Plus, D already uses it to indicate concatenation. stdout ~ "Hello " ~ "world" ~ 47 ~ endl ~ "bar" ~ format("%06i\n", 62); -- andy

Nov 05 2003
Andy Friesen <andy ikagames.com> writes:
Matthew Wilson wrote:
More operating overloading gunk. Hate it hate it hate it. Once again the
evil zombie iostreams are sent to plague us, just wearing another head

Gilbert Grump

Yup. But the reason I use printf instead of std::stringstream isn't any asthetic aversion to using << to indicate redirection. It's not because I think it's cryptic either. I've never known stream twiddling to ever reach that sort of complexity, and I've never needed to do bit shifting in the middle of stream in/output. I simply don't like how verbose things get when you start to do more complicated formatting. It's a pain to type and look at. I don't think that operator() is any better in that regard, though I suppose it is less arbitrary in nature. (caveat: opCall can accept any number of arguments; formatting could be much simpler than with any binary operator) Maybe D just needs some (completely insane) way to overload the comma operator and translate what looks like a single varargs method call into a series of monadic calls. Maybe not. -- andy
Nov 06 2003
Hauke Duden <H.NS.Duden gmx.net> writes:
Andy Friesen wrote:
Maybe D just needs some (completely insane) way to overload the comma
operator and translate what looks like a single varargs method call into
a series of monadic calls.  Maybe not.

Maybe D only needs a way to pass a variable number of arguments in a type-safe way. That would solve all problems of printf, since printf could always find out what was actually passed to it. Since D objects are always passed by reference only this problem is actually a little easier to solve than in C++. Howsabout the following: void print(char[] formatstring, vararglist args ); vararglist would be a special internal type that the compiler recognizes. Instead of just pushing all arguments onto the stack the compiler internally creates an array of structs of the following form (the implementation should probably be hidden from the programmer): struct vararg { int type; //type-info pointer?? TYPE arg; }; type could be a special value indicating whether it is a simple type (int, double, etc.) or an object reference. The class of the object would not have to be included, since objects in D already have runtime type information. The only problem I see with this are structs and pointers to structs. Does the compiler automatically generate some kind of typeinfo structure for each struct? If it does then vararg could simply include a pointer to that typeinfo and the called function could find out what kind of struct was passed. Another alternative, of course, would be to not allow structs to be passed to such a function. Anyway, provided that the struct problem is solved somehow then on the called side everything could be typesafe. A vararglist object could behave like some kind of iterator or cursor: void print(char[] formatstring, vararglist args) { while(args.next()) { if(args.isInt()) { int val=args.getInt(); //throws exception if //not an int or compatible type } else if(args.isObject()) { Object obj=args.getObject(); //throws an //exception if not an object } ... } } Hauke
Nov 06 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
Why not implement it like this?:

void print(... args)
{
foreach(v in args)
v.print(stdout);
}

Every type then would be required to provide a print function to a stream.
There could be several such functions (auto-generated if not explicitly
provided, of course) that read and write to/from text or binary streams.
The auto-generated functions would perhaps just call the base class function
then print the new members.

Sean

"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:bodopv$lfe$1 digitaldaemon.com...
Andy Friesen wrote:
Maybe D just needs some (completely insane) way to overload the comma
operator and translate what looks like a single varargs method call into
a series of monadic calls.  Maybe not.

Maybe D only needs a way to pass a variable number of arguments in a type-safe way. That would solve all problems of printf, since printf could always find out what was actually passed to it. Since D objects are always passed by reference only this problem is actually a little easier to solve than in C++. Howsabout the following: void print(char[] formatstring, vararglist args ); vararglist would be a special internal type that the compiler recognizes. Instead of just pushing all arguments onto the stack the compiler internally creates an array of structs of the following form (the implementation should probably be hidden from the programmer): struct vararg { int type; //type-info pointer?? TYPE arg; }; type could be a special value indicating whether it is a simple type (int, double, etc.) or an object reference. The class of the object would not have to be included, since objects in D already have runtime type information. The only problem I see with this are structs and pointers to structs. Does the compiler automatically generate some kind of typeinfo structure for each struct? If it does then vararg could simply include a pointer to that typeinfo and the called function could find out what kind of struct was passed. Another alternative, of course, would be to not allow structs to be passed to such a function. Anyway, provided that the struct problem is solved somehow then on the called side everything could be typesafe. A vararglist object could behave like some kind of iterator or cursor: void print(char[] formatstring, vararglist args) { while(args.next()) { if(args.isInt()) { int val=args.getInt(); //throws exception if //not an int or compatible type } else if(args.isObject()) { Object obj=args.getObject(); //throws an //exception if not an object } ... } } Hauke

Nov 06 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
You lose atomicity of write.

"Sean L. Palmer" <palmer.sean verizon.net> wrote in message
news:boe43g$16ri$1 digitaldaemon.com...
Why not implement it like this?:

void print(... args)
{
foreach(v in args)
v.print(stdout);
}

Every type then would be required to provide a print function to a stream.
There could be several such functions (auto-generated if not explicitly
provided, of course) that read and write to/from text or binary streams.
The auto-generated functions would perhaps just call the base class

then print the new members.

Sean

"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:bodopv$lfe$1 digitaldaemon.com...
Andy Friesen wrote:
Maybe D just needs some (completely insane) way to overload the comma
operator and translate what looks like a single varargs method call

a series of monadic calls.  Maybe not.

Maybe D only needs a way to pass a variable number of arguments in a type-safe way. That would solve all problems of printf, since printf could always find out what was actually passed to it. Since D objects are always passed by reference only this problem is actually a little easier to solve than in C++. Howsabout the following: void print(char[] formatstring, vararglist args ); vararglist would be a special internal type that the compiler recognizes. Instead of just pushing all arguments onto the stack the compiler internally creates an array of structs of the following form (the implementation should probably be hidden from the programmer): struct vararg { int type; //type-info pointer?? TYPE arg; }; type could be a special value indicating whether it is a simple type (int, double, etc.) or an object reference. The class of the object would not have to be included, since objects in D already have runtime type information. The only problem I see with this are structs and pointers to structs. Does the compiler automatically generate some kind of typeinfo structure for each struct? If it does then vararg could simply include a pointer to that typeinfo and the called function could find out what kind of struct was passed. Another alternative, of course, would be to not allow structs to be passed to such a function. Anyway, provided that the struct problem is solved somehow then on the called side everything could be typesafe. A vararglist object could behave like some kind of iterator or cursor: void print(char[] formatstring, vararglist args) { while(args.next()) { if(args.isInt()) { int val=args.getInt(); //throws exception if //not an int or compatible type } else if(args.isObject()) { Object obj=args.getObject(); //throws an //exception if not an object } ... } } Hauke

Nov 06 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
That is not a problem.  It's "writing" directly into the stream's buffer.
The actual write happens upon buffer flushes.

Sean

"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:boec1l$1j08$2 digitaldaemon.com...
You lose atomicity of write.

"Sean L. Palmer" <palmer.sean verizon.net> wrote in message
news:boe43g$16ri$1 digitaldaemon.com...
Why not implement it like this?:

void print(... args)
{
foreach(v in args)
v.print(stdout);
}

Every type then would be required to provide a print function to a

There could be several such functions (auto-generated if not explicitly
provided, of course) that read and write to/from text or binary streams.
The auto-generated functions would perhaps just call the base class

then print the new members.

Sean

Nov 09 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
What is so evil about it?

What is more evil:

Pascal:   WriteLn("foo", ' ', bar);
C:  printf("%s%c%i\n","foo",' ',bar);
C++:  cout << "foo" << ' ' << bar << endl;
BASIC:  print "foo", " ", %bar, chr(13)

D proposal #1:  stdout("foo")(' ')(bar)(endl);
D proposal #2:  stdout ~ "foo" ~ ' ' ~ bar ~ endl;

Why would you think commas are so much better than tildes or parens?

I can see tilde being confused with the array concatenation operator.

Parens are not confusing at all, once you get used to the chained call
style.

Commas are confusing too because of the comma operator that C,C++, and D all
share.

Sean

"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:bocr93$2am6$2 digitaldaemon.com...
More operating overloading gunk. Hate it hate it hate it. Once again the
evil zombie iostreams are sent to plague us, just wearing another head

Gilbert Grump

Nov 06 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
What is more evil:

Pascal:   WriteLn("foo", ' ', bar);
C:  printf("%s%c%i\n","foo",' ',bar);
C++:  cout << "foo" << ' ' << bar << endl;        ** This one
BASIC:  print "foo", " ", %bar, chr(13)

D proposal #1:  stdout("foo")(' ')(bar)(endl);
D proposal #2:  stdout ~ "foo" ~ ' ' ~ bar ~ endl;        ** This one

Why would you think commas are so much better than tildes or parens?

I don't
I can see tilde being confused with the array concatenation operator.

Indeed. That is one of the objections to it
Parens are not confusing at all, once you get used to the chained call
style.

Indeed. That is preferable, as I think I've indicated already in this thread
Commas are confusing too because of the comma operator that C,C++, and D

share.

Agreed
Nov 06 2003
Ilya Minkov <midiclub tiscali.de> writes:
Matthew Wilson wrote:

I can see tilde being confused with the array concatenation operator.

Indeed. That is one of the objections to it

Why "confused"? It's actually the maning of it! Look. If you have an output, you are actually concatenating stuff to it. Especially if it is a file. Or even if it is a console the paradigm works well enough. It doesn't make so much sense with inputs though. I think we need something like operator : or :: on them, which could also be used for list separation? Sather uses a notation like this #OUT + "this " + 123 + " that"; It actually creates an anonymous object of class OUT and calls an add method of it. Considering that adding is Sather's way of concatenating stuff, it's basically the same idea. The operator itself simply does the output, and then passes the OUT further. -eye
Nov 07 2003
"Jeandré du Toit" <morphiax hotmail.com> writes:

MessageBox.Show("NumTwo is {1} and NumOne {0} and both are {0}{1}", NumOne,
NumTwo);

"Sean L. Palmer" <palmer.sean verizon.net> wrote in message
news:boe3nb$16a7$1 digitaldaemon.com...
What is so evil about it?

What is more evil:

Pascal:   WriteLn("foo", ' ', bar);
C:  printf("%s%c%i\n","foo",' ',bar);
C++:  cout << "foo" << ' ' << bar << endl;
BASIC:  print "foo", " ", %bar, chr(13)

Nov 08 2003
In article <boc9me$1g2b$1 digitaldaemon.com>, Walter says...
[...]
void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}

if I understand, this would be equivalent to: stdout.opCall("hello").opCall(" world").opCall(47).nl().opCall("bar").opCall("%06i\n", 62); Right?
(Note that it retains the power of printf!)

so this: stdout("I am 50% stupid?"); generates a segmentation fault?
The issue here is how the syntax
stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.

I like <<, I like (), I like ~ (althouhg I haven't ~ on my keyboard). Ciao
Nov 05 2003
Hauke Duden <H.NS.Duden gmx.net> writes:
Roberto Mariottini wrote:
althouhg I haven't ~ on my keyboard).

That's important! VERY important. If ~ is not on all keyboards, then IMHO it shouldn't be a built-in operator at all. What kind of keyboard is this? Hauke
Nov 06 2003
In article <bod2or$2mnk$1 digitaldaemon.com>, Hauke Duden says...
Roberto Mariottini wrote:
althouhg I haven't ~ on my keyboard).

That's important! VERY important. If ~ is not on all keyboards, then IMHO it shouldn't be a built-in operator at all. What kind of keyboard is this?

Italian keyboard. For sure every one of the 56 millions of italians has to use the Alt-126 combination to enter a single ~. We also have no {}, but the undocumented AltGr-Shift-[ and AltGr-Shift-] cobinations fortunately work in any italian keyboard Windows driver, although I see many of my collegues using Alt-123 and Alt-125. Old italian hackers use USA keyboards, but not all employers agree to buy one for every developer. Ciao
Nov 06 2003
"Jan-Eric Duden" <jeduden whisset.com> writes:
OMG. I didn't think it is possible that { and } can be omitted on a keyboard
layout....

--
Jan-Eric Duden
"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message
news:bod3l8$2o2j$1 digitaldaemon.com...
In article <bod2or$2mnk$1 digitaldaemon.com>, Hauke Duden says...
Roberto Mariottini wrote:
althouhg I haven't ~ on my keyboard).

That's important! VERY important. If ~ is not on all keyboards, then IMHO it shouldn't be a built-in operator at all. What kind of keyboard is this?

Italian keyboard. For sure every one of the 56 millions of italians has to use the Alt-126 combination to enter a single ~. We also have no {}, but the undocumented AltGr-Shift-[ and AltGr-Shift-] cobinations fortunately work in any italian keyboard Windows driver,

see many of my collegues using Alt-123 and Alt-125.

Old italian hackers use USA keyboards, but not all employers agree to buy

for every developer.

Ciao

Nov 06 2003
Ilya Minkov <midiclub tiscali.de> writes:
I've looked at it and i find the italian keyboard very wierd. It is
underpopulated in some spots and overpopulated in the others. Bad
design. It also doesn't have a backquote, which is even present on
hebrew, russian, and all other fancy keyboars i've ever seen - and which
is requiered by some programming languages as well, most notably lisp.
And UNIX simply doesn't work without ~.

You can use a keyboard layout editor. Under Windows i use KLM Medium:

http://www.klm.freeservers.com/

However, it costs more than a US keyboard.

Another sane solution would be a program which would be a resident and
listen to a magic key combination, and then pastes the symbol into the
program. Or even a widows shortcut with a hotkey to call a small program
which would only paste a symbol into an active program...

-eye

Roberto Mariottini wrote:

Italian keyboard.
For sure every one of the 56 millions of italians has to use the Alt-126
combination to enter a single ~.
We also have no {}, but the undocumented AltGr-Shift-[ and AltGr-Shift-]
cobinations fortunately work in any italian keyboard Windows driver, although I
see many of my collegues using Alt-123 and Alt-125.

Old italian hackers use USA keyboards, but not all employers agree to buy one
for every developer.

Ciao

Nov 06 2003
"Walter" <walter digitalmars.com> writes:
"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message
news:bod3l8$2o2j$1 digitaldaemon.com...
Old italian hackers use USA keyboards, but not all employers agree to buy

for every developer.

I hate to be annoying <g>, but a USA keyboard can be had for $9.99 around here. Mine cost$19.99, but that's only because I just cannot stand the oversized Enter key that substitutes for the \ key. Every time I hit \, I get Enter instead and the command gets prematurely executed, sometimes with disastrous results: rm -r foo\bar becomes: rm -r foo Argggh! Why can't these layouts be standardized? C++ tried to get around the keyboard problem by introducing digraphs. When that failed, trigraphs were introduced. That's failed too, and now there's \uxxxx, etc. (By failed I mean that I see a lot of code from all over the world, and never once have I seen any code outside of a test suite that used digraphs, trigraphs, or \u or \U.) The C/C++ experiments with this show that there isn't a known decent solution. What I do to input funky characters is cut & paste them from a palette of them.
Feb 20 2004
Vathix <vathix dprogramming.com> writes:
I hate to be annoying <g>, but a USA keyboard can be had for $9.99 around here. Mine cost$19.99, but that's only because I just cannot stand the
oversized Enter key that substitutes for the \ key. Every time I hit \, I
get Enter instead and the command gets prematurely executed, sometimes with
disastrous results:

I have that large Enter. What used to bug me is backspace being smaller and me constantly bumping the insert key; that is, until I pulled the key out :D -- Christopher E. Miller www.dprogramming.com irc.dprogramming.com #D
Feb 21 2004
"Ben Hinkle" <bhinkle4 juno.com> writes:
| What I do to input funky characters is cut & paste them from a
| palette of them.

I know what you mean - the old Mac's MPW environment used greek
deltas (option-D) in scripts for line-continuation. There were
a few times when I found myself editing a script on a wacky
keyboard and could only wrap lines by cutting and pasting these
darn deltas from somewhere else. MPW loved that option key.

-Ben
Feb 21 2004
Hi,
the following example shows why you can't have only one

Stdout opCall(char[] format, ...)

to handle all strings output, but you must have one opCall with only one string
as parameter.

Works with:
Digital Mars Compiler Version 8.29n
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 12.00.8804 for 80x86

It doesn't work well with Borland compiler, gcc generates a segfault.

------------------------test.c----------------------------
#include <stdio.h>

char *s = "%%% stupid, not stupid %%%";

int f(char *m)
{
return m[15] = 0;
}

int main()
{
char *p = s+ 2;
f(p);
printf("I am 100% sane at all.\n");

return 0;
}
------------------------test.c----------------------------

Ciao
Nov 07 2003
"Ben Hinkle" <bhinkle4 juno.com> writes:
This got me thinking about message chaining in Object C and SmallTalk (or
Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or is
implementable ;-)
-Ben

"Walter" <walter digitalmars.com> wrote in message
news:boc9me$1g2b$1 digitaldaemon.com...
Since with () overloading class objects can now look like functions, I've
been toying with the idea of using this for formatted I/O. Here's a trial
mockup of what it might look like:

-----------------------------------------------
import std.string;
import std.c.stdio;
import std.c.stdlib;

class Stdout
{
Stdout opCall(int i)
{
printf("%d", i);
return this;
}

Stdout opCall(char[] format, ...)
{
va_list ap;
ap = cast(va_list)&format;
ap += format.size;
vprintf(format, ap);
return this;
}

Stdout nl()
{
printf("\n");
return this;
}
}

void main()
{  Stdout stdout = new Stdout();
stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
}
-------------------------------------------

(Note that it retains the power of printf!) The issue here is how the

stdout("foo")("bar") looks. In C++ it would look like stdout<<"foo"<<"bar"
which I don't find appealing.

Nov 06 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
This got me thinking about message chaining in Object C and SmallTalk (or
Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or is
implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you) syntax is that the write operation would be atomic, which would certainly need to be the case to system streams such as the log stream, and to process-wide streams in a multi-threaded process. If your example translates to a function that does that, by concatenating all input in a buffer, and then sending that to the requisite output stream in a single operation, then I would think it worth pursuing.
Nov 06 2003
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Matthew Wilson wrote:
This got me thinking about message chaining in Object C and SmallTalk (or
Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or is
implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you) syntax is that the write operation would be atomic, which would certainly need to be the case to system streams such as the log stream, and to process-wide streams in a multi-threaded process.

printf() is not atomic, I believe. write() generally is, I think. But printf() buffers output until either the buffer fills up or you call fflush(). So why are you arguing about the atomicity of print mechanisms? If atomicity is critical, form your own buffer and then use write() directly.
Nov 06 2003
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boedmk$1l44$1 digitaldaemon.com...
Matthew Wilson wrote:
This got me thinking about message chaining in Object C and SmallTalk

Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or

implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you)

is that the write operation would be atomic, which would certainly need

be the case to system streams such as the log stream, and to

streams in

printf() is not atomic, I believe. write() generally is, I think. But printf() buffers output until either the buffer fills up or you call fflush(). So why are you arguing about the atomicity of print mechanisms? If atomicity is critical, form your own buffer and then use write() directly.

Fair enough. My ineptly using printf as an example does not negate the point, however.
Nov 06 2003
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Matthew Wilson wrote:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:boedmk$1l44$1 digitaldaemon.com...

Matthew Wilson wrote:

This got me thinking about message chaining in Object C and SmallTalk

(or
Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or

is
implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you)

syntax
is that the write operation would be atomic, which would certainly need

to
be the case to system streams such as the log stream, and to

process-wide
streams in

printf() is not atomic, I believe. write() generally is, I think. But printf() buffers output until either the buffer fills up or you call fflush(). So why are you arguing about the atomicity of print mechanisms? If atomicity is critical, form your own buffer and then use write() directly.

Fair enough. My ineptly using printf as an example does not negate the point, however.

I hear you, but I don't think that atomic writes are a big requirement for a general-purpose formatted I/O routine. Once the routine is in place, you can use the syntax (whatever it happens to be) to build a buffer in memory, something like: Stream str = new BufStream; str <insert the formatting syntax here>; write(file_pointer, str);
Nov 06 2003
Ilya Minkov <midiclub tiscali.de> writes:
Russ Lewis wrote:

I hear you, but I don't think that atomic writes are a big requirement
for a general-purpose formatted I/O routine.  Once the routine is in
place, you can use the syntax (whatever it happens to be) to build a
buffer in memory, something like:

Stream str = new BufStream;
str <insert the formatting syntax here>;
write(file_pointer, str);

IIRC that's what Walter wanted to avoid forcing on the user, for efficiency reasons. He wants whatever system D has to be at least as efficient as printf. Not a basic requierement for the IO system IMHO - that's what the same write is for. A basic requierement is typesafety, extensibility, and ease of use even for beginners. C++ iostreams serve these requierements wonderfully well. -eye
Nov 07 2003
Hauke Duden <H.NS.Duden gmx.net> writes:
Ilya Minkov wrote:
I hear you, but I don't think that atomic writes are a big requirement
for a general-purpose formatted I/O routine.  Once the routine is in
place, you can use the syntax (whatever it happens to be) to build a
buffer in memory, something like:

Stream str = new BufStream;
str <insert the formatting syntax here>;
write(file_pointer, str);

IIRC that's what Walter wanted to avoid forcing on the user, for efficiency reasons. He wants whatever system D has to be at least as efficient as printf. Not a basic requierement for the IO system IMHO - that's what the same write is for. A basic requierement is typesafety, extensibility, and ease of use even for beginners. C++ iostreams serve these requierements wonderfully well.

I just had an idea to create an atomic version of the proposed print with the same syntax. Couldn't the first atomicPrint call return an auto object (like the BufStream mentioned above) that itself works in the same way as the proposed StdIO object? It would accumulate the following print calls and output the resulting string when its destructor is called. Essentially this would be the same as using a temporary Stream object, except that the user would not have to create it explicitly. Not sure whether auto-objects can be returned from a function, though. My intuition tells me probably not, but I'll would have to try it out... Hauke
Nov 07 2003
"Ben Hinkle" <bhinkle4 juno.com> writes:
"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:boec1m$1j08$3 digitaldaemon.com...
This got me thinking about message chaining in Object C and SmallTalk

Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or

implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you) syntax is that the write operation would be atomic, which would certainly need to be the case to system streams such as the log stream, and to process-wide streams in a multi-threaded process. If your example translates to a function that does that, by concatenating all input in a buffer, and then sending that to the requisite output

in a single operation, then I would think it worth pursuing.

I hadn't thought about that. Reading my post again (aside from the fact that I can't spell "Objective" before my first cup of coffee) I also see I was assuming strings were class objects and not plain arrays. I'll ponder some more about the atomic stuff and about cascading non-member functions. -Ben
Nov 06 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
There are equally as many cases where you *don't* want the output to be
atomic.  It is slower to write into this temporary buffer, before sending
the final buffer to the stream, than to write directly into the stream's
buffer.  Besides, you don't usually know how big of a buffer you're going to
need before you start writing.

Streams are always buffered, right?  If so there's a nice Flush() command
somewhere.

Unbuffered streams are horribly inefficient.

Sean

"Matthew Wilson" <matthew-hat -stlsoft-dot.-org> wrote in message
news:boec1m$1j08$3 digitaldaemon.com...
This got me thinking about message chaining in Object C and SmallTalk

Maybe a whole new syntax could help and possibly replace printf and ~.
Something like

stdout.printf["hello", " world", 47, "\nbar", ("%06i\n", 62)];
string.cat["a", "bc", 47, "def"];

would turn into

stdout.printf("hello").printf("
world").printf(47).printf("\nbar").printf("%06i\n", 62);
string.cat("a").cat("bc").cat(47).cat("def");

I haven't thought about if this syntax conflicts with anything else or

implementable ;-)
-Ben

I think the point of the concatenated (not concatenating, mind you) syntax is that the write operation would be atomic, which would certainly need to be the case to system streams such as the log stream, and to process-wide streams in a multi-threaded process. If your example translates to a function that does that, by concatenating all input in a buffer, and then sending that to the requisite output

in a single operation, then I would think it worth pursuing.

Nov 09 2003
Why not make IO a more formal operation.

Introduce a new keyword "write"

Syntax: write object, param [,param]*;

Example:

float a = 12.4;
write stdOut,"Hello ",12,.format(4,2,a)," amount";

Any "." preceeded name is considers a function of
the object.

The object has opWrite functions.

class StdOut
{
opWrite(char[]) { }
opWrite(int) { }
opWrite(float) { }

format(int digits,int postDigits, float value);
}

Read is handled in a similar way.

Example:

class StdIn
{
//etc...
}
Nov 06 2003
"Sean L. Palmer" <palmer.sean verizon.net> writes:
Because typesafe varargs is useful for lots of things besides I/O.

Sean

"Patrick Down" <Patrick_member pathlink.com> wrote in message
news:boe5fs$18se$1 digitaldaemon.com...
Why not make IO a more formal operation.

Introduce a new keyword "write"

Syntax: write object, param [,param]*;

Nov 09 2003
"Carlos Santander B." <carlos8294 msn.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:boc9me$1g2b$1 digitaldaemon.com...
| ...
|     stdout("hello")(" world")(47).nl()("bar")("%06i\n", 62);
| ...

Personally, I don't like so many (). ~ feels a bit better. However, I agree
that true typesafe varargs would be the ideal solution for this.

—————————————————————————
Carlos Santander

---

Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.536 / Virus Database: 331 - Release Date: 2003-11-03
Nov 06 2003