## D - variable number of arguments

• EvilOne (3/3) Oct 04 2001 Is there support for variable number of arguments in D? Something
• a (7/11) Oct 04 2001 printf is supported. I would guess that something like C's varargs will
• Walter (3/12) Oct 05 2001 D will support variable arguments, but only in interfacing to C function...
• pontus (9/9) Oct 07 2001 SGVsbG8NCg0KSW4gYSBnZW5lcmFsIHdheSwgY291bGRuJ3QgaXQgYmUgc29sdmVkIGxpa2Ug
• Walter (11/11) Oct 07 2001 The problem is that arguments on the stack can be different sizes.
• Pontus Pihlgren (3/20) Oct 08 2001 Well,maybe i'm missing something, but with a string and an array of
• Axel Kittenberger (20/20) Oct 08 2001 Pontus Pihlgren wrote:
• Walter (10/10) Oct 08 2001 Given:
• Russ Lewis (40/40) Oct 09 2001 What were your (Walter's) thoughts about the recursive scheme I cooked u...
• EvilOne (7/10) Oct 09 2001 [...]
• Russ Lewis (12/17) Oct 09 2001 But then, how would you get it to call
• EvilOne (8/17) Oct 10 2001 printf("value of foo.bar.baz ", foo.bar.baz, "\n");
• nik (26/48) Oct 10 2001 Hello,
• Russ Lewis (30/37) Oct 10 2001 I see your point, and it's valid to think that it's clearer. I disagree...
• a (31/71) Oct 10 2001 cout << "value of my variable: "
• Russ Lewis (23/60) Oct 10 2001 clap,clap,clap. I couldn't have done that. One question...doesn't the ...
• EvilOne (1/2) Oct 10 2001 The question is, what we'll have in D?
• a (55/101) Oct 10 2001 You got me. I tried to convince myself that hex worked like setw() and
• Russ Lewis (45/93) Oct 10 2001 How about:
• a (61/160) Oct 13 2001 Well, at the very least, I'd like to have a toStream method that can
• Russ Lewis (15/59) Oct 13 2001 What if toString had a char[] argument:
• a (52/117) Oct 13 2001 I like this idea. I still don't like %magic, but this improves it a
• Russ Lewis (48/79) Oct 14 2001 The key with strong typing is that you know what you know and you don't ...
• a (62/133) Oct 19 2001 Well are typesafe in that it will always be a descendant of Object.
• Russ Lewis (26/82) Oct 19 2001 Remember that all member functions of classes are automatically virtual ...
• Sean L. Palmer (22/48) Nov 04 2001 I hope the hell somebody goes through D and standardizes capitalization
• a (24/80) Nov 04 2001 The only problem is you have to make sure no character conversion
• Charles Hixson (19/19) Oct 17 2001 Are you implying that .toString() is a "magic method" that will
• Russ Lewis (14/16) Oct 17 2001 We have been using the term "magic" to refer to the printf format
• Reg Whitton (37/47) Oct 11 2001 formatting capabilities of printf. I
"EvilOne" <evilone omen.ru> writes:
```Is there support for variable number of arguments in D? Something
like VB's ParamArray, or maybe another (better?) way... or is this
something that's not going to be the language feature?
```
Oct 04 2001
a <a b.c> writes:
```EvilOne wrote:

Is there support for variable number of arguments in D? Something
like VB's ParamArray, or maybe another (better?) way... or is this
something that's not going to be the language feature?

printf is supported.  I would guess that something like C's varargs will
be supported.  It's a shame that useful (in my mind) features can be
dropped because that are dangerous, but we keep C's varargs (and printf
for that matter).  (I guess this is assuming that varargs must be
supported for printf)  Doesn't var-args rely on macros?

Dan
```
Oct 04 2001
"Walter" <walter digitalmars.com> writes:
```a wrote in message <3BBD3952.29C9B2A4 b.c>...
EvilOne wrote:
Is there support for variable number of arguments in D? Something
like VB's ParamArray, or maybe another (better?) way... or is this
something that's not going to be the language feature?

printf is supported.  I would guess that something like C's varargs will
be supported.  It's a shame that useful (in my mind) features can be
dropped because that are dangerous, but we keep C's varargs (and printf
for that matter).  (I guess this is assuming that varargs must be
supported for printf)  Doesn't var-args rely on macros?

D will support variable arguments, but only in interfacing to C functions.
It's only real use is for printf(), etc.
```
Oct 05 2001
pontus <popi5501 student.uu.se> writes:
```SGVsbG8NCg0KSW4gYSBnZW5lcmFsIHdheSwgY291bGRuJ3QgaXQgYmUgc29sdmVkIGxpa2Ug
dGhpczoNCg0Kdm9pZCBwcmludGYoImZvcm1hdCBzdHJpbmciLCAqdm9pZFtdKTsNCg0KVGhh
dCBpcyBhbiBhcnJheSB3aXRoIHBvaW50ZXJzKGhvcGUgaSBnb3QgdGhlIHN5bnRheCByaWdo
dCkuIEFuZCBzaW5jZSBhcnJheQ0KbGVuZ2h0cyBhcmUgYSBwcm9wZXJ0eSBvZiBhcnJheSB0
aGlzIHdvdWxkIGJlIGFuIGVhc3kgdGhpbmcgdG8gaW1wbGVtZW50Lg0KQSBvYnZpb3VzIHBy
b2JsZW0gdGhvdWdoLCBpcyBob3cgd291bGQgeW91IGtub3cgdGhhdCB0aGUgdGhpbmcgcG9p
bnRlZCB0byBhdA0KcGxhY2UgbiBpcyB0aGUgc2FtZSB0eXBlIGFzIGVudGl0eSBuIGluIHRo
ZSBmb3JtYXQgc3RyaW5nLCBidXQgZnJvbSB3aGF0IEkNCmNhbiBzZWUgdGhhdCBpcyBhIHBy
b2JsZW0gd2l0aCB2YXIgYXJncyB0by4NCg0KL1BvbnR1cw0K
```
Oct 07 2001
"Walter" <walter digitalmars.com> writes:
```The problem is that arguments on the stack can be different sizes.

pontus wrote in message <3BC071D5.D574F0AC student.uu.se>...
Hello

In a general way, couldn't it be solved like this:

void printf("format string", *void[]);

That is an array with pointers(hope i got the syntax right). And since array
lenghts are a property of array this would be an easy thing to implement.
A obvious problem though, is how would you know that the thing pointed to at
place n is the same type as entity n in the format string, but from what I
can see that is a problem with var args to.

/Pontus
```
Oct 07 2001
Pontus Pihlgren <popi5501 student.uu.se> writes:
```Well,maybe i'm missing something, but with a string and an array of
pointers, what on the stack have diffrent size?

Walter wrote:

The problem is that arguments on the stack can be different sizes.

pontus wrote in message <3BC071D5.D574F0AC student.uu.se>...
Hello

In a general way, couldn't it be solved like this:

void printf("format string", *void[]);

That is an array with pointers(hope i got the syntax right). And since array
lenghts are a property of array this would be an easy thing to implement.
A obvious problem though, is how would you know that the thing pointed to at
place n is the same type as entity n in the format string, but from what I
can see that is a problem with var args to.

/Pontus

```
Oct 08 2001
Axel Kittenberger <axel dtone.org> writes:
```Pontus Pihlgren wrote:

void myfunc(char a, char b, char);

will possibly put something like this on stack:
+--+--+--+
|  a |  b  |  c |
+--+--+--+

where a, b and c is only one byte long.

Today on almost all 32bit processesor (void *) ist 4 byte long
so *void[3] will look like this
+-----------+-----------+-----------+
|    *void[0]         |    *void[1]         |    *void[2]        |
+-----------+-----------+-----------+

each element is 4 bytes wide, see the difference? and why (void *) can most
times not be used to track function arguments.

It is only possible if the compiler always puts 4 bytes on stack for every
argument even smaller ones, and of course also never bigger ones like 'long
long', but this might be profuseness, however honestly I've no idea how
compilers do today... or how printf("%c%c%c", a, b, c); will be placed on
stack for an x86 processsor, maybe it uses 4 byte frames after all, in
which case a (void **) could actually function...
```
Oct 08 2001
"Walter" <walter digitalmars.com> writes:
```Given:

printf(" ... ", char, int, long long, double, long double);

the compiler pushes on the stack:
char    4
int    4
long long    8
double    8
ld        12

and in general any struct can be passed by value, and can be any (aligned)
size. Every scheme I've come up with to deal with this is inefficient.
```
Oct 08 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```What were your (Walter's) thoughts about the recursive scheme I cooked up?  I
remember other people commented on it, but I don't remember you speaking about
it.

D code:
char[] printf(char[],....)  // declares that variable argument lists are
ok, no body may be defined
out(result)
{
assert(result == "");
};

char[] printf(char[],char) {...};
char[] printf(char[],int) {...};
char[] printf(char[],char[]) {...};
char[] printf(char[],void*) {...};

Each version of printf accepts as its first argument the format string.  It
will throw an exception if the format specifier is invalid for the type.
Otherwise, it does the printing and returns any remaining portion of the
format string.  The compiler expands the variable argument call inline:

D call:
char c; char[] s; int i;
printf("%c %s %d",c,s,i);

Expands to:
char c; char[] s; int i;
printf(printf(printf("%c %s %d",c),s),i);

None of which are variable argument fucntion calls, and all of which are
typesafe.  The innermost printf returns the string "%s %d", while the next
returns "%d", while the last returns "".  Only then is the out condition
checked; it is fine, so the program goes on.

Note that this requires that the 1st argument of the call be the same type as
the return type; anything else would be a syntax error in this scheme.  To
allow multiple fixed arguments, the format is similar:

int foo(int,  // recursive argument
char,void*,char[], // these arguments are all called the same to all
copies of the recursion.
....);  // variable argument.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 09 2001
"EvilOne" <evilone omen.ru> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BC2A336.74A74409 deming-os.org...
What were your (Walter's) thoughts about the recursive scheme I cooked up?  I
remember other people commented on it, but I don't remember you speaking about
it.

[...]

It would be even better if there's a standartized format string, so it
could be generated by D compiler itself by just looking at argument list.
So, you can type:

char c; char[] s;
printf(5, c, s);    // format string will _automatically_ be "%d %c %s"
```
Oct 09 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```EvilOne wrote:

It would be even better if there's a standartized format string, so it
could be generated by D compiler itself by just looking at argument list.
So, you can type:

char c; char[] s;
printf(5, c, s);    // format string will _automatically_ be "%d %c %s"

But then, how would you get it to call
printf("value of foo.bar.baz %d\n", foo.bar.baz);
?

Anyhow, the compiler has all the information it needs to inline as much as it
wants.  It is perfectly
conceivable that the compiler could inline the whole printf function, determine
that there is a problem (and
printf will throw an Exception) and so the compiler could throw a warning.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 09 2001
"EvilOne" <evilone omen.ru> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BC31DC4.83500116 deming-os.org...
EvilOne wrote:

It would be even better if there's a standartized format string, so it
could be generated by D compiler itself by just looking at argument list.
So, you can type:

char c; char[] s;
printf(5, c, s);    // format string will _automatically_ be "%d %c %s"

But then, how would you get it to call
printf("value of foo.bar.baz %d\n", foo.bar.baz);

printf("value of foo.bar.baz ", foo.bar.baz, "\n");

But of course, this is not printf(). So maybe call it print() or writeln()?
Anyhow, I believe that such syntax is much clearer than of C-style printf().
Since there's no operator overloading in D, it's not possible to implement
C++ iostreams with their intuitive usage of << and >>. But there must be
a _simple_ way to perform at least console input and output. printf() is
not the best choice here, imho.
```
Oct 10 2001
nik <no spam.net> writes:
```Hello,

Please excuse me for intruding, but I too have been thinking along the
line of the EvilOne, that:

printf(5, c, s, someObj);
should internally call:
printf( 5.toString(), c.toString(), s.toString(), someObj.toString() );

where the toString() will provide the default formatting.

If one wants different formatting, than that object should override
the only other toString function from the base Object class:

String toString(String fmt);

so now we can have:
printf ( 5, c, s, someObj("-5x") ); // prefer this syntax
or
printf ( 5, c, s, someObj.toString("-5x") ); // ... over this

I would rather have two functions print & println instead of printf, but
thats besides my point.

Also, to fix the vaarg problem, if the syntax
{x, y, z}
creates a collection initialized with the objects x, y, z; then this
should work:
println( { x, y ,z } );
or
println( { "value of foo is", foo("-9.5f") } );

Anyway, just my 2c.

- nik.

EvilOne wrote:

"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BC31DC4.83500116 deming-os.org...
EvilOne wrote:

It would be even better if there's a standartized format string, so it
could be generated by D compiler itself by just looking at argument list.
So, you can type:

char c; char[] s;
printf(5, c, s);    // format string will _automatically_ be "%d %c %s"

But then, how would you get it to call
printf("value of foo.bar.baz %d\n", foo.bar.baz);

printf("value of foo.bar.baz ", foo.bar.baz, "\n");

But of course, this is not printf(). So maybe call it print() or writeln()?
Anyhow, I believe that such syntax is much clearer than of C-style printf().
Since there's no operator overloading in D, it's not possible to implement
C++ iostreams with their intuitive usage of << and >>. But there must be
a _simple_ way to perform at least console input and output. printf() is
not the best choice here, imho.

```
Oct 10 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```EvilOne wrote:

printf("value of foo.bar.baz ", foo.bar.baz, "\n");

But of course, this is not printf(). So maybe call it print() or writeln()?
Anyhow, I believe that such syntax is much clearer than of C-style printf().

I see your point, and it's valid to think that it's clearer.  I disagree :)
For simplistic printing, cout
has some real advantages.  But for complex ones, it really gets weak:

printf("value of my variable: %.8x\n",
foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX());

I would challenge anyone here to write the cout code that matches the
formatting capabilities of printf.  I
would also challenge anybody to write cout code that expresses, as clearly as
the printf format string, how
the stuff will actually look on the screen.

IMHO, printf shines where you need complex formatting and/or the arguments are
complex.

Since there's no operator overloading in D, it's not possible to implement
C++ iostreams with their intuitive usage of << and >>. But there must be
a _simple_ way to perform at least console input and output. printf() is
not the best choice here, imho.

Fair enough.  I like << and >> primarily because of their type-safety (scanf is
HORRID).  However, there is a
lot of elegance to the code:

int i;
cin >> i;

Which is more visual than

int i;
scanf("%d",&i);

Or, what I normally end up doing because I can never remember how scanf works:

int i;
char buf[32];
fgets(buf,32,stdin);
i = atoi(buf);

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 10 2001
a <a b.c> writes:
```Russ Lewis wrote:

EvilOne wrote:

printf("value of foo.bar.baz ", foo.bar.baz, "\n");

But of course, this is not printf(). So maybe call it print() or writeln()?
Anyhow, I believe that such syntax is much clearer than of C-style printf().

I see your point, and it's valid to think that it's clearer.  I disagree :)
For simplistic printing, cout
has some real advantages.  But for complex ones, it really gets weak:

