Thread overview
How do I store an immutable value into a mutable associative array?
Nov 06, 2012
PlatisYialos
Nov 06, 2012
PlatisYialos
Nov 06, 2012
PlatisYialos
Nov 06, 2012
Ali Çehreli
Nov 06, 2012
PlatisYialos
Nov 06, 2012
Ali Çehreli
Nov 06, 2012
PlatisYialos
November 06, 2012
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   }


November 06, 2012
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;
}
-----------------------------

November 06, 2012
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?
November 06, 2012
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
November 06, 2012
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

November 06, 2012
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
> 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

Of course! Duh!
November 06, 2012
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!