digitalmars.D.learn - Struct immutable data and dict
- Patric Dexheimer (12/12) Oct 05 2016 struct Test{
- Adam D. Ruppe (9/10) Oct 05 2016 Because you'd be overwriting that immutable member. Structs just
- Patric Dexheimer (3/14) Oct 05 2016 But why i´m overwriting the struct if its the first time i´m
- Adam D. Ruppe (7/9) Oct 05 2016 The compiler doesn't know it is the first time (it doesn't follow
- Mike Parker (19/21) Oct 05 2016 There's a difference between initialization and assignment.
- Patric Dexheimer (5/13) Oct 06 2016 Hm, so in dict they are always assuming that i´m doing
- Timoses (54/65) Sep 04 2018 Hm... so is there any way around this?
struct Test{ immutable size_t id; } Test[string] dict; Test[] array; void main(){ array~=Test(1);//work dict["teste"] = Test(1); //fail ?? } "Error: cannot modify struct dict["teste"] Test with immutable members" Why?
Oct 05 2016
On Thursday, 6 October 2016 at 01:23:35 UTC, Patric Dexheimer wrote:Why?Because you'd be overwriting that immutable member. Structs just put structure around their contents, but it doesn't change their nature. That struct is no different than if you wrote `immutable size_t` as the value - and of course, overwriting that; changing that violates that promise that you won't change it. You could store pointers to those structs though, and overwrite the pointer.
Oct 05 2016
On Thursday, 6 October 2016 at 02:09:44 UTC, Adam D. Ruppe wrote:On Thursday, 6 October 2016 at 01:23:35 UTC, Patric Dexheimer wrote:But why i´m overwriting the struct if its the first time i´m putting it there? (like on the array).Why?Because you'd be overwriting that immutable member. Structs just put structure around their contents, but it doesn't change their nature. That struct is no different than if you wrote `immutable size_t` as the value - and of course, overwriting that; changing that violates that promise that you won't change it. You could store pointers to those structs though, and overwrite the pointer.
Oct 05 2016
On Thursday, 6 October 2016 at 03:05:18 UTC, Patric Dexheimer wrote:But why i´m overwriting the struct if its the first time i´m putting it there? (like on the array).The compiler doesn't know it is the first time (it doesn't follow the data from creation, it just looks at that individual line, and first time write is no different than later writes with the associative array index, whereas array append is different so it can tell).
Oct 05 2016
On Thursday, 6 October 2016 at 03:05:18 UTC, Patric Dexheimer wrote:But why i´m overwriting the struct if its the first time i´m putting it there? (like on the array).There's a difference between initialization and assignment. ``` // Given this structure struct MyStruct { int x; } // Both of these lines are initializstion auto mystruct1 = MyStruct(10); MyStruct mystruct2; assert(mystruct1.x == 10); assert(mystruct2.x == 0); // And both of these are assignments. mystruct2 = MyStruct(11); mystruct1 = mystruct2; assert(mystruct2.x == 11); assert(mystruct1.x == 11); ``` If x were immutable, both initializations would succeed, but both assignments would fail.
Oct 05 2016
On Thursday, 6 October 2016 at 03:48:22 UTC, Mike Parker wrote:On Thursday, 6 October 2016 at 03:05:18 UTC, Patric Dexheimer wrote:On Thursday, 6 October 2016 at 03:48:22 UTC, Mike Parker wrote:[...]There's a difference between initialization and assignment. [...]On Thursday, 6 October 2016 at 03:05:18 UTC, Patric Dexheimer wrote: [...]Hm, so in dict they are always assuming that i´m doing assignments.. Ok, more clear now. thanks.
Oct 06 2016
On Thursday, 6 October 2016 at 02:09:44 UTC, Adam D. Ruppe wrote:On Thursday, 6 October 2016 at 01:23:35 UTC, Patric Dexheimer wrote:Hm... so is there any way around this? In my case I have a RandomAccessRange which caches it's results. Reduced example: struct Res { immutable int i; } struct Range { Res[size_t] c; Res fun(size_t i) { if (auto p = i in c) return *p; else { c[3] = Res(3); /// ERROR line 26 return c[3]; } } } unittest { auto r = Range(); r.fun(3); } which errors at compilation with onlineapp.d(26): Error: cannot modify struct this.c[3] Res with immutable members A workaround I thought could be to use an array struct Range { //Res[size_t] c; struct Con { Res c; bool valid; } Con[] c; Res fun(size_t i) { if (c.length > i && c[i].valid) return c[i].c; else { if (c.length <= i) c.length = i + 1; auto r = Con(Res(3), true); c[i] = r; /// same ERROR! return c[i].c; } } } However, of course this also fails because randomly assigning the array elements will overwrite it. So the associative array seems like the better idea. However, not being able to INITIALIZE an assoc array element disallows its usage. Is there any solution, trick or workaround??Why?Because you'd be overwriting that immutable member. Structs just put structure around their contents, but it doesn't change their nature. That struct is no different than if you wrote `immutable size_t` as the value - and of course, overwriting that; changing that violates that promise that you won't change it. You could store pointers to those structs though, and overwrite the pointer.
Sep 04 2018
On Tuesday, 4 September 2018 at 10:30:24 UTC, Timoses wrote:However, of course this also fails because randomly assigning the array elements will overwrite it. So the associative array seems like the better idea. However, not being able to INITIALIZE an assoc array element disallows its usage. Is there any solution, trick or workaround??If the initialization of assoc array is not the matter, but the initialization of an element of it, then, the question is rather: "Is the absence of an immutable value in an assoc array worth to be garanteed, because the values are immutable?" Isn't it? No idea about this :p ´´´ void main() { import std.stdio; auto r = Range("dummy"); r.fun(3).writeln; } struct Res { immutable int i; } struct Range { this(string) { c = [0 : Res(42), 5: Res(73), /*3: Res(4)*/]; } Res[size_t] c; Res fun(size_t i) { if (auto p = i in c) return *p; else { //c[3] = Res(3); /// ERROR line 26 return Res(int.max); } } } ´´´ I tried two workarounds: 1) let the immutable away. 2) preallocate a full array of immutables. Then, misuse the assoc array by using the keys only. If the key is there, then, yield the appropriate element from the preallocated array. If not, yield the "elephant in Cairo".
Sep 04 2018
On Tuesday, 4 September 2018 at 11:25:15 UTC, Alex wrote:On Tuesday, 4 September 2018 at 10:30:24 UTC, Timoses wrote:I also had this problem recently. I think aa.require() should allow to add immutables (feature request). Anyway, my workaround was along the lines of: final class AA(Key, Value) { Value[] _storage; size_t[Key] _aa; void opIndexAssign(Value value, Key key) { if (key !in _aa) { _storage ~= value; _aa[key] = _storage.length - 1; } } Value opIndex(Key key) { if (auto index = key in _aa) return _storage[*index]; throw new Exception("no key"); } } immutable struct S { int num; } void main() { import std.stdio : writeln; auto aa = new AA!(string, S); aa["one"] = S(1); aa["two"] = S(2); writeln(aa["one"]); writeln(aa["two"]); }However, of course this also fails because randomly assigning the array elements will overwrite it. So the associative array seems like the better idea. However, not being able to INITIALIZE an assoc array element disallows its usage. Is there any solution, trick or workaround??I tried two workarounds: 1) let the immutable away. 2) preallocate a full array of immutables. Then, misuse the assoc array by using the keys only. If the key is there, then, yield the appropriate element from the preallocated array. If not, yield the "elephant in Cairo".
Sep 04 2018
On Tuesday, 4 September 2018 at 12:27:47 UTC, nkm1 wrote:I also had this problem recently. I think aa.require() should allow to add immutables (feature request). Anyway, my workaround was along the lines of: final class AA(Key, Value) { Value[] _storage; size_t[Key] _aa; void opIndexAssign(Value value, Key key) { if (key !in _aa) { _storage ~= value; _aa[key] = _storage.length - 1; } } Value opIndex(Key key) { if (auto index = key in _aa) return _storage[*index]; throw new Exception("no key"); } } immutable struct S { int num; } void main() { import std.stdio : writeln; auto aa = new AA!(string, S); aa["one"] = S(1); aa["two"] = S(2); writeln(aa["one"]); writeln(aa["two"]); }Thanks for the replies. It seems quite annoying. I just use classes for now.
Sep 04 2018