Thread overview
AA with immutable values
Jun 24, 2012
Roman D. Boiko
Jun 24, 2012
Jonathan M Davis
Jun 24, 2012
Ali Çehreli
Jun 24, 2012
Jonathan M Davis
Jun 24, 2012
Roman D. Boiko
Jun 24, 2012
Jonathan M Davis
Jun 24, 2012
Roman D. Boiko
Jun 24, 2012
Roman D. Boiko
June 24, 2012
immutable(SomeClass)[S] _map;
_map[S.init] = null; // doesn't compile since _map[S.init] is immutable

My current workaround is:
immutable(SomeClass)*[S] _map;
_map[S.init] = [null].ptr;

But this introduces an additional level of indirection in a performance-critical part of my code.

Probably I could cast away immutable before storing, and cast back to immutable after retrieving. But I would be more happy without these two casts. (By the way, is it correct that this way would be more efficient?)

Is there any other way to put immutable values into a dictionary?
June 24, 2012
On Sunday, June 24, 2012 13:57:44 Roman D. Boiko wrote:
> immutable(SomeClass)[S] _map;
> _map[S.init] = null; // doesn't compile since _map[S.init] is
> immutable
> 
> My current workaround is:
> immutable(SomeClass)*[S] _map;
> _map[S.init] = [null].ptr;
> 
> But this introduces an additional level of indirection in a performance-critical part of my code.
> 
> Probably I could cast away immutable before storing, and cast back to immutable after retrieving. But I would be more happy without these two casts. (By the way, is it correct that this way would be more efficient?)
> 
> Is there any other way to put immutable values into a dictionary?

Use std.typecons.Rebindable.

- Jonathan M Davis
June 24, 2012
On 06/24/2012 04:57 AM, Roman D. Boiko wrote:
> immutable(SomeClass)[S] _map;
> _map[S.init] = null; // doesn't compile since _map[S.init] is immutable
>
> My current workaround is:
> immutable(SomeClass)*[S] _map;
> _map[S.init] = [null].ptr;
>
> But this introduces an additional level of indirection in a
> performance-critical part of my code.
>
> Probably I could cast away immutable before storing, and cast back to
> immutable after retrieving. But I would be more happy without these two
> casts. (By the way, is it correct that this way would be more efficient?)
>
> Is there any other way to put immutable values into a dictionary?

Although it sounds like a limitation, it may be due to the fact that AA may need to rehash, which may not be suitable with immutable values.

The following are two ways of generating immutable AA values that I can think of:

import std.exception;

class SomeClass
{}

class S
{}

void main()
{
    /* By initialization */
    immutable(SomeClass)[S] _map = [ S.init : null ];

    /* By a function */
    immutable(SomeClass[S]) makeMap()
    {
        SomeClass[S] result;
        result[S.init] = null;

        return assumeUnique(result);
    }

    /* Note that the entire AA is immutable: */
    auto myImmMap = makeMap();
}

Ali
June 24, 2012
On Sunday, June 24, 2012 05:15:03 Ali Çehreli wrote:
> Although it sounds like a limitation, it may be due to the fact that AA may need to rehash, which may not be suitable with immutable values.

const and immutable types as elements of a container are problematic in general. The container generally needs to have been designed with them in mind for them to work properly - especially in D, where const and immutable are very strict, and you're not supposed to be mutating them even through casts.

- Jonathan M Davis
June 24, 2012
On Sunday, 24 June 2012 at 12:15:10 UTC, Ali Çehreli wrote:
> Although it sounds like a limitation, it may be due to the fact that AA may need to rehash, which may not be suitable with immutable values.
Thanks, now I can see the motivation.

> The following are two ways of generating immutable AA values that I can think of:
>
> import std.exception;
>
> class SomeClass
> {}
>
> class S
> {}
>
> void main()
> {
>     /* By initialization */
>     immutable(SomeClass)[S] _map = [ S.init : null ];
>
>     /* By a function */
>     immutable(SomeClass[S]) makeMap()
>     {
>         SomeClass[S] result;
>         result[S.init] = null;
>
>         return assumeUnique(result);
>     }
>
>     /* Note that the entire AA is immutable: */
>     auto myImmMap = makeMap();
> }
>
> Ali
Unfortunately, this doesn't fit my use case. I needed this to memoize creation of immutable objects. I plan to not use AA in the future (it is possible to optimize, since the key is some string), so this is not a critical problem in my case. I was just wondering.
June 24, 2012
On Sunday, 24 June 2012 at 12:21:50 UTC, Jonathan M Davis wrote:
> On Sunday, June 24, 2012 05:15:03 Ali Çehreli wrote:
>> Although it sounds like a limitation, it may be due to the fact that AA
>> may need to rehash, which may not be suitable with immutable values.
>
> const and immutable types as elements of a container are problematic in
> general. The container generally needs to have been designed with them in mind
> for them to work properly - especially in D, where const and immutable are
> very strict, and you're not supposed to be mutating them even through casts.
>
> - Jonathan M Davis

Yeah, but I wonder that such a core feature as AA doesn't support this use case better (I mean more efficiently).
June 24, 2012
On Sunday, June 24, 2012 14:24:48 Roman D. Boiko wrote:
> Yeah, but I wonder that such a core feature as AA doesn't support this use case better (I mean more efficiently).

The current AA implementation is quite buggy. It works, but there are all kinds of corner cases which it doesn't handle properly. Part of the problem was that its implementation was shifted from the compiler to druntime, and it was done fairly poorly. A redesign is underway (none of which should affect its usage other than fixing bugs, since it should be entirely an implementation matter, not API), but it hasn't been completed yet.

- Jonathan M Davis
June 24, 2012
On Sunday, 24 June 2012 at 12:34:28 UTC, Jonathan M Davis wrote:
> On Sunday, June 24, 2012 14:24:48 Roman D. Boiko wrote:
>> Yeah, but I wonder that such a core feature as AA doesn't support
>> this use case better (I mean more efficiently).
>
> The current AA implementation is quite buggy. It works, but there are all
> kinds of corner cases which it doesn't handle properly. Part of the problem
> was that its implementation was shifted from the compiler to druntime, and it
> was done fairly poorly. A redesign is underway (none of which should affect its
> usage other than fixing bugs, since it should be entirely an implementation
> matter, not API), but it hasn't been completed yet.
>
> - Jonathan M Davis
It would be nice to find a design which would not force the user to introduce an additional indirection (like I did in a workaround). This should not be a breaking change.