March 21, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A0B2A.97E27D89@deming-os.org...
> You would declare a varargs function much like C, but you would not define
a
> body for it.  The D version of printf might be:
>     char[] printf(char[], ...);
> The key here is that the first argument is the same type as the return
value.
>
> Then you would define a series of functions that had the same name and
return
> value, that had the same arguments, plus a single additional argument:
>     char[] printf(char[], int);
>     char[] printf(char[], char);
>     char[] printf(char[], Object);
>     char[] printf(char[], char[]);
>     etc...
>
> The compiler would then turn a varargs call into a recursive call:
>     D code:
>         printf("%d: %s\n", 123, "abc");
>     Expanded by the compiler to be:
>         printf(printf("%d: %s\n", 123), "abc");
>

This is very promising - let's talk about it.

It seems to me that the "recursive" behavior is kinda backwards.  The rightmost argument is evaluated first, and this may be bad.  But, the part about using polymorphism for a variable argument list is interesting, and it made me think.

How about something like the VB ParamArray, but smarter?

Start with the function declaration:

void printf(char[], PrintfParam args...)
{
// Function body


"type args..." is like "type args[]" but signals that the compiler should collect up the arguments into the array. "type... args" should be a synonym of "type args..." just as "type[] array" is the same as "type array[]". The body of this function treats args as if it were a regular dynamic array, because it is.

When a user codes:
    char[] name = "Cecil";
    printf("My name is %s\n", name);

..the compiler does the equivalent of this:

   PrintfParms[] _t;
   _t[0] = new PrintfParms(name);
   printf("My name is %s\n", _t);

Rules:

    Each function argument must be implicitly compatible with the argument
type; else,

    Each argument must be convertible to the argument type via the type's
constructor; else,

    The argument's not valid and the compiler prints an error.

Only the final parameter to a function can be varargs, just like C.

I like this better than the universal VARIANT type that VB uses, since that way allows programmers to pass types that the function doesn't expect, and/or requires the called function to expect every type.  The argument type only needs constructors for types it can deal with.

You can't make a varargs function in C which is allowed to take zero arguments.  But with this method, you can:  void NoArgs(Type args...) could be called with no arguments, and would receive a zero-length array.

"<type> args..." is implicitly compatible with "<type> args[]" and, as such, can be passed around between functions, like C's va_list can.  But it's even better: you can write code to construct the a "<type> args[]", but you *can't* construct a va_list in C except by calling a varargs function.

Discussion?

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)


March 21, 2002
Richard Krehbiel wrote:

> It seems to me that the "recursive" behavior is kinda backwards.  The rightmost argument is evaluated first, and this may be bad.

Unless I'm misunderstanding you - no, this isn't true.  The leftmost "vararg" is given to the innermost function, and is thus evaluated first.  Or am I missing what you mean?

> But, the part
> about using polymorphism for a variable argument list is interesting, and it
> made me think.
>
> How about something like the VB ParamArray, but smarter?

I like the idea you proposed, though making them actually be cast to the right
type (even by a constructor) seems hack-ish to me (personal opinion).

Maybe some sort of union-like syntax?  You would tell the compiler which types are valid in the varargs array.  The array would be an array of structures, each element of which contains an identifer telling the type and a union.

Still pondering...

--
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))) ]


March 21, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A2BDA.9C26890A@deming-os.org...

> I like the idea you proposed, though making them actually be cast to the
right
> type (even by a constructor) seems hack-ish to me (personal opinion).

Oh yes!
Some syntax to construct arrays on the fly would be needed in this case.

> Maybe some sort of union-like syntax?  You would tell the compiler which
types
> are valid in the varargs array.  The array would be an array of
structures, each
> element of which contains an identifer telling the type and a union.

... which leads us back to the variants (or, at least, some sort of them).




March 21, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A2BDA.9C26890A@deming-os.org...
> Richard Krehbiel wrote:
>
> > It seems to me that the "recursive" behavior is kinda backwards.  The rightmost argument is evaluated first, and this may be bad.
>
> Unless I'm misunderstanding you - no, this isn't true.  The leftmost
"vararg" is
> given to the innermost function, and is thus evaluated first.  Or am I
missing
> what you mean?

No, that's what I meant; I misread it to mean that vararg(a, b, c) would
convert to vararg(a, vararg(b, c)).  But now I've re-read it and I see you
meant vararg(a, b, c) becomes vararg(vararg(a, b), c).  Um - that's still
hard to read.  But I think I get it.  :-)

> > But, the part
> > about using polymorphism for a variable argument list is interesting,
and it
> > made me think.
> >
> > How about something like the VB ParamArray, but smarter?
>
> I like the idea you proposed, though making them actually be cast to the
right
> type (even by a constructor) seems hack-ish to me (personal opinion).
>
> Maybe some sort of union-like syntax?  You would tell the compiler which
types
> are valid in the varargs array.  The array would be an array of
structures, each
> element of which contains an identifer telling the type and a union.

Actually I was trying to avoid having unions and a suite of compiler-defined run-time constants for object kinds.  I don't know what it is that I dislike about it, though.

In my scheme you can use unions with type IDs if you wish, and you get to define the type IDs too.

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)



March 21, 2002
"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A0B2A.97E27D89@deming-os.org...