printf("value of my variable: %.8x\n",
foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX());

I would challenge anyone here to write the cout code that matches the
formatting capabilities of printf.

cout << "value of my variable: "
<< setw(8) << hex
<< foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX()
<< endl;

I
would also challenge anybody to write cout code that expresses, as clearly as
the printf format string, how
the stuff will actually look on the screen.

I don't think the above is all that bad really.  As far as clearness,
I've never though all the %magic was really that clear.  It's ugly as
sin to tell the truth.  Of course if you want things to appear in the
code as they would on the screen, we could go back to COBOL picture
statements.  Perl has a similar feature that they are about to rip out
of the perl core.
I'm not against having something like printf in D, but I have two
issues.  It is real nice to be able to define input and output routines
for user defined types that can be used with the standard I/O code,
since some user types are simply made to make up for the deficiencies in
the language's built-ins.  (Dates, vectors, etc.)  The other is that
printf can be a huge security hole.  You may challenge people write cout
code that you think is pretty.  I challenge anyone to implement a printf
that isn't capable of producing security breaches.  (I'm looking at the
format string when I say that.)

IMHO, printf shines where you need complex formatting and/or the arguments are
complex.

And the beauty of iostreams is that you can write code so that even the
most complex types can be read or written as easily as a simple infix
expression.

