Community

I've been thinking for this feature for a while. An anonymous struct is
basically what it sound like, a struct without a name. The inserting
part is its members. If two anonymous structs have the same members (not
necessarily in the same order) they are considered to be of the same
type. This shows how anonymous structs looks like:
{ int x, int y } point = { y: 4, x: 5 };
auto point2 = { x: 1, y: 2 };
point = point2;
In this example "point" and "point2" are of the same type since they
have the same members. This is basically lowered to something similar to:
struct __AnonymousStruct_int_x_int_y
{
int x;
int y;
}
__AnonymousStruct_int_x_int_y point;
point.y = 4;
point.x = 5;
__AnonymousStruct_int_x_int_y point2;
point2.x = 1;
point2.y = 2;
point = point2;
The compiler will implicitly generate a new struct type with a name that
will always be the same if it has the same members. These structs will
then behave just like any other structs, accessing members and so on.
assert(point2.x == 1);
assert(point.y == 2);
The advantage of anonymous structs is that they can be declared in
place, in function declartions for example:
void foo ({ int x, int y } point)
{
}
foo({ y: 5, x: 3 });
When calling a function and passing in an anonymous structs it's
possible to drop the braces to get a more pleasing and less verbose syntax:
foo(y: 5, x: 3);
With this syntax sugar we can basically get named parameters. With the
braces it also looks like JSON.
Anonymous structs can be implicitly converted to and from regular named
struts:
* Named struct to anonymous struct:
struct Bar
{
int x;
int y;
}
foo(Bar(1, 2));
* Anonymous struct to named struct:
void bar (Bar b) {}
bar(x: 3, y: 4);
It would also be nice to have opDispatch soak up everything that doesn't
match, if it's declared in a named struct:
struct Options
{
int x;
int y;
private Variant[string] members;
void opDispatch (string name, T) (T t)
{
members[name] = Variant(t);
}
}
void fooBar (Options options) {}
fooBar(x: 5, a: "asd", y: 1.2, b: 4);
"x" and "y" are matched with the regular members, "a" and "b" are
matched to opDispatch which takes care of them.
Perhaps this initializer syntax can be used for classes as well:
class FooBar
{
int x;
int y;
}
FooBar fb = { x: 3, y: 5 };
The above would be lowered to:
FooBar fb = new FooBar();
fb.x = 3;
fb.y = 5;
Thoughts?
--
/Jacob Carlborg

On Monday, 11 February 2013 at 21:30:52 UTC, Jacob Carlborg wrote:
> I've been thinking for this feature for a while. An anonymous
> struct is basically what it sound like, a struct without a
> name. The inserting part is its members. If two anonymous
> structs have the same members (not necessarily in the same
> order) they are considered to be of the same type. This shows
> how anonymous structs looks like:
>
> { int x, int y } point = { y: 4, x: 5 };
> auto point2 = { x: 1, y: 2 };
> point = point2;
>
> In this example "point" and "point2" are of the same type since
> they have the same members. This is basically lowered to
> something similar to:
What if there's another anonymous struct that has a little more?
{ int x, int y } point = { y: 4, x: 5 };
{ int x, int y, int color } color_point
= { y: 4, x: 5, color: 0x000000 };
//which anonymous struct does it go with?
//Or can auto only work with named/returned structs?
auto point2 = { x: 1, y: 2 };
point = point2; //error, point2 type void _error
We can instantiate structs with fewer arguments than elements
they hold. It would either have to go the safe route, or try it's
best to either be 'safe' or 'whatever seems to work' until you
change something and break it utterly with no description of
'what' it is.
Anonymous structs would be more useful as single instances like
unions can be in C. (I think it's disallowed in D, or I had
trouble with them)
Nick Sabalausky wrote:
>Isn't that all basically syntax sugar for tuples?
Maybe. I would think an explicit tuple would be better.

On Monday, 11 February 2013 at 21:30:52 UTC, Jacob Carlborg wrote:
> The advantage of anonymous structs is that they can be declared
> in place, in function declartions for example:
>
> void foo ({ int x, int y } point)
> {
> }
>
> foo({ y: 5, x: 3 });
At the first look it seems interesting, but imagine that you need
to change one type or add more members to that struct, have you
imagined the mess to change all those declarations?
Because that case I prefer the old way:
void foo(MyPointStruct point)
{
}
Any changing in "MyPointStruct" will be consumed by all the code.

On Monday, 11 February 2013 at 21:30:52 UTC, Jacob Carlborg wrote:
> { int x, int y } point = { y: 4, x: 5 };
That looks like it would confuse the parser because it looks
almost exactly like a BlockStatement until you get several tokens
in.

On 2013-02-11 22:54, Nick Sabalausky wrote:
> Isn't that all basically syntax sugar for tuples?
I didn't really thing of tuples, but it might be considered that. I
assume you are referring to std.typecons.Tuple? Except the syntax, there
are some limitations with Tuple. It cannot be implicitly converted to
other types based on its members. I don't know if that's possible to
fix. It can also contain just types, or just values.
BTW, isn't tuples and structs basically the same thing in the end.
--
/Jacob Carlborg

On 2013-02-11 23:20, Era Scarecrow wrote:
> What if there's another anonymous struct that has a little more?
>
> { int x, int y } point = { y: 4, x: 5 };
> { int x, int y, int color } color_point
> = { y: 4, x: 5, color: 0x000000 };
> //which anonymous struct does it go with?
> //Or can auto only work with named/returned structs?
> auto point2 = { x: 1, y: 2 };
>
> point = point2; //error, point2 type void _error
"point2" is completely independent of the other declarations. But you
can think of it having the same type as "point". It can also be
implicitly converted to "color_point". It's not the actual type that's
interesting, it's the members. The compiler checks the members to see if
two values are of the same types.
> We can instantiate structs with fewer arguments than elements they
> hold. It would either have to go the safe route, or try it's best to
> either be 'safe' or 'whatever seems to work' until you change something
> and break it utterly with no description of 'what' it is.
It's not the actual type that's interesting, as long as the members
match they're considered to be the same type.
--
/Jacob Carlborg

On 2013-02-11 23:58, MattCoder wrote:
> On Monday, 11 February 2013 at 21:30:52 UTC, Jacob Carlborg wrote:
>> The advantage of anonymous structs is that they can be declared in
>> place, in function declartions for example:
>>
>> void foo ({ int x, int y } point)
>> {
>> }
>>
>> foo({ y: 5, x: 3 });
>
> At the first look it seems interesting, but imagine that you need to
> change one type or add more members to that struct, have you imagined
> the mess to change all those declarations?
If you add a new member to the anonymous struct declared in "foo" any
existing call will still match. That's just like the current initializer
syntax works:
struct Bar
{
int a;
int b;
}
Bar bar = { b: }; // "a" is default initialized
If you remove a member from the anonymous struct declared in "foo" you
will get a compile error since there will be a member that doesn't match.
> Because that case I prefer the old way:
>
> void foo(MyPointStruct point)
> {
> }
>
> Any changing in "MyPointStruct" will be consumed by all the code.
I'm not sure I see the difference compared with the anonymous struct.
--
/Jacob Carlborg

On 2013-02-12 00:17, Brian Schott wrote:
> That looks like it would confuse the parser because it looks almost
> exactly like a BlockStatement until you get several tokens in.
That might be the case, I have no idea. Is there another syntax that
would work better that could fit in a function declaration as well?
--
/Jacob Carlborg