> You would declare a varargs function much like C, but you would not define
a
> body for it.  The D version of printf might be:
>     char[] printf(char[], ...);
> The key here is that the first argument is the same type as the return
value.
>
> Then you would define a series of functions that had the same name and
return
> value, that had the same arguments, plus a single additional argument:
>     char[] printf(char[], int);
>     char[] printf(char[], char);
>     char[] printf(char[], Object);
>     char[] printf(char[], char[]);
>     etc...
>
> The compiler would then turn a varargs call into a recursive call:
>     D code:
>         printf("%d: %s\n", 123, "abc");
>     Expanded by the compiler to be:
>         printf(printf("%d: %s\n", 123), "abc");

I like the idea! Maybe the syntax could be tweaked a bit, a special
attribute
or something:

    vararg printf(char[]);
    ...

Anyhow, it seems like a good solution to me. Completely typesafe, with
ability
to limit range of types that could be passed to a function, rather fast,
and should be easier to implement than paramarrays (I think).

What do you think of this, Walter?


March 21, 2002
"Richard Krehbiel" <rich@kastle.com> wrote in message news:a7dbhq$s5k$1@digitaldaemon.com...
> "Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:3C9A2BDA.9C26890A@deming-os.org...
> > Richard Krehbiel wrote:
> >
> > > It seems to me that the "recursive" behavior is kinda backwards.  The rightmost argument is evaluated first, and this may be bad.
> >
> > Unless I'm misunderstanding you - no, this isn't true.  The leftmost
> "vararg" is
> > given to the innermost function, and is thus evaluated first.  Or am I
> missing
> > what you mean?
>
> No, that's what I meant; I misread it to mean that vararg(a, b, c) would
> convert to vararg(a, vararg(b, c)).  But now I've re-read it and I see you
> meant vararg(a, b, c) becomes vararg(vararg(a, b), c).  Um - that's still
> hard to read.  But I think I get it.  :-)
>
> > > But, the part
> > > about using polymorphism for a variable argument list is interesting,
> and it
> > > made me think.
> > >
> > > How about something like the VB ParamArray, but smarter?
> >
> > I like the idea you proposed, though making them actually be cast to the
> right
> > type (even by a constructor) seems hack-ish to me (personal opinion).
> >
> > Maybe some sort of union-like syntax?  You would tell the compiler which
> types
> > are valid in the varargs array.  The array would be an array of
> structures, each
> > element of which contains an identifer telling the type and a union.
>
> Actually I was trying to avoid having unions and a suite of
compiler-defined
> run-time constants for object kinds.  I don't know what it is that I
dislike
> about it, though.
>
> In my scheme you can use unions with type IDs if you wish, and you get to define the type IDs too.
>
> --
> Richard Krehbiel, Arlington, VA, USA
> rich@kastle.com (work) or krehbiel3@comcast.net  (personal)
>
>
> ----- Original Message -----
From: "Richard Krehbiel" <rich@kastle.com>
Newsgroups: D
Sent: Thursday, March 21, 2002 10:15 PM
Subject: Re: Type-safe varargs


> In my scheme you can use unions with type IDs if you wish, and you get to define the type IDs too.

... and you have to fill those unions yourself, which just kills the idea. I want to be able to write print() in a single line, like this:

    print("Hello, world!", foo, bar);

And not like this:

    print(new PrintArg("Hello, world!"), new PrintArg(foo), new
PrintArg(bar));





March 21, 2002
"Pavel Minayev" <evilone@omen.ru> wrote in message news:a7dbqt$sd1$1@digitaldaemon.com...
>
> "Richard Krehbiel" <rich@kastle.com> wrote in message news:a7dbhq$s5k$1@digitaldaemon.com...
> > Actually I was trying to avoid having unions and a suite of
> > compiler-defined run-time constants for object kinds.
> > I don't know what it is that I dislike about it, though.
> >
> > In my scheme you can use unions with type IDs if you wish, and you get
to
> > define the type IDs too.
>
> ... and you have to fill those unions yourself, which just kills the idea. I want to be able to write print() in a single line, like this:
>
>     print("Hello, world!", foo, bar);
>
> And not like this:
>
>     print(new PrintArg("Hello, world!"), new PrintArg(foo), new
> PrintArg(bar));

What I meant was the declared homogenous parameter type could, within it's various constructors, set up a union containing the types, and set a type ID; not that the caller of printf would have to do it.

--
Richard Krehbiel, Arlington, VA, USA
rich@kastle.com (work) or krehbiel3@comcast.net  (personal)



March 21, 2002
>    aligned = address + align - (address % align);

>
> [1] The compiler can't see that align is always going
> to be a power of 2, so it can't convert the mod to a
> mask.[2]


Well... Try this:

// obvious solution, isn't it? ;-)

aligned = (address + align) & ~(align-1);


March 21, 2002
Serge K wrote:
>>   aligned = address + align - (address % align);
>>
> 
>>[1] The compiler can't see that align is always going
>>to be a power of 2, so it can't convert the mod to a
>>mask.[2]
>>
> 
> 
> Well... Try this:
> 
> // obvious solution, isn't it? ;-)
> 
> aligned = (address + align) & ~(align-1);

Well, yes, but then, so is using "unsigned".

-R


March 21, 2002
> > // obvious solution, isn't it? ;-)
> >
> > aligned = (address + align) & ~(align-1);
>
> Well, yes, but then, so is using "unsigned".

In such situation "unsigned" cannot help compiler to replace "%" with masking...

(I'm not against unsigned integer types - use them all the time if it fits ;-)
and I really don't like that ">>" is an arithmetic shift in Java.
It's against logic :
"<<" - left shift with zero-filling,
">>" - right shift with sign-filling (???),
">>>" - right shift with zero-filling (???).
Than again - I use shifts mostly for bit-twiddling.