digitalmars.D.learn - Struct initializers as expressions
- Chris Wright (36/36) Dec 02 2015 I can initialize a struct with named values:
- Mike Parker (4/19) Dec 02 2015 AFAIK, your only option is to use a struct constructor. This is
- Chris Wright (7/9) Dec 03 2015 Which brings be back to positional arguments, which means that someone
- Enamex (3/12) Dec 03 2015 I asked about that a while ago and was given noncommittal answers
- Marc =?UTF-8?B?U2Now7x0eg==?= (15/24) Dec 04 2015 I'd support that, too.
- Andrea Fontana (3/4) Dec 04 2015 ... but not forbidden. With templates or "auto" could be useful
- Mike Parker (13/20) Dec 04 2015 I like the idea of field names in a struct literal, but I would
- Marc =?UTF-8?B?U2Now7x0eg==?= (8/31) Dec 04 2015 Dropping the parens/braces is an optional step, but I would
- Jacob Carlborg (9/23) Dec 04 2015 I've been thinking along the same lines as well and would really like to...
- Marc =?UTF-8?B?U2Now7x0eg==?= (8/38) Dec 04 2015 Right, this would need to be rejected. When the compiler sees
- Chris Wright (9/12) Dec 04 2015 Right. I would much rather keep any DIPs minimal in terms of scope and
I can initialize a struct with named values: --- struct Foo { int i, j, k, l, m, n; } Foo f = {k: 12}; // other fields get default initialization --- I can initialize it with call syntax: --- auto f = Foo(0, 0, 12, 0, 0, 0); // works --- I can use the latter as an expression: --- void bar(Foo f) {} bar(Foo(0, 0, 12, 0, 0, 0)); // just peachy --- but not the latter: --- void bar(Foo f) {} bar({k: 12}); bar(Foo{k: 12}); --- Those both give: Error: found '{' when expecting ',' Error: found ':' when expecting ',' Error: found '}' when expecting ',' This is slightly cruddy. I wanted to write couchdb.queryView("byUsername", {key: "neia"}); But it looks like I have to use: QueryOptions o = {key: "neia"}; couchdb.queryView("byUsername", o); Not so good. Ideally, I want something that lets you specify only the fields you care about and won't have to be modified (just recompiled) if I add more fields. I also want something inline. Is there anything I can use here that's better than what I have?
Dec 02 2015
On Thursday, 3 December 2015 at 05:26:17 UTC, Chris Wright wrote:I can initialize a struct with named values: --- struct Foo { int i, j, k, l, m, n; } Foo f = {k: 12}; // other fields get default initialization --- I can initialize it with call syntax: --- auto f = Foo(0, 0, 12, 0, 0, 0); // works ---The bottom syntax is a struct literal, the top one is not.Ideally, I want something that lets you specify only the fields you care about and won't have to be modified (just recompiled) if I add more fields. I also want something inline. Is there anything I can use here that's better than what I have?AFAIK, your only option is to use a struct constructor. This is the sort of thing they're used for.
Dec 02 2015
On Thu, 03 Dec 2015 06:38:20 +0000, Mike Parker wrote:AFAIK, your only option is to use a struct constructor. This is the sort of thing they're used for.Which brings be back to positional arguments, which means that someone wishing to supply a limit on the number of query results must also give me the number of results per page, even if she doesn't care about the number of results per page. Is it worth posting a DIP for struct literals of the form `Name{fieldname: value}` ?
Dec 03 2015
On Thursday, 3 December 2015 at 15:31:49 UTC, Chris Wright wrote:On Thu, 03 Dec 2015 06:38:20 +0000, Mike Parker wrote:I asked about that a while ago and was given noncommittal answers on why it wasn't accepted. I'd support your DIP.AFAIK, your only option is to use a struct constructor. This is the sort of thing they're used for.Which brings be back to positional arguments, which means that someone wishing to supply a limit on the number of query results must also give me the number of results per page, even if she doesn't care about the number of results per page. Is it worth posting a DIP for struct literals of the form `Name{fieldname: value}` ?
Dec 03 2015
On Thursday, 3 December 2015 at 15:31:49 UTC, Chris Wright wrote:On Thu, 03 Dec 2015 06:38:20 +0000, Mike Parker wrote:I'd support that, too. I suggest to make the struct name optional: struct S { int a, b; } struct T { string a, b; } void foo(S s); void foo(T t); foo({b: 1, a: 2}); // foo(S(2, 1)); foo({a: "bla"}); // foo(T("bla", null)); Then we can add some syntax sugar to leave out the braces, too: void bar(int a, T t) bar(42, a: "bla", b: "xyz"); This effectively gives us strongly typed named arguments, without making the names part of the function signature, which Walter objected to the last time something like this was proposed.AFAIK, your only option is to use a struct constructor. This is the sort of thing they're used for.Which brings be back to positional arguments, which means that someone wishing to supply a limit on the number of query results must also give me the number of results per page, even if she doesn't care about the number of results per page. Is it worth posting a DIP for struct literals of the form `Name{fieldname: value}` ?
Dec 04 2015
On Friday, 4 December 2015 at 10:42:46 UTC, Marc Schütz wrote:I suggest to make the struct name optional:... but not forbidden. With templates or "auto" could be useful to force the type.
Dec 04 2015
On Friday, 4 December 2015 at 10:42:46 UTC, Marc Schütz wrote: ;Then we can add some syntax sugar to leave out the braces, too: void bar(int a, T t) bar(42, a: "bla", b: "xyz"); This effectively gives us strongly typed named arguments, without making the names part of the function signature, which Walter objected to the last time something like this was proposed.I like the idea of field names in a struct literal, but I would prefer to keep the parens. And no braces! The syntax for literals is already recommended over the C-style initializers, so IMO the same ought to hold for named initializers. I agree with dropping the struct name, though. bar(42, (a: "bla", b: "xyz")) I realized that if named arguments are not supported, then dropping the parens should still indicate that you're dealing with a struct, but the clear delineation is much more obvious. It also holds the door open for Walter to change his mind on named arguments.
Dec 04 2015
On Friday, 4 December 2015 at 11:25:12 UTC, Mike Parker wrote:On Friday, 4 December 2015 at 10:42:46 UTC, Marc Schütz wrote: ;Dropping the parens/braces is an optional step, but I would prefer to allow it. It looks much cleaner, and from my POV the goal is to make it look seamless. And IIRC Walter isn't really opposed to named arguments per se. He just didn't want parameter names to become part of the signature. With this proposal, they won't be, and it's opt-in from the implementer's POV.Then we can add some syntax sugar to leave out the braces, too: void bar(int a, T t) bar(42, a: "bla", b: "xyz"); This effectively gives us strongly typed named arguments, without making the names part of the function signature, which Walter objected to the last time something like this was proposed.I like the idea of field names in a struct literal, but I would prefer to keep the parens. And no braces! The syntax for literals is already recommended over the C-style initializers, so IMO the same ought to hold for named initializers. I agree with dropping the struct name, though. bar(42, (a: "bla", b: "xyz")) I realized that if named arguments are not supported, then dropping the parens should still indicate that you're dealing with a struct, but the clear delineation is much more obvious. It also holds the door open for Walter to change his mind on named arguments.
Dec 04 2015
On 2015-12-04 11:42, Marc Schütz wrote:I'd support that, too. I suggest to make the struct name optional: struct S { int a, b; } struct T { string a, b; } void foo(S s); void foo(T t); foo({b: 1, a: 2}); // foo(S(2, 1)); foo({a: "bla"}); // foo(T("bla", null)); Then we can add some syntax sugar to leave out the braces, too: void bar(int a, T t) bar(42, a: "bla", b: "xyz"); This effectively gives us strongly typed named arguments, without making the names part of the function signature, which Walter objected to the last time something like this was proposed.I've been thinking along the same lines as well and would really like to see that feature. Wondering if it could work with opDispatch as well to swallow unrecognized fields. But I do see a problem, which I'm guessing Walter would point out as well. It might/will complicate the overloading rules. What if "a" and "b" in T would be integers instead. I think that would be ambiguous. -- /Jacob Carlborg
Dec 04 2015
On Friday, 4 December 2015 at 14:07:01 UTC, Jacob Carlborg wrote:On 2015-12-04 11:42, Marc Schütz wrote:Right, this would need to be rejected. When the compiler sees such syntax, it would need to get a list of struct types allowed in the current position, and try to construct each of them with the given arguments. If there isn't exactly one match, it is rejected. This way, there is no change to the overloading rules themselves, it's just a rule to determine the type of the {key: value, ...} expression. After that, overloading works as usual.I'd support that, too. I suggest to make the struct name optional: struct S { int a, b; } struct T { string a, b; } void foo(S s); void foo(T t); foo({b: 1, a: 2}); // foo(S(2, 1)); foo({a: "bla"}); // foo(T("bla", null)); Then we can add some syntax sugar to leave out the braces, too: void bar(int a, T t) bar(42, a: "bla", b: "xyz"); This effectively gives us strongly typed named arguments, without making the names part of the function signature, which Walter objected to the last time something like this was proposed.I've been thinking along the same lines as well and would really like to see that feature. Wondering if it could work with opDispatch as well to swallow unrecognized fields. But I do see a problem, which I'm guessing Walter would point out as well. It might/will complicate the overloading rules. What if "a" and "b" in T would be integers instead. I think that would be ambiguous.
Dec 04 2015
On Fri, 04 Dec 2015 15:07:01 +0100, Jacob Carlborg wrote:But I do see a problem, which I'm guessing Walter would point out as well. It might/will complicate the overloading rules. What if "a" and "b" in T would be integers instead. I think that would be ambiguous.Right. I would much rather keep any DIPs minimal in terms of scope and compiler changes. It could cause headaches with overload resolution if you didn't require the struct name in the literal, so I won't propose that at first. If named arguments come along, it would require additional care not to conflict with no-parentheses struct literal arguments. And what if a function takes two structs as parameters? Plus there would be issues with people mixing no-parens struct fields with positional parameters and getting confused.
Dec 04 2015