Fair enough.  I like << and >> primarily because of their type-safety (scanf
is HORRID).  However, there is a
lot of elegance to the code:

int i;
cin >> i;

Which is more visual than

int i;
scanf("%d",&i);

Or, what I normally end up doing because I can never remember how scanf works:

int i;
char buf[32];
fgets(buf,32,stdin);
i = atoi(buf);

scanf is horrid, but printf isn't?  They are the left and right arms of
the same depraved beast.

Dan
```
Oct 10 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```a wrote:

printf("value of my variable: %.8x\n",
foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX());

I would challenge anyone here to write the cout code that matches the
formatting capabilities of printf.

cout << "value of my variable: "
<< setw(8) << hex
<< foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX()
<< endl;

clap,clap,clap.  I couldn't have done that.  One question...doesn't the "hex"
format persist?  Shouldn't you reset
that somehow, so that it doesn't corrupt later print on cout?  Or does it reset
after printing one thing?

I
would also challenge anybody to write cout code that expresses, as clearly as
the printf format string, how
the stuff will actually look on the screen.

I don't think the above is all that bad really.  As far as clearness,
I've never though all the %magic was really that clear.  It's ugly as
sin to tell the truth.  Of course if you want things to appear in the
code as they would on the screen, we could go back to COBOL picture
statements.  Perl has a similar feature that they are about to rip out
of the perl core.

True, %magic is ugly, but I haven't seen better yet.  I don't know anything
about COBOL, so I can't really speak to
it...

I'm not against having something like printf in D, but I have two
issues.  It is real nice to be able to define input and output routines
for user defined types that can be used with the standard I/O code,
since some user types are simply made to make up for the deficiencies in
the language's built-ins.  (Dates, vectors, etc.)

True, this is nice.  Maybe functions of the base class ('object', I think it
was) that you can override.

The other is that
printf can be a huge security hole.  You may challenge people write cout
code that you think is pretty.  I challenge anyone to implement a printf
that isn't capable of producing security breaches.  (I'm looking at the
format string when I say that.)

I've heard of such things...things like the ability to read memory directly and
such.  Can you give examples of it,
since I haven't seen it firsthand?

I thought that printf in general...where one %magic correlates to one argument,
and there are none of the special
specifires...was secure, even if all of the extensions of it are not.  Am I
wrong?  (p.s. I know that sprintf can
cause buffer overflows...but other than that...)

scanf is horrid, but printf isn't?  They are the left and right arms of
the same depraved beast.

I don't think that that's fair.  To me, it seems that printf was designed to
allow flexible printing syntax.  As
long as you don't mix the wrong formatter with the wrong type, you're ok...and
were looking to see if there's a way
to make a D version of printf that is typesafe so you can't use the wrong
formatter.

It appears to me that scanf was designed to look like printf...but in doing so,
it created a nightmare.  scanf
should have been designed very differently, in a way that made sense for
reading, just like printf was designed to
work well with output.

Anyhow, this is all just my opinion.  I use both cout and printf as my whims
dictate :)

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 10 2001
"EvilOne" <evilone omen.ru> writes:
``` Anyhow, this is all just my opinion.  I use both cout and printf as my whims
dictate :)

The question is, what we'll have in D?
```
Oct 10 2001
a <a b.c> writes:
```Russ Lewis wrote:

a wrote:
cout << "value of my variable: "
<< setw(8) << hex
<< foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX()
<< endl;

clap,clap,clap.  I couldn't have done that.  One question...doesn't the "hex"
format persist?  Shouldn't you reset
that somehow, so that it doesn't corrupt later print on cout?  Or does it
reset after printing one thing?

You got me.  I tried to convince myself that hex worked like setw() and
a number of the other one shot manipulators.  It kind of sucks in this
case.  You would have to save the state flag before the cout and restore
it when you're done doing hex.

True, %magic is ugly, but I haven't seen better yet.  I don't know anything
about COBOL, so I can't really speak to
it...

Oh, you missed out.  You define a format line that specifies who field
will be laid out.  Then when you print you give it the format name a a
list variables (a record actually that you've populated with the data).

I'm not against having something like printf in D, but I have two
issues.  It is real nice to be able to define input and output routines
for user defined types that can be used with the standard I/O code,
since some user types are simply made to make up for the deficiencies in
the language's built-ins.  (Dates, vectors, etc.)

True, this is nice.  Maybe functions of the base class ('object', I think it
was) that you can override.

You still need to create your own %magic symbol to use it with printf,
so he knows how to handle the argument.  That just make the % problem
worse, if not open ended.  I admit that printf does what it does better
that most anything else.  It's just not capable of being expanded in a
reasonable way.

The other is that
printf can be a huge security hole.  You may challenge people write cout
code that you think is pretty.  I challenge anyone to implement a printf
that isn't capable of producing security breaches.  (I'm looking at the
format string when I say that.)

I've heard of such things...things like the ability to read memory directly
and such.  Can you give examples of it,
since I haven't seen it firsthand?

Not on short notice.  :-)

I thought that printf in general...where one %magic correlates to one
argument, and there are none of the special
specifires...was secure, even if all of the extensions of it are not.  Am I
wrong?  (p.s. I know that sprintf can
cause buffer overflows...but other than that...)

scanf is horrid, but printf isn't?  They are the left and right arms of
the same depraved beast.

I don't think that that's fair.

Well I am trying to vilify stdio after all...

To me, it seems that printf was designed to allow flexible printing syntax.  As
long as you don't mix the wrong formatter with the wrong type, you're ok...and
were looking to see if there's a way
to make a D version of printf that is typesafe so you can't use the wrong
formatter.

If it's type safe, then you don't need the formatter in most cases.
The %i, %d, %s, %c, %x, etc. formats are redundant if printf could be
made type safe.  They would allow you to put an implicit case of some
sort in the format string, but that sounds nasty to me.  And it defies
the "Only one way to possibly do it." ideology that D seems to be going
for.  (Maybe I do like it.)
Maybe we could define a function that takes a list of class printable
objects (and class Object could have a cast defined that users could
override) and then we could allow optional modifiers to be applied to
the arguments.  There is no point in forcing some to specify formats
when all he wants say is:
print("It was: ", it, "\n");

It appears to me that scanf was designed to look like printf...but in doing
so, it created a nightmare.  scanf
should have been designed very differently, in a way that made sense for
reading, just like printf was designed to
work well with output.

printf allows aggregate printing. scanf allow aggregate reading.  I used
to work with folks who loved scanf the way you love printf.  Both are
better than the world of have a read and print function for every data
type imaginable for the user to memorize the options to.  It's just that
it feels like it is time to get fed up and improve things again.

Anyhow, this is all just my opinion.  I use both cout and printf as my whims
dictate :)

Same here.  Recently I began to force myself to use cout even when it
hurts so I can learn how to criticize it more meaningfully.  It ain't
printf but it's not as bad as most people make it out to be.  It's cool
that you can make your own custom manipulators easily, but it would be
nicer if you could define a manipulator type and assign it the
OR/accumulation/whatever a bunch of manipulations together so you could
then apply it to a variable being inserted.

form F = hex + width(5) + center;
cout << x << F + y << width(3) + right + z << endl;

It still needs work, but it give the basic idea.  I just used plus every
where because I was at a loss for words.  The accumulation operator
should be different from the apply operator.  Maybe it could be spelled:

form F = hex & width(5) & center;
cout << x << F|y << width(3)&right|z << end;

It might be nice to be apply to apply to a list of arguments too. But I
digress.  This type of syntax won't work for D.

Dan
```
Oct 10 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```a wrote:

I'm not against having something like printf in D, but I have two
issues.  It is real nice to be able to define input and output routines
for user defined types that can be used with the standard I/O code,
since some user types are simply made to make up for the deficiencies in
the language's built-ins.  (Dates, vectors, etc.)

True, this is nice.  Maybe functions of the base class ('object', I think it
was) that you can override.

You still need to create your own %magic symbol to use it with printf,
so he knows how to handle the argument.  That just make the % problem
worse, if not open ended.  I admit that printf does what it does better
that most anything else.  It's just not capable of being expanded in a
reasonable way.

class object     // base for everything else
{
public:
char[] toString() { // default value returns a hex print of the 'this'
pointer };
};

The implementation recognizes a new %magic that is only legal when matched to
an argument that is a pointer to object (or
a child, ofc).  Any classes that want to override how they are printed must
override toString().  Thus, you only add 1
%magic that will work with all classes.

It doesn't help with structs, ofc...

scanf is horrid, but printf isn't?  They are the left and right arms of
the same depraved beast.

I don't think that that's fair.

Well I am trying to vilify stdio after all...

LOL

If it's type safe, then you don't need the formatter in most cases.
The %i, %d, %s, %c, %x, etc. formats are redundant if printf could be
made type safe.  They would allow you to put an implicit case of some
sort in the format string, but that sounds nasty to me.  And it defies
the "Only one way to possibly do it." ideology that D seems to be going
for.  (Maybe I do like it.)

Hold on here...the point of those specifiers is to tell you how to print
something.  %d (and %i, which I think is
identical) prints an integer in decimal format.  %c prints the ASCII character
that has the ASCII code given.  %x and %X
are two distinct ways of printing an integer as a hexdecimal value.  All of
these specifiers can work on the SAME
argument!

printf("%d %c %x %X",10,10,10,10);
prints out
"10 \n a A"

The typesafety comes in when you try to pass a char[] and print it as an
integer, or an integer and you try to print it
as a string (meaning printf expects it to be a pointer value).  In either of
those cases, printf() would throw an
exception.

It appears to me that scanf was designed to look like printf...but in doing
so, it created a nightmare.  scanf
should have been designed very differently, in a way that made sense for
reading, just like printf was designed to
work well with output.

printf allows aggregate printing. scanf allow aggregate reading.  I used
to work with folks who loved scanf the way you love printf.  Both are
better than the world of have a read and print function for every data
type imaginable for the user to memorize the options to.  It's just that
it feels like it is time to get fed up and improve things again.

I suppose scanf might work to my liking, if it was typesafe, wouldn't overrun
buffers, and didn't require you to take the
address of every little integer you're reading.

I agree, it's time for an upgrade.  cout might be a step in the right
direction, but I think it's more of a step
sideways.  Let's brainstorm... :)

Anyhow, this is all just my opinion.  I use both cout and printf as my whims
dictate :)

Same here.  Recently I began to force myself to use cout even when it
hurts so I can learn how to criticize it more meaningfully.  It ain't
printf but it's not as bad as most people make it out to be.  It's cool
that you can make your own custom manipulators easily, but it would be
nicer if you could define a manipulator type and assign it the
OR/accumulation/whatever a bunch of manipulations together so you could
then apply it to a variable being inserted.

form F = hex + width(5) + center;
cout << x << F + y << width(3) + right + z << endl;

It still needs work, but it give the basic idea.  I just used plus every
where because I was at a loss for words.  The accumulation operator
should be different from the apply operator.  Maybe it could be spelled:

form F = hex & width(5) & center;
cout << x << F|y << width(3)&right|z << end;

It might be nice to be apply to apply to a list of arguments too. But I
digress.  This type of syntax won't work for D.

I actually kind of like your syntax, personally.  It has the potential for the
compactness I like of printf with the all
of the OOP benefits.

And it's actually not as far from D syntax as you might think.  What if we make
some definitions:

class FormElement;
typedef FormElement[] form;

form hex = { hexElement };
form width(int i) { return ... };
form center = { centerElement };

To accumulate types, you do this:

form F = hex + width(5) + center;

which D interprets as concatenating arrays.  Now walter helps us by adding a
property function called "format" which
takes a form argument and returns a char[].  We also implement it as a function
in 'object', so now we can print easily:

stdout.print(x.format() + "this is a string" + y.format(F) +
z.format(width(3)+right) + endl);

Thoughts?

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 10 2001
a <a b.c> writes:
```Russ Lewis wrote:

