digitalmars.D.learn - Associative Array c'tor
- Bahman Movaqar (25/25) Jul 11 2016 I'm processing a list of structs (MySt) with `reduce` to produce an
- Steven Schveighoffer (5/27) Jul 11 2016 Untested, but you could try MySt[][string].init.
- Bahman Movaqar (5/8) Jul 11 2016 Could you elaborate more?
- =?UTF-8?Q?Ali_=c3=87ehreli?= (27/33) Jul 11 2016 Both AAs and slices behave like reference types even when passed by
- Bahman Movaqar (9/35) Jul 11 2016 Now I understand.
- ketmar (3/9) Jul 12 2016 no. the only thing you can do is to add something to aa and
- Steven Schveighoffer (13/20) Jul 12 2016 There was a suggestion to make .clear (a relatively new feature)
- Steven Schveighoffer (21/25) Jul 11 2016 An AA initializes on demand. So if you pass by value *after* it has been...
I'm processing a list of structs (MySt) with `reduce` to produce an associate array of type `MySt[][string]`. Right now I'm using the following (slimmed down) code: MySt[][string] result; return reduce!( function MySt[][string](MySt[][string] acc, MySt val) { // do something with acc return acc; } )(result, inputList); I was wondering if I could remove the empty declaration line (line 1); for example: return reduce!( function MySt[][string](MySt[][string] acc, MySt val) { // do something with acc return acc; } )(new MySt[][string](), inputList); Obviously, this fails with the error message: "cannot pass type string as a function argument". I very much would like to avoid empty declaration lines like that of `result`. Is there anyway you folks would suggest? Thanks in advance, -- Bahman
Jul 11 2016
On 7/11/16 9:48 AM, Bahman Movaqar wrote:I'm processing a list of structs (MySt) with `reduce` to produce an associate array of type `MySt[][string]`. Right now I'm using the following (slimmed down) code: MySt[][string] result; return reduce!( function MySt[][string](MySt[][string] acc, MySt val) { // do something with acc return acc; } )(result, inputList); I was wondering if I could remove the empty declaration line (line 1); for example: return reduce!( function MySt[][string](MySt[][string] acc, MySt val) { // do something with acc return acc; } )(new MySt[][string](), inputList); Obviously, this fails with the error message: "cannot pass type string as a function argument". I very much would like to avoid empty declaration lines like that of `result`. Is there anyway you folks would suggest?Untested, but you could try MySt[][string].init. But passing empty AA by value sometimes can be surprising. I'm not sure if it will work. -Steve
Jul 11 2016
On 07/11/2016 06:30 PM, Steven Schveighoffer wrote:Untested, but you could try MySt[][string].init.That did it. Thanks.But passing empty AA by value sometimes can be surprising. I'm not sure if it will work.Could you elaborate more? -- Bahman
Jul 11 2016
On 07/11/2016 07:33 AM, Bahman Movaqar wrote:On 07/11/2016 06:30 PM, Steven Schveighoffer wrote:Both AAs and slices behave like reference types even when passed by value: When a function adds an element, the argument sees that element as well. This is not the case when the argument is an empty (more correctly, null) AA or slice: void foo(string[int] aa) { aa[1] = "one"; } void main() { string[int] a; foo(a); assert(a is null); // The last result would be different if 'a' were not null // before calling 'foo'. string[int] b; b[0] = "zero"; foo(b); assert(b[0] == "zero"); assert(b[1] == "one"); } Ali P.S. There is std.array.assocArray if you already have a range of tuples at hand: https://dlang.org/phobos/std_array.html#.assocArray P.P.S. There is std.algorithm.fold, which works with range chaining (unlike reduce, which was designed before ranges): https://dlang.org/phobos/std_algorithm_iteration.html#.foldUntested, but you could try MySt[][string].init.That did it. Thanks.But passing empty AA by value sometimes can be surprising. I'm not sure if it will work.Could you elaborate more?
Jul 11 2016
On 07/11/2016 07:15 PM, Ali Çehreli wrote:Both AAs and slices behave like reference types even when passed by value: When a function adds an element, the argument sees that element as well. This is not the case when the argument is an empty (more correctly, null) AA or slice: void foo(string[int] aa) { aa[1] = "one"; } void main() { string[int] a; foo(a); assert(a is null); // The last result would be different if 'a' were not null // before calling 'foo'. string[int] b; b[0] = "zero"; foo(b); assert(b[0] == "zero"); assert(b[1] == "one"); }Now I understand. This is tricky --could introduce hard to find bugs. Is there anyway to make sure it doesn't happen? Such as giving the AA a default empty value on the declaration line --like `string[int] a = []`?P.P.S. There is std.algorithm.fold, which works with range chaining (unlike reduce, which was designed before ranges): https://dlang.org/phobos/std_algorithm_iteration.html#.fold`fold` definitely feels more natural. Thanks. -- Bahman
Jul 11 2016
On Tuesday, 12 July 2016 at 03:38:44 UTC, Bahman Movaqar wrote:Now I understand. This is tricky --could introduce hard to find bugs. Is there anyway to make sure it doesn't happen? Such as giving the AA a default empty value on the declaration line --like `string[int] a = []`?no. the only thing you can do is to add something to aa and immediately `.clear`
Jul 12 2016
On 7/12/16 5:42 AM, ketmar wrote:On Tuesday, 12 July 2016 at 03:38:44 UTC, Bahman Movaqar wrote:There was a suggestion to make .clear (a relatively new feature) actually preallocate if it's currently null, but I didn't want to do allocating in that method (too surprising). I do think it would be nice to have an initializer function that simply allocates the impl. Anyone want to do a PR? basically (strawman name): int[int] aa; aa.initialize; // still has 0 elements, but no longer null. I'm not sure you could make a static initializer method, since AA's are special builtin types. Relative modules needed to be changed are object.d and src/rt/aaA.d -SteveNow I understand. This is tricky --could introduce hard to find bugs. Is there anyway to make sure it doesn't happen? Such as giving the AA a default empty value on the declaration line --like `string[int] a = []`?no. the only thing you can do is to add something to aa and immediately `.clear`
Jul 12 2016
On Tuesday, 12 July 2016 at 12:34:40 UTC, Steven Schveighoffer wrote:There was a suggestion to make .clear (a relatively new feature) actually preallocate if it's currently null, but I didn't want to do allocating in that method (too surprising). I do think it would be nice to have an initializer function that simply allocates the impl.q&n patch[1]. it adds template arg to `.clear`, so no code breakage here (old `clear` is still not allocate, but `.clear!true` will). [1] https://issues.dlang.org/show_bug.cgi?id=16269
Jul 12 2016
On Tuesday, 12 July 2016 at 13:01:20 UTC, ketmar wrote:On Tuesday, 12 July 2016 at 12:34:40 UTC, Steven Schveighoffer wrote:I'm with Steven here, that's definitely too surprising, initialization should not be linked to clear in any way.There was a suggestion to make .clear (a relatively new feature) actually preallocate if it's currently null, but I didn't want to do allocating in that method (too surprising). I do think it would be nice to have an initializer function that simply allocates the impl.q&n patch[1]. it adds template arg to `.clear`, so no code breakage here (old `clear` is still not allocate, but `.clear!true` will). [1] https://issues.dlang.org/show_bug.cgi?id=16269
Jul 12 2016
On Tuesday, 12 July 2016 at 13:56:49 UTC, cym13 wrote:I'm with Steven here, that's definitely too surprising, initialization should not be linked to clear in any way.feel free to change/improve it. for me it is logical, but i'm often found that i am the only one who agrees with my logic. ;-)
Jul 12 2016
On 7/11/16 10:33 AM, Bahman Movaqar wrote:On 07/11/2016 06:30 PM, Steven Schveighoffer wrote:An AA initializes on demand. So if you pass by value *after* it has been initialized it behaves like a reference type. But before it's initialized, it's essentially a null pointer. This can cause surprising behavior: foo(int[int] aa) { foreach(i; 0 .. 100) aa[i] = i; } void main() { import std.random; int[int] aa; // initialized as null if(uniform!ubyte < 128) aa[0] = 0; // intialized foo(aa); // at this point, depending on random initialization, either aa is filled or is still null. } -SteveBut passing empty AA by value sometimes can be surprising. I'm not sure if it will work.Could you elaborate more?
Jul 11 2016