www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How do I store an immutable value into a mutable associative array?

reply "PlatisYialos" <leonidasklados gmail.com> writes:
Here's a test file, with the compiler messages obtained.  I also 
tried introducing an alias with similar results to the second 
attempt below.

1    module test;
2
3    void noparens() {
4      immutable char[char] aMap;
5      aMap['a'] = 'b';
6
7      /* Compiler error messages
8         ./src/test.d(5): Error: aMap['a'] isn't mutable
9         ./src/test.d(5): Error: variable test.noparens.aMap 
cannot modify immutable
10      */
11   }
12
13   void withparens() {
14     immutable(char)[char] aMap;
15     aMap['a'] = 'b';
16
17     /* Compiler error messages
18        ./src/test.d(15): Error: aMap['a'] isn't mutable
19      */
20   }
Nov 06 2012
next sibling parent reply "PlatisYialos" <leonidasklados gmail.com> writes:
On Tuesday, 6 November 2012 at 17:23:41 UTC, PlatisYialos wrote:

Errmm!  Here's a better example, but with the same results:

----------------------------
module test;

void noparens() {
   immutable char[char] aMap;
   char a = 'a';
   immutable char b = 'b';
   aMap[a] = b;
}

void withparens() {
   immutable(char)[char] aMap;
   char a = 'a';
   immutable char b = 'b';
   aMap[a] = b;
}
-----------------------------
Nov 06 2012
next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/06/2012 09:48 AM, PlatisYialos wrote:
 On Tuesday, 6 November 2012 at 17:23:41 UTC, PlatisYialos wrote:

 Errmm! Here's a better example, but with the same results:

 ----------------------------
 module test;

 void noparens() {
 immutable char[char] aMap;
 char a = 'a';
 immutable char b = 'b';
 aMap[a] = b;
 }

 void withparens() {
 immutable(char)[char] aMap;
 char a = 'a';
 immutable char b = 'b';
 aMap[a] = b;
 }
 -----------------------------

I think it is not surprising why noparens() doesn't work: aMap is immutable. withparens() would be expected to work but again, 'aMap[a] = b' is seen as a mutation of element aMap[a]. If associative arrays had an insert() function, then we would expect it to work. Here is a quick solution: /* I used 'inout' to accept mutable, const, and immutable value types */ void insert(K, V)(ref immutable(V)[K] aa, K key, inout V value) { /* I would like to use the following simpler code: * * auto mutable = cast(V[K])aa; * mutable[key] = value; * * It did not work when 'aa' was null. The later initialization of * 'mutable ' would affect only 'mutable', not 'aa'. */ V[K] * mutable = cast(V[K]*)&aa; (*mutable)[key] = value; } // ... aMap.insert(a, b); Ali
Nov 06 2012
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 11/06/2012 10:13 AM, PlatisYialos wrote:
 On Tuesday, 6 November 2012 at 17:48:55 UTC, PlatisYialos wrote:

 To really give a stark example:

 -------------------------------
 void compiles() {
 immutable(char)[][immutable(char)[]] aMap;

[...]
 Does the compiler give special treatment to strings?

No. Note that the value type is not immutable above. Individual characters are immutable but the whole value is not: immutable(char)[]. Ali
Nov 06 2012
prev sibling next sibling parent "PlatisYialos" <leonidasklados gmail.com> writes:
On Tuesday, 6 November 2012 at 17:48:55 UTC, PlatisYialos wrote:

To really give a stark example:

-------------------------------
void compiles() {
   immutable(char)[][immutable(char)[]] aMap;
   immutable(char)[] a = ['a'];
   immutable(char)[] b = ['b'];
   aMap[a] = b;
}

void doesnotcompile() {
   immutable(char)[immutable(char)] aMap;
   immutable(char) a = 'a';
   immutable(char) b = 'b';
   aMap[a] = b;
}
-------------------------------

I don't see what I'm doing wrong.  Does the compiler give special 
treatment to strings?
Nov 06 2012
prev sibling next sibling parent "PlatisYialos" <leonidasklados gmail.com> writes:
On Tuesday, 6 November 2012 at 18:28:04 UTC, Ali Çehreli wrote:
 On 11/06/2012 10:13 AM, PlatisYialos wrote:
 On Tuesday, 6 November 2012 at 17:48:55 UTC, PlatisYialos

 To really give a stark example:

 -------------------------------
 void compiles() {
 immutable(char)[][immutable(char)[]] aMap;

[...]
 Does the compiler give special treatment to strings?

No. Note that the value type is not immutable above. Individual characters are immutable but the whole value is not: immutable(char)[]. Ali

Of course! Duh!
Nov 06 2012
prev sibling parent "PlatisYialos" <leonidasklados gmail.com> writes:
On Tuesday, 6 November 2012 at 18:25:46 UTC, Ali Çehreli wrote:
 On 11/06/2012 09:48 AM, PlatisYialos wrote:
 On Tuesday, 6 November 2012 at 17:23:41 UTC, PlatisYialos 
 wrote:

 Errmm! Here's a better example, but with the same results:

 ----------------------------
 module test;

 void noparens() {
 immutable char[char] aMap;
 char a = 'a';
 immutable char b = 'b';
 aMap[a] = b;
 }

 void withparens() {
 immutable(char)[char] aMap;
 char a = 'a';
 immutable char b = 'b';
 aMap[a] = b;
 }
 -----------------------------

I think it is not surprising why noparens() doesn't work: aMap is immutable. withparens() would be expected to work but again, 'aMap[a] = b' is seen as a mutation of element aMap[a]. If associative arrays had an insert() function, then we would expect it to work. Here is a quick solution: /* I used 'inout' to accept mutable, const, and immutable value types */ void insert(K, V)(ref immutable(V)[K] aa, K key, inout V value) { /* I would like to use the following simpler code: * * auto mutable = cast(V[K])aa; * mutable[key] = value; * * It did not work when 'aa' was null. The later initialization of * 'mutable ' would affect only 'mutable', not 'aa'. */ V[K] * mutable = cast(V[K]*)&aa; (*mutable)[key] = value; } // ... aMap.insert(a, b); Ali

Thank you, Ali, for going above and beyond on this one!
Nov 06 2012