a wrote:
You still need to create your own %magic symbol to use it with printf,
so he knows how to handle the argument.  That just make the % problem
worse, if not open ended.  I admit that printf does what it does better
that most anything else.  It's just not capable of being expanded in a
reasonable way.

class object     // base for everything else
{
public:
char[] toString() { // default value returns a hex print of the 'this'
pointer };
};

The implementation recognizes a new %magic that is only legal when matched to
an argument that is a pointer to object (or
a child, ofc).  Any classes that want to override how they are printed must
override toString().  Thus, you only add 1
%magic that will work with all classes.

It doesn't help with structs, ofc...

Well, at the very least, I'd like to have a toStream method that can
default to toString.  The human readable format is not always the
best/most complete way to store to a file.
Given only one %magic symbol that can handle all descendants of Object
would work, but you would only have one way of formatting, and how would
you deal with the %modifiers?  (Assuming we really want the kludge up
printf this way.)

If it's type safe, then you don't need the formatter in most cases.
The %i, %d, %s, %c, %x, etc. formats are redundant if printf could be
made type safe.  They would allow you to put an implicit case of some
sort in the format string, but that sounds nasty to me.  And it defies
the "Only one way to possibly do it." ideology that D seems to be going
for.  (Maybe I do like it.)

Hold on here...the point of those specifiers is to tell you how to print
something.  %d (and %i, which I think is
identical) prints an integer in decimal format.  %c prints the ASCII character
that has the ASCII code given.  %x and %X
are two distinct ways of printing an integer as a hexdecimal value.  All of
these specifiers can work on the SAME
argument!

printf("%d %c %x %X",10,10,10,10);
prints out
"10 \n a A"

The typesafety comes in when you try to pass a char[] and print it as an
integer, or an integer and you try to print it
as a string (meaning printf expects it to be a pointer value).  In either of
those cases, printf() would throw an
exception.

You are right that there is a difference between %d and %x (etc.) that
we'd need to keep.  In the above discussion, we could not have such
differences in representation for objects.  A pity.
I will argue that you don't need %c or similar %magic that specify a
type, but not a representation.  In your above example, if you want 10
to be a char, cast it.  that is the implicit cast I was talking about.

It appears to me that scanf was designed to look like printf...but in doing
so, it created a nightmare.  scanf
should have been designed very differently, in a way that made sense for
reading, just like printf was designed to
work well with output.

printf allows aggregate printing. scanf allow aggregate reading.  I used
to work with folks who loved scanf the way you love printf.  Both are
better than the world of have a read and print function for every data
type imaginable for the user to memorize the options to.  It's just that
it feels like it is time to get fed up and improve things again.

I suppose scanf might work to my liking, if it was typesafe, wouldn't overrun
buffers, and didn't require you to take the
address of every little integer you're reading.

I agree, it's time for an upgrade.  cout might be a step in the right
direction, but I think it's more of a step
sideways.  Let's brainstorm... :)

The whole OO and infix think I think was in at least a vaguely forward
direction.

Same here.  Recently I began to force myself to use cout even when it
hurts so I can learn how to criticize it more meaningfully.  It ain't
printf but it's not as bad as most people make it out to be.  It's cool
that you can make your own custom manipulators easily, but it would be
nicer if you could define a manipulator type and assign it the
OR/accumulation/whatever a bunch of manipulations together so you could
then apply it to a variable being inserted.

form F = hex + width(5) + center;
cout << x << F + y << width(3) + right + z << endl;

It still needs work, but it give the basic idea.  I just used plus every
where because I was at a loss for words.  The accumulation operator
should be different from the apply operator.  Maybe it could be spelled:

form F = hex & width(5) & center;
cout << x << F|y << width(3)&right|z << end;

It might be nice to be apply to apply to a list of arguments too. But I
digress.  This type of syntax won't work for D.

I actually kind of like your syntax, personally.  It has the potential for the
compactness I like of printf with the all
of the OOP benefits.

And it's actually not as far from D syntax as you might think.  What if we
make some definitions:

class FormElement;
typedef FormElement[] form;

form hex = { hexElement };
form width(int i) { return ... };
form center = { centerElement };

To accumulate types, you do this:

form F = hex + width(5) + center;

which D interprets as concatenating arrays.  Now walter helps us by adding a
property function called "format" which
takes a form argument and returns a char[].  We also implement it as a
function in 'object', so now we can print easily:

stdout.print(x.format() + "this is a string" + y.format(F) +
z.format(width(3)+right) + endl);

Thoughts?

Is the array thing really the best way to do this?  I looks to me like
a hack to get around the lack of operator overloads.  It might feel
better like:
format.apply(hex).apply(right).apply(width(3));
I'm not crazy in love with this either.

On an aesthetic level, I think I'm more accustomed to the format coming
before the data being formatted.  That's minor though. If enough people
agree though, we could be the format something that take an argument and
returns something streamable.

I can say that I don't like the concatenations prior to the print
operation.  If print could safely do variable arguments, it could
print/write them all without having to allocate an intermediate buffer
the size of everything being printed and copying it.  There would be
excess time overhead with the extra copying and memory overhead with the
temp string.  This isn't a problem with print so much as it's the only
way we can pass a variable number of objects to a print routine.

Another aesthetic note.  Say what you will about cout's failings, I do
find the expression based syntax more visually pleasing.  It's a style
thing I think.  I hate doing multi-line method invocations.  Multi-line
expressions don't for some reason unless it's an argument to function or
control structure.  In your example I would probably want to do:
stdout.print(x.format()
+ "this is a string"
+ y.format(F)
+ z.format(width(3)+right)
+ endl);

For some reason I like it better when it's not a method call.  Cout's
formatting is still gross in form and function but I find its code
formats better for my eyes.
I like the example less since those are pluses and not commas.  For
plain function calls, I don't tend to mind splitting lines on commas.
Anything else just feels icky.  I know my reasoning here is dippy, but
style is like that.

I think it would be worth brain storming out how the I/O might work.
The same is true of other library like functions.  Java got big before
it's library was stable.  I'm not sure I'd feel safe calling it stable
yet.  I'd hate to see D follow in Java's foot steps in this way.  I've
found the difference between versions of java to bother me more than the
differences implementations of C on different platforms.  It rivals
C++.  (Granted, I've had the supreme pleasure of not having to code for
Windows.)

Dan
```
Oct 13 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```a wrote:

Russ Lewis wrote:
a wrote:
You still need to create your own %magic symbol to use it with printf,
so he knows how to handle the argument.  That just make the % problem
worse, if not open ended.  I admit that printf does what it does better
that most anything else.  It's just not capable of being expanded in a
reasonable way.

class object     // base for everything else
{
public:
char[] toString() { // default value returns a hex print of the 'this'
pointer };
};

The implementation recognizes a new %magic that is only legal when matched to
an argument that is a pointer to object (or
a child, ofc).  Any classes that want to override how they are printed must
override toString().  Thus, you only add 1
%magic that will work with all classes.

It doesn't help with structs, ofc...

Well, at the very least, I'd like to have a toStream method that can
default to toString.  The human readable format is not always the
best/most complete way to store to a file.
Given only one %magic symbol that can handle all descendants of Object
would work, but you would only have one way of formatting, and how would
you deal with the %modifiers?  (Assuming we really want the kludge up
printf this way.)

What if toString had a char[] argument:

stdout.print("%z %'asdf'z", obj1, obj2);

The 'asdf' string would be passed to the toString call on obj2.

I will argue that you don't need %c or similar %magic that specify a
type, but not a representation.  In your above example, if you want 10
to be a char, cast it.  that is the implicit cast I was talking about.

That's true, kind of.  But there is a substantial difference between "print the
decimal representation of this byte", "print
the hexadecimal representation of this byte", and "print the ASCII
representation of this byte", all of which are valid for a
char type.

Is the array thing really the best way to do this?

I certainly hope not!

I looks to me like
a hack to get around the lack of operator overloads.

Very true.  It is very ugly; it was just a brainstorm to get things started. :)

It might feel
better like:
format.apply(hex).apply(right).apply(width(3));
I'm not crazy in love with this either.

On an aesthetic level, I think I'm more accustomed to the format coming
before the data being formatted.  That's minor though. If enough people
agree though, we could be the format something that take an argument and
returns something streamable.

