digitalmars.D - proposed syntax for tuple: t{} and TypeTuple: T{} (cf precedent of
- Timothee Cour via Digitalmars-d (12/12) Apr 04 2016 {} for tuples hasn't worked out since it was deemed ambiguous with
- ag0aep6g (20/27) Apr 05 2016 In existing syntax, most {...} blocks can contain semicolon separated
- Nick Treleaven (9/19) Apr 08 2016 Functions can return std.typecons.tuple. All that is needed IMO
- ZombineDev (27/40) Apr 05 2016 I don't think that t or T is needed in front of {}.
- jmh530 (7/13) Apr 05 2016 Is making this
- ZombineDev (3/16) Apr 05 2016 Yes, I think it would be a breaking change, if my proposal is
- Timon Gehr (22/66) Apr 05 2016 This is moot.
- ZombineDev (23/104) Apr 05 2016 The answer to this question and all similar cases is that is that
- Timon Gehr (25/134) Apr 05 2016 There might have been some underlying misunderstanding here.
- Jack Stouffer (3/16) Apr 05 2016 Tuple and AliasSeq are library types, so the chance that they
- Adam D. Ruppe (5/7) Apr 05 2016 Yes on Tuple, but AliasSeq actually is in the language (just
{} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}
Apr 04 2016
On 05.04.2016 07:45, Timothee Cour via Digitalmars-d wrote:How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ----In existing syntax, most {...} blocks can contain semicolon separated declarations. Your proposed constructs would be comma separated lists. I'd vote for other delimiters because of that. Static struct initializers are the exception in existing syntax, but they stick out, and they're not used often. Parentheses are not an option because of arbitrary identifiers in function calls and such, and making `t`/`T` keywords for this purpose doesn't seem wise. That leaves square brackets. `t[...]` doesn't clash with anything, as far as I see. And it makes a good fit for the feature, in my opinion. So I'd prefer `t[...]` over `t{...}`. I'm not sure if the new syntax is worth adding, though. `T{...}` (or `T[...]`) saves just one character over `T!(...)`. The latter can be done without touching the language. For the value tuple, one can do `alias t = std.typecons.tuple;` which gives you `t(...)`. That's just as short as `t{...}`. But maybe std.typecons.tuple is lacking somehow. A more proper `t(...)` could be implemented when functions could return tuples, which would also be desirable if we had `t{...}` syntax. So implementing `T!(...)` and `t(...)` in D seems like the way to go to me. And maybe allow functions to return tuples.
Apr 05 2016
On Tuesday, 5 April 2016 at 14:00:46 UTC, ag0aep6g wrote:I'm not sure if the new syntax is worth adding, though. `T{...}` (or `T[...]`) saves just one character over `T!(...)`. The latter can be done without touching the language. For the value tuple, one can do `alias t = std.typecons.tuple;` which gives you `t(...)`. That's just as short as `t{...}`. But maybe std.typecons.tuple is lacking somehow. A more proper `t(...)` could be implemented when functions could return tuples, which would also be desirable if we had `t{...}` syntax. So implementing `T!(...)` and `t(...)` in D seems like the way to go to me. And maybe allow functions to return tuples.Functions can return std.typecons.tuple. All that is needed IMO is unpacking syntax: auto (int x, y) = someTuple; Rather than adding this specific feature, we could allow better, have Rust-like pattern matching macros: macro unpack(Declaration...); $unpack(int x, auto y) = someTuple;
Apr 08 2016
On Tuesday, 5 April 2016 at 05:45:08 UTC, Timothee Cour wrote:{} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}I don't think that t or T is needed in front of {}. 1) Function literals / lambdas / delegates: If someone wants an empty function literal, they just have to use (){} instead of {}: alias Action = void delegate(); Action action = (){}; // instead of Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegates auto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon. 2) Tuples and AliasSeq-s. Correct me if I'm wrong, but I think that in all cases the expression is unambiguous: auto t1 = {3, 4}; // Tuple enum t2 = {3, 4}; // Tuple alias t3 = {3, 4}; // AliasSeq void foo(Tuple!(int, int) x); foo({3, 4}); // same as foo(t1), or foo(t2) template staticMap(alias F, T...); alias constTypes = staticMap!( constOf, { int, float, void[] } ); static assert (is( constTypes == { const(int), const(float), const(void[]) } ); writefln!({int, string, double})("%s %s %s", {3, "test", 4.2});
Apr 05 2016
On Tuesday, 5 April 2016 at 15:29:06 UTC, ZombineDev wrote:Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegates auto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon.Is making this Action action = {}; an error a breaking change? It currently compiles without error and I can get the typeof(action) as void delegate(), though I can't really do much of anything with it. Similarly for empty function literals.
Apr 05 2016
On Tuesday, 5 April 2016 at 16:34:49 UTC, jmh530 wrote:On Tuesday, 5 April 2016 at 15:29:06 UTC, ZombineDev wrote:Yes, I think it would be a breaking change, if my proposal is accepted.Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegates auto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon.Is making this Action action = {}; an error a breaking change? It currently compiles without error and I can get the typeof(action) as void delegate(), though I can't really do much of anything with it. Similarly for empty function literals.
Apr 05 2016
On 05.04.2016 17:29, ZombineDev wrote:On Tuesday, 5 April 2016 at 05:45:08 UTC, Timothee Cour wrote:(This specific case would actually be unproblematic. {} can be polysemous.){} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}I don't think that t or T is needed in front of {}. 1) Function literals / lambdas / delegates: If someone wants an empty function literal, they just have to use (){} instead of {}: alias Action = void delegate(); Action action = (){}; // instead of Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegatesauto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon. 2) Tuples and AliasSeq-s. Correct me if I'm wrong, but I think that in all cases the expression is unambiguous: auto t1 = {3, 4}; // Tuple enum t2 = {3, 4}; // Tuple alias t3 = {3, 4}; // AliasSeq ...This is moot. template T(alias a,alias b){} template T(alias a){} T!({1,2}) // <- ? Note that template alias parameters can accept values. (Other alias declarations can too, possibly depending on how you look at it; the language grammar is a little warty there.) I don't think there should be separate syntax for 'AliasSeq' especially if it resembles tuple syntax. (The design is already confusing enough, for no gain.)void foo(Tuple!(int, int) x); foo({3, 4}); // same as foo(t1), or foo(t2) template staticMap(alias F, T...); alias constTypes = staticMap!( constOf, { int, float, void[] } ); static assert (is( constTypes == { const(int), const(float), const(void[]) } ); writefln!({int, string, double})("%s %s %s", {3, "test", 4.2});That highlights another flaw in AliasSeq. This should do the trick, but does not: alias constTypes = const(AliasSeq!(int,float,void[])); pragma(msg, constTypes); // (int, float, void[]) // wat? This means that auto a=...; const b=a; is not always the same as auto a=...; const(typeof(a)) b=a;
Apr 05 2016
On Tuesday, 5 April 2016 at 20:13:59 UTC, Timon Gehr wrote:On 05.04.2016 17:29, ZombineDev wrote:The answer to this question and all similar cases is that is that {1,2} is rewritten to AliasSeq!(1, 2). In this particular case it auto-expands and calls the T template with two alias parameters.On Tuesday, 5 April 2016 at 05:45:08 UTC, Timothee Cour wrote:(This specific case would actually be unproblematic. {} can be polysemous.){} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}I don't think that t or T is needed in front of {}. 1) Function literals / lambdas / delegates: If someone wants an empty function literal, they just have to use (){} instead of {}: alias Action = void delegate(); Action action = (){}; // instead of Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegatesauto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon. 2) Tuples and AliasSeq-s. Correct me if I'm wrong, but I think that in all cases the expression is unambiguous: auto t1 = {3, 4}; // Tuple enum t2 = {3, 4}; // Tuple alias t3 = {3, 4}; // AliasSeq ...This is moot. template T(alias a,alias b){} template T(alias a){} T!({1,2}) // <- ?Note that template alias parameters can accept values. (Other alias declarations can too, possibly depending on how you look at it; the language grammar is a little warty there.)Yes I know. And I see no problem with this. template K(alias fun, alias var, size_t idx, string str, T, Y...) int local = 42; K!(AliasSeq!(x => x * 2, local, 1 + 5, "asd", int, float, double)); K!({ x => x * 2, local, 1 + 5, "asd", int, float, double }); // also the same as: K!(x => x * 2, local, 1 + 5, { "asd", int, {float, double} });I don't think there should be separate syntax for 'AliasSeq' especially if it resembles tuple syntax. (The design is already confusing enough, for no gain.)Well it would be a pretty big whole in the language if you could do tuple, but not alias sequences. Also it's nice to do: {float, float} scale({float, float} vec, float x) { return vec * x; }Yeah this looks like a bug in the current implementation. I also find the following limitation unfortunate: struct Point3 { int x, y, z; } Point3 a, b, c; c = a.tupleof + b.tupleof; // doesn't work :(void foo(Tuple!(int, int) x); foo({3, 4}); // same as foo(t1), or foo(t2) template staticMap(alias F, T...); alias constTypes = staticMap!( constOf, { int, float, void[] } ); static assert (is( constTypes == { const(int), const(float), const(void[]) } ); writefln!({int, string, double})("%s %s %s", {3, "test", 4.2});That highlights another flaw in AliasSeq. This should do the trick, but does not: alias constTypes = const(AliasSeq!(int,float,void[])); pragma(msg, constTypes); // (int, float, void[]) // wat? This means that auto a=...; const b=a; is not always the same as auto a=...; const(typeof(a)) b=a;
Apr 05 2016
On 05.04.2016 22:48, ZombineDev wrote:On Tuesday, 5 April 2016 at 20:13:59 UTC, Timon Gehr wrote:There might have been some underlying misunderstanding here. My guess is that you want the new built-in tuple syntax to be lowered to expression sequences? (I don't.)On 05.04.2016 17:29, ZombineDev wrote:The answer to this question and all similar cases is that is that {1,2} is rewritten to AliasSeq!(1, 2). In this particular case it auto-expands and calls the T template with two alias parameters.On Tuesday, 5 April 2016 at 05:45:08 UTC, Timothee Cour wrote:(This specific case would actually be unproblematic. {} can be polysemous.){} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}I don't think that t or T is needed in front of {}. 1) Function literals / lambdas / delegates: If someone wants an empty function literal, they just have to use (){} instead of {}: alias Action = void delegate(); Action action = (){}; // instead of Action action = {}; // error: `{}` is an empty tuple, can't be assigned to delegatesauto t = {}; // deduced as an empty tuple. Also, the non-empty {} syntax can't be mistaken for a function literal because non-empty function literals always have at least one statement that ends with a semicolon. 2) Tuples and AliasSeq-s. Correct me if I'm wrong, but I think that in all cases the expression is unambiguous: auto t1 = {3, 4}; // Tuple enum t2 = {3, 4}; // Tuple alias t3 = {3, 4}; // AliasSeq ...This is moot. template T(alias a,alias b){} template T(alias a){} T!({1,2}) // <- ?Note that template alias parameters can accept values. (Other alias declarations can too, possibly depending on how you look at it; the language grammar is a little warty there.)Yes I know. And I see no problem with this. ...template K(alias fun, alias var, size_t idx, string str, T, Y...) int local = 42; K!(AliasSeq!(x => x * 2, local, 1 + 5, "asd", int, float, double)); K!({ x => x * 2, local, 1 + 5, "asd", int, float, double }); // also the same as: K!(x => x * 2, local, 1 + 5, { "asd", int, {float, double} });IMAO any design that tries to make wacky auto-expansion even more prominent is not good enough. Auto-expansion should be a derived notion at best. (I.e. there are tuples that are actually tuples, and then they might have an .expand property.) (Also, note that multiple return values are explicitly ruled out at the moment.)I don't think there should be separate syntax for 'AliasSeq' especially if it resembles tuple syntax. (The design is already confusing enough, for no gain.)Well it would be a pretty big whole in the language if you could do tuple, but not alias sequences. Also it's nice to do: {float, float} scale({float, float} vec, float x) { return vec * x; } ...Hopefully. Hard to tell. Walter?Yeah this looks like a bug in the current implementation.void foo(Tuple!(int, int) x); foo({3, 4}); // same as foo(t1), or foo(t2) template staticMap(alias F, T...); alias constTypes = staticMap!( constOf, { int, float, void[] } ); static assert (is( constTypes == { const(int), const(float), const(void[]) } ); writefln!({int, string, double})("%s %s %s", {3, "test", 4.2});That highlights another flaw in AliasSeq. This should do the trick, but does not: alias constTypes = const(AliasSeq!(int,float,void[])); pragma(msg, constTypes); // (int, float, void[]) // wat? This means that auto a=...; const b=a; is not always the same as auto a=...; const(typeof(a)) b=a;I also find the following limitation unfortunate: struct Point3 { int x, y, z; } Point3 a, b, c; c = a.tupleof + b.tupleof; // doesn't work :(There are many, way more arbitrary, limitations. E.g. auto-expansion does not work in case labels, expression sequences cannot be operands of the comma operator and ternary operator and they cannot be returned from functions. The main reason why AliasSeq is hard to evolve is that it is basically fubar'd. I don't know if you know about this: alias Seq(T...)=T; void main(){ int x=0; Seq!(int,int) y = ++x; assert(y[0]==1 && y[1]==2); } Unless breaking changes are allowed, any design that builds on AliasSeq will be... funny.
Apr 05 2016
On Tuesday, 5 April 2016 at 05:45:08 UTC, Timothee Cour wrote:{} for tuples hasn't worked out since it was deemed ambiguous with delegate syntax (was it for the case of empty statements/tuple?). How about the following syntax instead: ---- {} // delegate (existing syntax) q{...} // string literal (existing syntax) t{...} // tuple(a,b) (proposed syntax) T{...} // TypeTuple!(a,b) (proposed syntax) ---- See also [1] where i propose i{...} for a D analog of C++11's uniform initialization. [1] EMAIL: uniform initialization in D (as in C++11): i{...}Tuple and AliasSeq are library types, so the chance that they will be added into the language is slim to none.
Apr 05 2016
On Tuesday, 5 April 2016 at 16:56:15 UTC, Jack Stouffer wrote:Tuple and AliasSeq are library types, so the chance that they will be added into the language is slim to none.Yes on Tuple, but AliasSeq actually is in the language (just unnamed there, it is what you get with T... in a template argument list) and isn't actually a type at all. It is just a list of compile time names.
Apr 05 2016