Proposal: real struct literals

Jarrett Billingsley kb3ctd2 at yahoo.com
Tue Jun 24 13:30:28 PDT 2008


The status of struct literals and construction in D1 has always really 
grated on me.  So I've come up with a possible alternative syntax which 
would supplant the current syntax.  (I've reproduced this in an enhancement 
request in bugzilla.)

The current struct literals use a function-call-looking style to construct 
structs.  This has some minor issues:

- If you define a static opCall for the struct, even if it isn't supposed to 
be used as a "constructor", you can no longer use struct literals on that 
struct.  I'm not sure if this was an intended aspect of the design, but it 
becomes annoying to implement that static opCall without using struct 
literals!

- Once structs get real constructors, the opCall "blessing" becomes 
superfluous, and I hope plans are in the works to remove it.

- Using a struct literal does not call a function, so it seems weird to use 
syntax that looks like a function call to construct it.

The much more serious issue is that in terms of features and syntax, static 
struct initialization and struct literals are *completely* different.

struct S
{
    int x, y;
    char[] s;
}

void foo()
{
    static S s = { 5, y: 10, s: "hi!" };
    auto s2 = S(5, 10, "hi!");
}

They have completely different syntax and features.  Static struct 
initializers are far more powerful: you can name members, initialize them 
out of order, and skip arbitrary members.  The struct literal syntax is far 
more limited: you must initialize the members in order (which quickly gets 
out of hand for more than 2 or 3 members), you can't name them, and you can 
only skip members at the end of the struct.

So I propose that struct "literals" be replaced with actual struct literals, 
which look like static struct initializers.  There is a very obvious, 
simple, unambiguous syntax for this: an identifier, followed by a static 
struct initializer.  Crazy, I know!

static s = S{ 5, y: 10, s: "hi!" };
auto s2 =  S{ 5, y: 10, s: "hi!" };

Now struct literals have all the nice capabilities of static struct 
initializers.  Static struct initializers actually no longer have to be 
special-cased.  The declaration of s above expects the initializer to be 
evaluatable at compile-time, just like any other static declaration, and so 
the struct literal on the RHS now just has to contain all 
compile-time-evaluatable values.  No problem.

------

Dreaming, this also opens up the possibility for named function parameters. 
Consider a function:

struct Args
{
    void* dest;
    void* src;
    size_t num;
}

void memcopy(Args args)
{
    // Copy args.num bytes from args.src to args.dest
}

...

memcopy(Args{ dst, src, 8 }); // Use ordered params
memcopy(Args{ src: a, dest: b, num: a.length }); // Use named params

The issue with this is that you have to have a different named struct for 
every function that takes this style of parameters.  But -- here's the cool 
trick -- extend typesafe variadic parameters to take structures like they 
already do for classes...

void memcopy(Args args...) // hee hee!

memcopy(dst, src, 8); // woah, looks like a normal function..
memcopy(src: a, dest: b, num: a.length); // bam, named params for free!

Having colons in the parameter list for a function call is also unambiguous. 





More information about the Digitalmars-d mailing list