char[] format(form,int)    ???

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 13 2001
a <a b.c> writes:
```Russ Lewis wrote:

a wrote:

Russ Lewis wrote:
a wrote:
You still need to create your own %magic symbol to use it with printf,
so he knows how to handle the argument.  That just make the % problem
worse, if not open ended.  I admit that printf does what it does better
that most anything else.  It's just not capable of being expanded in a
reasonable way.

class object     // base for everything else
{
public:
char[] toString() { // default value returns a hex print of the 'this'
pointer };
};

The implementation recognizes a new %magic that is only legal when matched to
an argument that is a pointer to object (or
a child, ofc).  Any classes that want to override how they are printed must
override toString().  Thus, you only add 1
%magic that will work with all classes.

It doesn't help with structs, ofc...

Well, at the very least, I'd like to have a toStream method that can
default to toString.  The human readable format is not always the
best/most complete way to store to a file.
Given only one %magic symbol that can handle all descendants of Object
would work, but you would only have one way of formatting, and how would
you deal with the %modifiers?  (Assuming we really want the kludge up
printf this way.)

What if toString had a char[] argument:

stdout.print("%z %'asdf'z", obj1, obj2);

The 'asdf' string would be passed to the toString call on obj2.

I like this idea.  I still don't like %magic, but this improves it a
bit.  It did just strike me though, we were going after typesafety
somewhere back there.  By have one %magic for all object, haven't we
killed real typesafety?  For instance, suppose you passed the wrong
object type to your print statement above.  It would be valid still.  It
may barf at runtime because it doesn't handle 'asdf'.  Not to derail
you, its a good idea, but how do we get typesafety back into it?

I will argue that you don't need %c or similar %magic that specify a
type, but not a representation.  In your above example, if you want 10
to be a char, cast it.  that is the implicit cast I was talking about.

That's true, kind of.  But there is a substantial difference between "print
the decimal representation of this byte", "print
the hexadecimal representation of this byte", and "print the ASCII
representation of this byte", all of which are valid for a
char type.

There a different representations, like hex, oct, dec, left, right, etc.
but doesn't %h only work for type char because printf uses varargs
converting chars into ints?  I'm just used to the bare %magic being used
to specify type.  That notion should die and be replaced with type
safety.  Representation descriptors would still be valid, but in many
cases a sane default should be acceptable.  Make character type look
like characters, make numbers look like numbers, etc.

Is the array thing really the best way to do this?

I certainly hope not!

Sorry.  :-)

I looks to me like
a hack to get around the lack of operator overloads.

Very true.  It is very ugly; it was just a brainstorm to get things started. :)

Well, I guess the very first thing we ought to decide what type of
syntax we want.  If we go all procedural, we are ok.  You said you would
need a format property in your idea.  I think I like that, but I'm not
sure how to best leverage it.  In any case that is something we would
have to be Walter for.  Likewise, if we want more on an expression based
syntax, we either have to kludge around with the built-in types in D or
we have to beg Walter to add a couple more primitives, with operators.
At that point I'd say we are work in the language itself though and not
in the library.

It might feel
better like:
format.apply(hex).apply(right).apply(width(3));
I'm not crazy in love with this either.

On an aesthetic level, I think I'm more accustomed to the format coming
before the data being formatted.  That's minor though. If enough people
agree though, we could be the format something that take an argument and
returns something streamable.

char[] format(form,int)    ???

I'm not sure really.  I guess I was thinking:

form F = <manipulator(s)>;        // custom
stdio.print(v1, hex(v2), F(v3));  // default form, hex form, my custom
form

But think makes it difficult or applets nasty looking to apply multiple
format manipulator to a single variable in the print statement.

stdio.print(hex(width(3, right(v1))));  // lisp anyone

I don't think I would want to have to declare a format type for every
custom manipulation.  It would give us one of the worst drawbacks of
COBOL's and perl's record based output without the benefits.

I'm also having trouble being objective coming up with something looks
like it fits D's ideology.  I'm real partial to C++'s i/o and in D
that's right out.  I like the suggestion you had above for %magic on
object types but I don't think it goes far enough.
Would help to work out a formalized set of string ops to build upon?
Most I/O will either be binary records or text strings I would assume.
The binary output wouldn't need much in the way of formatting.  fixed
record sizes, byte and bit ordering and that sort of thing should do.
It's with the human readable that we worry and justification,
representation, padding, text formation of complex types.  Maybe we
would have a better feel for what feels right for printing strings in D
once we get a feel for what it would be like to just muck around with
strings in D.

Dan
```
Oct 13 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```a wrote:

I like this idea.  I still don't like %magic, but this improves it a
bit.  It did just strike me though, we were going after typesafety
somewhere back there.  By have one %magic for all object, haven't we
killed real typesafety?  For instance, suppose you passed the wrong
object type to your print statement above.  It would be valid still.  It
may barf at runtime because it doesn't handle 'asdf'.  Not to derail
you, its a good idea, but how do we get typesafety back into it?

The key with strong typing is that you know what you know and you don't have to
make wild guesses or assumptions.  When the %z (or
whatever) magic is passed, if the typesafe printf sees that the matching
argument is anything but a pointer to an object, then it
throws an exception.  If it is an object, then it calls toString with the
(possibly zero length) char[] array that is the %z format
qualifier.  This call goes right to the overloaded version of this function in
the class (remember, the compiler is smart enough to
make all functions virtual).  This class is then responsible for dealing with
the qualifier.

If your class doesn't deal with qualifiers, then you throw the exception if it
is nonzero length.  If you do, then you throw an
exception if you don't recognize the format.  Etc...

Please clarify if I'm missing something, but this seems 100% typesafe to me -
provided that the underlying printf varargs
architecture is also typesafe.

There a different representations, like hex, oct, dec, left, right, etc.
but doesn't %h only work for type char because printf uses varargs
converting chars into ints?  I'm just used to the bare %magic being used
to specify type.  That notion should die and be replaced with type
safety.  Representation descriptors would still be valid, but in many
cases a sane default should be acceptable.  Make character type look
like characters, make numbers look like numbers, etc.

Ah, yes.  I see what you're saying now.  And I totally agree.  One of my big
gripes with %x/%X is that if the high bit is 1, then
we always get a 8-character printf string:

printf("%x",(signed char)-1)    prints "FFFFFFFF"

whereas I wish it would print "FF".  The hack around that that I found was to
convert my arg to an UNsigned char...so that when
it's promoted to a long, it is filled with 0's.  Then printf works as I would
like.  In D's printf, passing a char should make the
format default to only printing 2 characters (or less).

I looks to me like
a hack to get around the lack of operator overloads.

Very true.  It is very ugly; it was just a brainstorm to get things started. :)

Well, I guess the very first thing we ought to decide what type of
syntax we want.  If we go all procedural, we are ok.  You said you would
need a format property in your idea.  I think I like that, but I'm not
sure how to best leverage it.  In any case that is something we would
have to be Walter for.  Likewise, if we want more on an expression based
syntax, we either have to kludge around with the built-in types in D or
we have to beg Walter to add a couple more primitives, with operators.
At that point I'd say we are work in the language itself though and not
in the library.

We could go with the Perl syntax here (shudder).  Use the dot operator to
concatenate (formatted) strings.  Any time that the
compiler sees something of the form:

char[] . foo

It converts it internally to

char[] + format(foo)

where format(...) is a series of library routines that convert various things
into char[].  The format(object) just calls
toString() to do it.  But now we have the problem of how to do format
specifiers again....   #\$)(^%\$#%&

Ofc, this all requires that Walter implement some special case code for
char[]...but one of the stated objectives of D was
"Languages should be good at handling strings."

Another thought.  Instead of only making this work for char[], you could make
it work for all array types.  Earlier, in a
discussion about casts, somebody talked about actually passing a type (not a
value) as a parameter into a cast function:

int i = cast(int,foo);

We could do a similar thing with the . operator on arrays.

char[] str = "" . foo . bar . baz;

Is expanded to:

char[] str = "" + format(char[],foo) + format(char[],bar) + format(char[],baz);

I thought about using the cast syntax, but that becomes cloudy when the
argument you're trying to format is a pointer or another
array.

I'm also having trouble being objective coming up with something looks
like it fits D's ideology.  I'm real partial to C++'s i/o and in D
that's right out.  I like the suggestion you had above for %magic on
object types but I don't think it goes far enough.

I Walter doesn't mind the overloaded . operator idea, you could use << and >>

char[] str = "" . foo;
becomes
char[] str = "" + format(char[],foo);

and

str >> foo;
becomes
foo = extract(typeof(foo),str);

Or something like that.  Still no (good) solution for format specifiers.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 14 2001
a <a b.c> writes:
```Russ Lewis wrote:

The key with strong typing is that you know what you know and you don't have
to make wild guesses or assumptions.  When the %z (or
whatever) magic is passed, if the typesafe printf sees that the matching
argument is anything but a pointer to an object, then it
throws an exception.  If it is an object, then it calls toString with the
(possibly zero length) char[] array that is the %z format
qualifier.  This call goes right to the overloaded version of this function in
the class (remember, the compiler is smart enough to
make all functions virtual).  This class is then responsible for dealing with
the qualifier.

If your class doesn't deal with qualifiers, then you throw the exception if it
is nonzero length.  If you do, then you throw an
exception if you don't recognize the format.  Etc...

Please clarify if I'm missing something, but this seems 100% typesafe to me -
provided that the underlying printf varargs
architecture is also typesafe.

Well are typesafe in that it will always be a descendant of Object.
But you can't be more specific.  (I don't mean just any Fruit.  I want
an Apple!)  You will always get the streamify routine for the Object you
pass, but I guess I would like to say what type of Object I expect and
get en error otherwise, like you would with builtin types.  Not a show
stopper by any means.

There a different representations, like hex, oct, dec, left, right, etc.
but doesn't %h only work for type char because printf uses varargs
converting chars into ints?  I'm just used to the bare %magic being used
to specify type.  That notion should die and be replaced with type
safety.  Representation descriptors would still be valid, but in many
cases a sane default should be acceptable.  Make character type look
like characters, make numbers look like numbers, etc.

Ah, yes.  I see what you're saying now.  And I totally agree.  One of my big
gripes with %x/%X is that if the high bit is 1, then
we always get a 8-character printf string:

printf("%x",(signed char)-1)    prints "FFFFFFFF"

whereas I wish it would print "FF".  The hack around that that I found was to
convert my arg to an UNsigned char...so that when
it's promoted to a long, it is filled with 0's.  Then printf works as I would
like.  In D's printf, passing a char should make the
format default to only printing 2 characters (or less).

Well, I guess I would rather that D would always print a char as a
char/glyph, unless I cast it to something else (like an unsigned) in
which case I would like to to print way ever I passed it.  I do agree
that in some cases there is format information that is useful and not
associated to the type (unless we attach a format property; probably
overkill) like hex/oct/dec, left/right/center, and the like, but I don't
think I like the use of the format character as an end run around a
cast.  I C you didn't have a choice.  printf only saw ints.

We could go with the Perl syntax here (shudder).  Use the dot operator to
concatenate (formatted) strings.  Any time that the
compiler sees something of the form:

char[] . foo

It converts it internally to

char[] + format(foo)

where format(...) is a series of library routines that convert various things
into char[].  The format(object) just calls
toString() to do it.  But now we have the problem of how to do format
specifiers again....   #\$)(^%\$#%&

Actually, this isn't how perl does formatting.  Your choices in perl are
(s)printf and format lines like:

format FOO
price: \$<<<<<   tax: \$>>>>
\$thePrice, \$theTax

