## digitalmars.D - Variadic functions again

• Andrew Edwards (69/69) Jun 08 2004 This is an attempt to generate conversation on variadic functions, the
• J C Calvarese (10/100) Jun 08 2004 I think a built-in variant type would be Fantastic!
• Derek Parnell (12/102) Jun 08 2004 Love it!
• Ben Hinkle (16/104) Jun 09 2004 three thoughts come to mind:
• Andrew Edwards (25/131) Jun 09 2004 The idea is for it to be a self-dereferencing pointer (similar to the &v...
Andrew Edwards <ridimz_at yahoo.dot.com> writes:
```This is an attempt to generate conversation on variadic functions, the
implementation of which would ultimately lesson our search for an
adequate solution to the D I/O issue.

Note: I'm often uncomfortable referring to arguments and parameters in
speech and writing so I'll be referring to all such items as
arguments.

------print.d------
int main()
{
double d;
char c;
print(d,c);
}

void print(char[] start, ...)
{
}

-------------------
compiler errors messages:
print.d(5): function print (char[]start,...) does not match argument
types (double,char)
print.d(5): cannot implicitly convert double to char[]

Given the function print(), as defined above, it is clear to see (from
the generated error messages) that the compiler is capable of not only
discerning the total numbers of arguments used to call that function,
but also the type of each of those arguments.

IMHO it wouldn't be too unreasonable to assume that in order for it to
gather this information, the compiler must know beforehand where each of
those arguments are stored (i.e. the address of each argument) in
memory.

Now suppose for a moment that we had a built-in type-pointer, called
"variant", that points to and assumes the characteristics of any, and
all, other built-in types. Making the following legal:

variant variable; // value automatically dereferenced to the value of
// whatever it points to. (Does NOT return an
// address and is NOT a copy!)
void space;
char[] string;
int i; double j; char c; etc...

variable = space;  // typeof(variable) -> void
variable = string; // typeof(variable) -> char[]
variable = i;      // typeof(variable) -> int
variable = j;      // typeof(variable) -> double
variable = c;      // typeof(variable) -> char
etc...

Wouldn't this allow us to deal with variables at compile time without
knowing it's actual type?

Hold that thought for a moment!

Review of the stdarg functions reveal that variable arguments are
arranged sequentially in memory. Simply knowing the size of each argument
allows us to move from one memory location to another within the
argument list.

So what if we stored those arguments in an array (call it "sequence" if
you will) internally to the compiler whenever a variadic function is
encountered? [e.g. echo(char[] v, int i, char c, ...) or scan(...), but
not foo(char ch) or bar()]

Wouldn't we be able to access each argument individually through array
indexing (akin to accessing arguments passed in to the main() function)?

Now suppose the array was an associative array:

variant[int] sequence; // syntactic sugar for this would be ...

Wouldn't we be able to foreach through each of those arguments and
manipulate them without regard to type?

This functionality could drastically reduce our search for a proper I/O
facility for The D Language and completely eliminate the problem of
traversing arguments of a variadic function (thereby eliminating the
need for std.c.stdarg).

Your thoughts and opinions are greatly appreciated.

If I'm somewhere off in coocoo land, please don't be afraid to say so!!!

Thanks,
Andrew
```
Jun 08 2004
J C Calvarese <jcc7 cox.net> writes:
```Andrew Edwards wrote:
This is an attempt to generate conversation on variadic functions, the
implementation of which would ultimately lesson our search for an
adequate solution to the D I/O issue.

Note: I'm often uncomfortable referring to arguments and parameters in
speech and writing so I'll be referring to all such items as
arguments.

------print.d------
int main()
{
double d;
char c;
print(d,c);
}

void print(char[] start, ...)
{
}

-------------------
compiler errors messages:
print.d(5): function print (char[]start,...) does not match argument
types (double,char)
print.d(5): cannot implicitly convert double to char[]

Given the function print(), as defined above, it is clear to see (from
the generated error messages) that the compiler is capable of not only
discerning the total numbers of arguments used to call that function,
but also the type of each of those arguments.

IMHO it wouldn't be too unreasonable to assume that in order for it to
gather this information, the compiler must know beforehand where each of
those arguments are stored (i.e. the address of each argument) in
memory.

Now suppose for a moment that we had a built-in type-pointer, called
"variant", that points to and assumes the characteristics of any, and
all, other built-in types. Making the following legal:

variant variable; // value automatically dereferenced to the value of
// whatever it points to. (Does NOT return an
// address and is NOT a copy!)
void space;
char[] string;
int i; double j; char c; etc...

variable = space;  // typeof(variable) -> void
variable = string; // typeof(variable) -> char[]
variable = i;      // typeof(variable) -> int
variable = j;      // typeof(variable) -> double
variable = c;      // typeof(variable) -> char
etc...

Wouldn't this allow us to deal with variables at compile time without
knowing it's actual type?

Hold that thought for a moment!

Review of the stdarg functions reveal that variable arguments are
arranged sequentially in memory. Simply knowing the size of each argument
allows us to move from one memory location to another within the
argument list.

So what if we stored those arguments in an array (call it "sequence" if
you will) internally to the compiler whenever a variadic function is
encountered? [e.g. echo(char[] v, int i, char c, ...) or scan(...), but
not foo(char ch) or bar()]

Wouldn't we be able to access each argument individually through array
indexing (akin to accessing arguments passed in to the main() function)?

Now suppose the array was an associative array:

variant[int] sequence; // syntactic sugar for this would be ...

Wouldn't we be able to foreach through each of those arguments and
manipulate them without regard to type?

This functionality could drastically reduce our search for a proper I/O
facility for The D Language and completely eliminate the problem of
traversing arguments of a variadic function (thereby eliminating the
need for std.c.stdarg).

Your thoughts and opinions are greatly appreciated.

If I'm somewhere off in coocoo land, please don't be afraid to say so!!!

Thanks,
Andrew

I think a built-in variant type would be Fantastic!

It would also help us seduce programmers from all kinds of languages
that have easy variant support, such as Visual Basic, VBScript,
JavaScript, JScript, etc. (Of course some might also consider this a
disadvantage. ;) )

Now we just need to twist Walter's arm...

--
Justin (a/k/a jcc7)
http://jcc_7.tripod.com/d/
```
Jun 08 2004
Derek Parnell <derek psych.ward> writes:
```On Tue, 08 Jun 2004 21:54:15 -0400, Andrew Edwards wrote:

This is an attempt to generate conversation on variadic functions, the
implementation of which would ultimately lesson our search for an
adequate solution to the D I/O issue.

Note: I'm often uncomfortable referring to arguments and parameters in
speech and writing so I'll be referring to all such items as
arguments.

------print.d------
int main()
{
double d;
char c;
print(d,c);
}

void print(char[] start, ...)
{
}

-------------------
compiler errors messages:
print.d(5): function print (char[]start,...) does not match argument
types (double,char)
print.d(5): cannot implicitly convert double to char[]

Given the function print(), as defined above, it is clear to see (from
the generated error messages) that the compiler is capable of not only
discerning the total numbers of arguments used to call that function,
but also the type of each of those arguments.

IMHO it wouldn't be too unreasonable to assume that in order for it to
gather this information, the compiler must know beforehand where each of
those arguments are stored (i.e. the address of each argument) in
memory.

Now suppose for a moment that we had a built-in type-pointer, called
"variant", that points to and assumes the characteristics of any, and
all, other built-in types. Making the following legal:

variant variable; // value automatically dereferenced to the value of
// whatever it points to. (Does NOT return an
// address and is NOT a copy!)
void space;
char[] string;
int i; double j; char c; etc...

variable = space;  // typeof(variable) -> void
variable = string; // typeof(variable) -> char[]
variable = i;      // typeof(variable) -> int
variable = j;      // typeof(variable) -> double
variable = c;      // typeof(variable) -> char
etc...

Wouldn't this allow us to deal with variables at compile time without
knowing it's actual type?

Hold that thought for a moment!

Review of the stdarg functions reveal that variable arguments are
arranged sequentially in memory. Simply knowing the size of each argument
allows us to move from one memory location to another within the
argument list.

So what if we stored those arguments in an array (call it "sequence" if
you will) internally to the compiler whenever a variadic function is
encountered? [e.g. echo(char[] v, int i, char c, ...) or scan(...), but
not foo(char ch) or bar()]

Wouldn't we be able to access each argument individually through array
indexing (akin to accessing arguments passed in to the main() function)?

Now suppose the array was an associative array:

variant[int] sequence; // syntactic sugar for this would be ...

Wouldn't we be able to foreach through each of those arguments and
manipulate them without regard to type?

This functionality could drastically reduce our search for a proper I/O
facility for The D Language and completely eliminate the problem of
traversing arguments of a variadic function (thereby eliminating the
need for std.c.stdarg).

Your thoughts and opinions are greatly appreciated.

If I'm somewhere off in coocoo land, please don't be afraid to say so!!!

Thanks,
Andrew

Love it!

I'm *so* used to working with polymorphic variables that I know I'll be
missing them in D. And your idea will not cause compiled programs that DO
NOT use the variant type to slow down any either. So, if a coder chooses to
use a variant datatye then they accept the (slight) performance hit in
order to use a *much* easier programming paradigm.

I assume that we could work with classes and structures in this scheme too.

--
Derek
Melbourne, Australia
9/Jun/04 2:36:25 PM
```
Jun 08 2004
Ben Hinkle <bhinkle4 juno.com> writes:
```Andrew Edwards wrote:

This is an attempt to generate conversation on variadic functions, the
implementation of which would ultimately lesson our search for an
adequate solution to the D I/O issue.

Note: I'm often uncomfortable referring to arguments and parameters in
speech and writing so I'll be referring to all such items as
arguments.

------print.d------
int main()
{
double d;
char c;
print(d,c);
}

void print(char[] start, ...)
{
}

-------------------
compiler errors messages:
print.d(5): function print (char[]start,...) does not match argument
types (double,char)
print.d(5): cannot implicitly convert double to char[]

Given the function print(), as defined above, it is clear to see (from
the generated error messages) that the compiler is capable of not only
discerning the total numbers of arguments used to call that function,
but also the type of each of those arguments.

IMHO it wouldn't be too unreasonable to assume that in order for it to
gather this information, the compiler must know beforehand where each of
those arguments are stored (i.e. the address of each argument) in
memory.

Now suppose for a moment that we had a built-in type-pointer, called
"variant", that points to and assumes the characteristics of any, and
all, other built-in types. Making the following legal:

variant variable; // value automatically dereferenced to the value of
// whatever it points to. (Does NOT return an
// address and is NOT a copy!)
void space;
char[] string;
int i; double j; char c; etc...

variable = space;  // typeof(variable) -> void
variable = string; // typeof(variable) -> char[]
variable = i;      // typeof(variable) -> int
variable = j;      // typeof(variable) -> double
variable = c;      // typeof(variable) -> char
etc...

Wouldn't this allow us to deal with variables at compile time without
knowing it's actual type?

Hold that thought for a moment!

Review of the stdarg functions reveal that variable arguments are
arranged sequentially in memory. Simply knowing the size of each argument
allows us to move from one memory location to another within the
argument list.

So what if we stored those arguments in an array (call it "sequence" if
you will) internally to the compiler whenever a variadic function is
encountered? [e.g. echo(char[] v, int i, char c, ...) or scan(...), but
not foo(char ch) or bar()]

Wouldn't we be able to access each argument individually through array
indexing (akin to accessing arguments passed in to the main() function)?

Now suppose the array was an associative array:

variant[int] sequence; // syntactic sugar for this would be ...

Wouldn't we be able to foreach through each of those arguments and
manipulate them without regard to type?

This functionality could drastically reduce our search for a proper I/O
facility for The D Language and completely eliminate the problem of
traversing arguments of a variadic function (thereby eliminating the
need for std.c.stdarg).

Your thoughts and opinions are greatly appreciated.

If I'm somewhere off in coocoo land, please don't be afraid to say so!!!

Thanks,
Andrew

three thoughts come to mind:
1) variant feels very close to Object except variant also works for
primitive types (reminds me of post long ago about boxing/unboxing or
wrapping primitive types)
2) have you looked into using a struct like
struct variant {
TypeInfo* ti;
void* data;
}
3) variant is somewhat like a plain old void* since it isn't clear what
"manipulate them without regard to type" would mean in a compiled language.
What operations should be supported by a variant? addition? toString?
printf?

I think this is an interesting topic but is hard to work into a compiled
language where there isn't any RTTI for primitive types.
```
Jun 09 2004
Andrew Edwards <Andrew_member pathlink.com> writes:
```In article <ca70oe\$2adn\$1 digitaldaemon.com>, Ben Hinkle says...
Andrew Edwards wrote:

This is an attempt to generate conversation on variadic functions, the
implementation of which would ultimately lesson our search for an
adequate solution to the D I/O issue.

Note: I'm often uncomfortable referring to arguments and parameters in
speech and writing so I'll be referring to all such items as
arguments.

------print.d------
int main()
{
double d;
char c;
print(d,c);
}

void print(char[] start, ...)
{
}

-------------------
compiler errors messages:
print.d(5): function print (char[]start,...) does not match argument
types (double,char)
print.d(5): cannot implicitly convert double to char[]

Given the function print(), as defined above, it is clear to see (from
the generated error messages) that the compiler is capable of not only
discerning the total numbers of arguments used to call that function,
but also the type of each of those arguments.

IMHO it wouldn't be too unreasonable to assume that in order for it to
gather this information, the compiler must know beforehand where each of
those arguments are stored (i.e. the address of each argument) in
memory.

Now suppose for a moment that we had a built-in type-pointer, called
"variant", that points to and assumes the characteristics of any, and
all, other built-in types. Making the following legal:

variant variable; // value automatically dereferenced to the value of
// whatever it points to. (Does NOT return an
// address and is NOT a copy!)
void space;
char[] string;
int i; double j; char c; etc...

variable = space;  // typeof(variable) -> void
variable = string; // typeof(variable) -> char[]
variable = i;      // typeof(variable) -> int
variable = j;      // typeof(variable) -> double
variable = c;      // typeof(variable) -> char
etc...

Wouldn't this allow us to deal with variables at compile time without
knowing it's actual type?

Hold that thought for a moment!

Review of the stdarg functions reveal that variable arguments are
arranged sequentially in memory. Simply knowing the size of each argument
allows us to move from one memory location to another within the
argument list.

So what if we stored those arguments in an array (call it "sequence" if
you will) internally to the compiler whenever a variadic function is
encountered? [e.g. echo(char[] v, int i, char c, ...) or scan(...), but
not foo(char ch) or bar()]

Wouldn't we be able to access each argument individually through array
indexing (akin to accessing arguments passed in to the main() function)?

Now suppose the array was an associative array:

variant[int] sequence; // syntactic sugar for this would be ...

Wouldn't we be able to foreach through each of those arguments and
manipulate them without regard to type?

This functionality could drastically reduce our search for a proper I/O
facility for The D Language and completely eliminate the problem of
traversing arguments of a variadic function (thereby eliminating the
need for std.c.stdarg).

Your thoughts and opinions are greatly appreciated.

If I'm somewhere off in coocoo land, please don't be afraid to say so!!!

Thanks,
Andrew

three thoughts come to mind:
1) variant feels very close to Object except variant also works for
primitive types (reminds me of post long ago about boxing/unboxing or
wrapping primitive types)

The idea is for it to be a self-dereferencing pointer (similar to the &var of
C++ or the inout parameter of D). Modifying the variant directly affects the
variable to which it points, but it should facilitate pointing to a different
variable later on.

2) have you looked into using a struct like
struct variant {
TypeInfo* ti;
void* data;
}

As a matter of fact I have. This, however, does not fit the bill. The variant
should assume the characteristics of the variable to which it points.

double trouble;  // initial value nan
variant var;     // initial value null
var = trouble;   // var takes the address of trouble (var == nan)
// maybe we could recall the adressof operator (&)?
var = 6.66;      // trouble = 6.66

typeof(var) foo; // foo is of type double

printf(toString(var));  // calls toString(double)

3) variant is somewhat like a plain old void* since it isn't clear what
"manipulate them without regard to type" would mean in a compiled language.
What operations should be supported by a variant? addition? toString?
printf?

Not quite! "variant" is like a void* in the sense that it can point to
anything. However, unlike void*, once it points to a variable it assumes
all characteristics of that variable. If it points to an int, you can
treat the variant as if it were an int. All changes made to the variant
would <strong>*directly*</strong> affect the variable to which it points.
Absolutely no need for casting as with void*s.

I think this is an interesting topic but is hard to work into a compiled
language where there isn't any RTTI for primitive types.

This is where I get confused. It is also the purpose of the little example
provided earlier. If the compiler is capable of identifying that the
incorrect number and type of arguments (and vice-versa) are used to call a
function, isn't that enought information to determine the type of variable
to which a variant points?
```
Jun 09 2004