## 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
Kazuhiro Inaba <Kazuhiro_member pathlink.com> writes:
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:
What about this syntax:

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

Then, the class would have multiple overloaded overloadings of the ~
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);

Then, the class would have multiple overloaded overloadings of the ~
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);

Then, the class would have multiple overloaded overloadings of the ~
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);

Then, the class would have multiple overloaded overloadings of the ~
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);

Then, the class would have multiple overloaded overloadings of the ~
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...
Since with () overloading class objects can now look like functions,

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
J Anderson <REMOVEanderson badmama.com.au> writes:
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
J Anderson <REMOVEanderson badmama.com.au> 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
"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
Roberto Mariottini <Roberto_member pathlink.com> writes:
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:
I'm not buying into your dogma.

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:
 I'm not buying into your dogma.

Probably wise, as I think I had my Devil's Advocate head on in this
discussion

Nov 09 2003
Dario <Dario_member pathlink.com> writes:
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

I'll try to write something that works...
Dario

Nov 06 2003
Dario <Dario_member pathlink.com> writes:
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
Dario <Dario_member pathlink.com> writes:
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
Jonathan Andrew <Jonathan_member pathlink.com> writes:
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
J Anderson <REMOVEanderson badmama.com.au> writes:
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:

Since with () overloading class objects can now look like functions,

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++.

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++.

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++.

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:
What about C#'s

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
Roberto Mariottini <Roberto_member pathlink.com> writes:
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
Roberto Mariottini <Roberto_member pathlink.com> writes:
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
Roberto Mariottini <Roberto_member pathlink.com> writes:
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

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

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

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

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
Patrick Down <Patrick_member pathlink.com> writes:
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:

read stdIn, a, b, c;

class StdIn
{
opRead(out char[]) { }
//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
Matthias Becker <Matthias_member pathlink.com> writes:
This all doesn't help me, to output objects of my own classes, does it?

Nov 16 2003
Jan Knepper <jan smartsoft.us> writes:
Walter wrote:

(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.

stdout << "foo" << "bar";

Does indeed not loop very appealing. I personally would have liked better:

stdout << "foo", "bar", i, "\n", "second line", nl;

Jan

Nov 16 2003