to say the first value will be left justified and the second will be
right justified.  (I have the syntax wrong, but it's the general idea.
You then have to tell the interpreter which format you are using for a
given filehandle and then you do a write like so:

(\$thePrice, \$theTax) = (\$something, \$somethingelse);
write myFileHandle;

Ofc, this all requires that Walter implement some special case code for
char[]...but one of the stated objectives of D was
"Languages should be good at handling strings."

Oh, for string handling.  I was thinking of something comparable to C's
strtok, sprintf, index, etc except (hopefully) better.  If we can come
up with an easy way to say "make this string 8 chars wide, center the
characters in the string and uppercase the first letter" in a very
concise way, then print formatting is easy.  Kind of like reducing
printf to {return puts(sprintf(ARGS))};
Now if it's not very abbreviated, it's going to suck.  printf was very
brief.  C++ wasn't as brief, but with the exception that some modifiers
were persistent and some were one shot, it conveyed the idea fairly
elegantly.  It needs some work though in terms of ease of use.  I've
found the single argument, overloaded write/writeln scheme to be a bit
clumsy.  With good string formating, the printing may be less of an
issue sincec we can build the string and print it as a single argument,
but I still believe there will be needless memory/cpu overhead with such
a scheme.  If you do a lot of i/o, you'll run the cpu ragged collecting
the temporaries when you're not in i/o wait.

Another thought.  Instead of only making this work for char[], you could make
it work for all array types.  Earlier, in a
discussion about casts, somebody talked about actually passing a type (not a
value) as a parameter into a cast function:

int i = cast(int,foo);

I think that got shot down because the type could not be determined
until the semantic pass.

We could do a similar thing with the . operator on arrays.

char[] str = "" . foo . bar . baz;

Dot won't work.  It could be a member dereference, or it could be a
concatenation.  Actually, perl 6 is switching . to _ so that they switch
-> to . like all other OO languages.  That's academic though.  We can
find another operator.

Is expanded to:

char[] str = "" + format(char[],foo) + format(char[],bar) + format(char[],baz);

I thought about using the cast syntax, but that becomes cloudy when the
argument you're trying to format is a pointer or another
array.

Actually, format is looking a lot like a synonym for cast.  How would
you use the scheme to justify, set field width, or print a number in
hex?

I'm also having trouble being objective coming up with something looks
like it fits D's ideology.  I'm real partial to C++'s i/o and in D
that's right out.  I like the suggestion you had above for %magic on
object types but I don't think it goes far enough.

I Walter doesn't mind the overloaded . operator idea, you could use << and >>

char[] str = "" . foo;
becomes
char[] str = "" + format(char[],foo);

and

str >> foo;
becomes
foo = extract(typeof(foo),str);

Or something like that.  Still no (good) solution for format specifiers.

It's not that I'm fixated on the >>/<< operators.  It's that I am
fixated on expressions as opposed to calls.  I don't see a clean way to
do that in a library w/o overloading operators or variable arguments.  I
also like the fact that user defined type can be printed like any first
class Object.  Treating Objects like first class types has been met with
near hostility here.  I think the might be a good hint that D i/o
probably should try to blur that line no matter how much I may want to.

Dan
```
Oct 19 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```a wrote:

Russ Lewis wrote:

The key with strong typing is that you know what you know and you don't have
to make wild guesses or assumptions.  When the %z (or
whatever) magic is passed, if the typesafe printf sees that the matching
argument is anything but a pointer to an object, then it
throws an exception.  If it is an object, then it calls toString with the
(possibly zero length) char[] array that is the %z format
qualifier.  This call goes right to the overloaded version of this function in
the class (remember, the compiler is smart enough to
make all functions virtual).  This class is then responsible for dealing with
the qualifier.

If your class doesn't deal with qualifiers, then you throw the exception if it
is nonzero length.  If you do, then you throw an
exception if you don't recognize the format.  Etc...

Please clarify if I'm missing something, but this seems 100% typesafe to me -
provided that the underlying printf varargs
architecture is also typesafe.

Well are typesafe in that it will always be a descendant of Object.
But you can't be more specific.  (I don't mean just any Fruit.  I want
an Apple!)  You will always get the streamify routine for the Object you
pass, but I guess I would like to say what type of Object I expect and
get en error otherwise, like you would with builtin types.  Not a show
stopper by any means.

Remember that all member functions of classes are automatically virtual in D
(when necessary).  Thus, if you pass a Fruit* pointer (which
is cast down to an Object*), then when you call toString(), you get
Fruit::toString.  You get complete control.  And if the formatter
arguments you pass with it don't make sense for Fruit::toString, then it throws
an exception.

Well, I guess I would rather that D would always print a char as a
char/glyph, unless I cast it to something else (like an unsigned) in
which case I would like to to print way ever I passed it.  I do agree
that in some cases there is format information that is useful and not
associated to the type (unless we attach a format property; probably
overkill) like hex/oct/dec, left/right/center, and the like, but I don't
think I like the use of the format character as an end run around a
cast.  I C you didn't have a choice.  printf only saw ints.

Makes sense.  We just have to implement the printf() routine...but I agree that
this is a good default.

We could go with the Perl syntax here (shudder).  Use the dot operator to
concatenate (formatted) strings.  Any time that the
compiler sees something of the form:

char[] . foo

It converts it internally to

char[] + format(foo)

where format(...) is a series of library routines that convert various things
into char[].  The format(object) just calls
toString() to do it.  But now we have the problem of how to do format
specifiers again....   #\$)(^%\$#%&

Actually, this isn't how perl does formatting.  Your choices in perl are
(s)printf and format lines like:

I meant it not as a formatting routine, but as an easy concatenation routine.
If you used
char[] . foo
, it would call format to convert foo to a char[], then concatenate the arrays.
If you wanted explicit formating strings, you would call

char[] . format(foo, options)

Ofc, this all requires that Walter implement some special case code for
char[]...but one of the stated objectives of D was
"Languages should be good at handling strings."

Oh, for string handling.  I was thinking of something comparable to C's
strtok, sprintf, index, etc except (hopefully) better.  If we can come
up with an easy way to say "make this string 8 chars wide, center the
characters in the string and uppercase the first letter" in a very
concise way, then print formatting is easy.

