www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Struct immutable data and dict

reply Patric Dexheimer <patric.dexheimer gmail.com> writes:
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
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
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
next sibling parent reply Patric Dexheimer <patric.dexheimer gmail.com> writes:
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:
 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.
But why i´m overwriting the struct if its the first time i´m putting it there? (like on the array).
Oct 05 2016
next sibling parent Adam D. Ruppe <destructionator gmail.com> writes:
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
prev sibling parent reply Mike Parker <aldacron gmail.com> writes:
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
parent Patric Dexheimer <patric.dexheimer gmail.com> writes:
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:

 [...]
There's a difference between initialization and assignment. [...]
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:

 [...]
Hm, so in dict they are always assuming that i´m doing assignments.. Ok, more clear now. thanks.
Oct 06 2016
prev sibling parent reply Timoses <timosesu gmail.com> writes:
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:
 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.
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??
Sep 04 2018
parent reply Alex <sascha.orlov gmail.com> writes:
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
parent reply nkm1 <t4nk074 openmailbox.org> writes:
On Tuesday, 4 September 2018 at 11:25:15 UTC, Alex wrote:
 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??
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".
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"]); }
Sep 04 2018
parent Timoses <timosesu gmail.com> writes:
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