Unfortunately, we can't really describe it easily even in English...not
terribly likely we're going to be able to better in a programming
language without creating some weird new language (like printf did).   :(

Kind of like reducing printf to {return puts(sprintf(ARGS))};

BTW, as you imply here, I very much think that sprintf should NOT take the
buffer as an argument, but instead should return the string it
creates.  Either that or require arrays (no pointers).  I don't want to mess
with buffer overflows anymore.  Or with having to calculate
ahead of time how much buffer space I'll need.

Is expanded to:

char[] str = "" + format(char[],foo) + format(char[],bar) + format(char[],baz);

I thought about using the cast syntax, but that becomes cloudy when the
argument you're trying to format is a pointer or another
array.

Actually, format is looking a lot like a synonym for cast.  How would
you use the scheme to justify, set field width, or print a number in
hex?

By adding an extra argument that allows the user to pass format specifiers.

The problem with unifying format and cast is:

int i = ...;
char *ptr = format(char*,i);
char[] str = format(char[],i);

The first should cast the value i into a ptr whose address is i.  The latter
should create a char[] which contains a string which is the
decimal representation of i.  We need to keep these totally distinct.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 19 2001
"Sean L. Palmer" <spalmer iname.com> writes:
```         Well, at the very least, I'd like to have a toStream method

that can
default to toString.  The human readable format is not always the
best/most complete way to store to a file.

I hope the hell somebody goes through D and standardizes capitalization
before it goes public, or better yet get rid of case sensitivity.  That was
one of the few things I really liked about Pascal and that I now miss.

I'm not sure really.  I guess I was thinking:

form F = <manipulator(s)>;        // custom
stdio.print(v1, hex(v2), F(v3));  // default form, hex form, my custom
form

But think makes it difficult or applets nasty looking to apply multiple
format manipulator to a single variable in the print statement.

stdio.print(hex(width(3, right(v1))));  // lisp anyone

I don't think I would want to have to declare a format type for every
custom manipulation.  It would give us one of the worst drawbacks of
COBOL's and perl's record based output without the benefits.

I'm also having trouble being objective coming up with something looks
like it fits D's ideology.  I'm real partial to C++'s i/o and in D
that's right out.  I like the suggestion you had above for %magic on
object types but I don't think it goes far enough.
Would help to work out a formalized set of string ops to build upon?
Most I/O will either be binary records or text strings I would assume.
The binary output wouldn't need much in the way of formatting.  fixed
record sizes, byte and bit ordering and that sort of thing should do.
It's with the human readable that we worry and justification,
representation, padding, text formation of complex types.  Maybe we
would have a better feel for what feels right for printing strings in D
once we get a feel for what it would be like to just muck around with
strings in D.

Binary files could be built on strings (since strings don't rely on that
nasty trailing NULL character to determine their length, as in C/C++).

Strings in general should be easy to manipulate.  There's only a few things
you'd want to do to any string: field width, justification, alignment, and
padding (all can be implemented once as a function and will otherwise work
for all types) and for any printable item to change type of conversion
applied (These can be simple function calls probably with overloading, such
as hex(int) and hex(char).

I don't know about anyone else here, but I'm all for building my strings in
memory and then dumping them off in a block to the file or stdout or
whatever at reasonable intervals (such as each line).  Especially if you can
somehow cause the string to reserve enough memory to hold the biggest batch
before you start.  The big advantage is you should be able to use these
methods on all your strings, not just strings going to stdout/cout/whatever.
That one separation enables every kind of stream to have formatting, without
having any stream have to implement or even wrap printf.  All you'd need is
an equivalent to puts().

Sean
```
Nov 04 2001
a <a b.c> writes:
```"Sean L. Palmer" wrote:

Well, at the very least, I'd like to have a toStream method

that can
default to toString.  The human readable format is not always the
best/most complete way to store to a file.

I hope the hell somebody goes through D and standardizes capitalization
before it goes public, or better yet get rid of case sensitivity.  That was
one of the few things I really liked about Pascal and that I now miss.

I'm not sure really.  I guess I was thinking:

form F = <manipulator(s)>;        // custom
stdio.print(v1, hex(v2), F(v3));  // default form, hex form, my custom
form

But think makes it difficult or applets nasty looking to apply multiple
format manipulator to a single variable in the print statement.

stdio.print(hex(width(3, right(v1))));  // lisp anyone

I don't think I would want to have to declare a format type for every
custom manipulation.  It would give us one of the worst drawbacks of
COBOL's and perl's record based output without the benefits.

I'm also having trouble being objective coming up with something looks
like it fits D's ideology.  I'm real partial to C++'s i/o and in D
that's right out.  I like the suggestion you had above for %magic on
object types but I don't think it goes far enough.
Would help to work out a formalized set of string ops to build upon?
Most I/O will either be binary records or text strings I would assume.
The binary output wouldn't need much in the way of formatting.  fixed
record sizes, byte and bit ordering and that sort of thing should do.
It's with the human readable that we worry and justification,
representation, padding, text formation of complex types.  Maybe we
would have a better feel for what feels right for printing strings in D
once we get a feel for what it would be like to just muck around with
strings in D.

Binary files could be built on strings (since strings don't rely on that
nasty trailing NULL character to determine their length, as in C/C++).

The only problem is you have to make sure no character conversion
silliness is going on.  You also have to know what sizeof(char).  You
have to know that some deranged systems aren't converting '\n' into two
characters.  It's better to have a way to tell the code not to do any of
that.

Strings in general should be easy to manipulate.  There's only a few things
you'd want to do to any string: field width, justification, alignment, and
padding (all can be implemented once as a function and will otherwise work
for all types) and for any printable item to change type of conversion
applied (These can be simple function calls probably with overloading, such
as hex(int) and hex(char).

This could be ok if the syntax doesn't get so complex as to take a way
from what you are trying to format.  printf fans/fiends often like how
you get a feel for how the output will like by looking at the format
string.  I am also a little concerned about how to do alignment though
before you send to the stream since that usual depends on stream state.

I don't know about anyone else here, but I'm all for building my strings in
memory and then dumping them off in a block to the file or stdout or
whatever at reasonable intervals (such as each line).  Especially if you can
somehow cause the string to reserve enough memory to hold the biggest batch
before you start.  The big advantage is you should be able to use these
methods on all your strings, not just strings going to stdout/cout/whatever.
That one separation enables every kind of stream to have formatting, without
having any stream have to implement or even wrap printf.  All you'd need is
an equivalent to puts().

I've mentioned this before myself.  The problem is that you have to
know ahead of time what the largest batch is going to be.  Some (many,
I) would consider that an unnecessary pain.  It also adds yet another
buffer layer between the print and the final destination.  This uses
more clock cycles to build a temp string and it and a requires more
memory to store our extra buffer.  It will also require the the user the
maintain the string to make sure it gets reused, or you have to count on
GC to not go nuts when the program does a lot of io. printf didn't need
to build such a buffer.  It analyzed the arguments to be printed one at
a time.  What ever D has will be compared to printf, unless it is
printf.  If we replace printf, it better be good so we don't get as many
people complaining about it as C++ iostreams has.

Dan
```
Nov 04 2001
Charles Hixson <charleshixsn earthlink.net> writes:
```Are you implying that .toString() is a "magic method" that will
be invoked automatically by printf?

That's a plausible approach.  It makes it more important that it
be easy to concatenate strings.  Do remember to allow for usages
such as:
printf (x.asHead(1, 10) + "  " + y.asHead(1, 13) + ...);
or some suitable substitute.
N.B.:  here I was assuming that the asHead methods took the
arguments format#, width, and that each object might do a bit of
self layout formatting.
E.g., if one wanted to produce:
This is  And This is
x         y
=======  ===========
one could do:
printf (x.asHead(1, 10) + "  " + y.asHead(1, 13) + "\n");
printf (x.asHead(2, 10) + "  " + y.asHead(2, 13) + "\n");
printf (x.asHead(3, 10) + "  " + y.asHead(3, 13) + "\n");

persuming that the objects could determine their names.
```
Oct 17 2001
Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
```Charles Hixson wrote:

Are you implying that .toString() is a "magic method" that will
be invoked automatically by printf?

We have been using the term "magic" to refer to the printf format
specifiers.  We were thinking that we could add a new specifier to
format objects.  The idea is that when printf sees that specifier, it
thinks the argument is a pointer to an object, and so calls the
toString() method on it.

It won't work - not safely, anyhow - unless we can get some sort of
typesafe printing routine, so we don't mistakenly think that an int is a
pointer or vice-versa.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
```
Oct 17 2001
"Reg Whitton" <reg.whitton ifonline.com> writes:
```"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BC477F3.F4D0452C deming-os.org...

printf("value of my variable: %.8x\n",
foo->GetOrthogonalBaz()
->Barrify()
->GetNormal(1,2,3)
->MakeHorizontal(false)
->GetX());

I would challenge anyone here to write the cout code that matches the

formatting capabilities of printf.  I
would also challenge anybody to write cout code that expresses, as clearly

as the printf format string, how
the stuff will actually look on the screen.

IMHO, printf shines where you need complex formatting and/or the arguments

are complex.

You are right!  As it is said in the FAQ printf is damned useful.

It also allows you to reuse those format strings again and again without
having to use common routines to build up the messages.

In fact I have worked with code that goes further down the format string
road than printf, and would be impossible to do with C++ iostreams or string
concatenation. When you do internationalisation you often need to be able to
re-order where the arguments appear within the format.

In your code you may put:
display(getMessage(201), colour, item);
in you English message file you may put:
201="You have selected a |0 |1."
but in other languages you might need to name the item before giving its
colour, so the message file might appear:
201="You have selected a |1, |0."                // sorry I'm
uni-lingual.

However, I understand the frustration at printf.  I have seen well tested
software crash in live situations because printf had the wrong number of
arguments and the program has segmented.  You might say it cannot be well
tested if it crashes, but most of the messages in a C program are there to
deal with errors that will probably never happen.  It is very difficult and
unproductive to exercise all the error handling code.  So where the compiler
can check the format string against the arguments, I say please let it (I
believe gcc does this with the -Wformat option).

Unfortunately taking the messages out of the code (as above) and putting
them into files would stop any attempt by the compiler to check the format
string against parameter types.  Where the compiler cannot see the format
string, then I afraid it is upto the programmer to eyeball his code, or
write tools to do this checking.

I have written my own tools that parse the C sources and associated format
strings, and then creates copies of the source with the printf function name
replaced with one that mangles in the expected parameter types, and adds a
related prototype.  Compiling these copies flushes out the type errors.
```
Oct 11 2001