Principled method of lookup-or-insert in associative arrays?

Tomek Sowiński just at ask.me
Sat Nov 20 06:45:58 PST 2010


Andrei Alexandrescu <SeeWebsiteForEmail at erdani.org> napisał(a):

> TDPL has an example that can be reduced as follows:
>
> void main() {
>    uint[string] map;
>    foreach (line; stdin.byLine()) {
>      ++map[line];
>    }
> }
>
> byLine reuses its buffer so it exposes it as char[]. Therefore,  
> attempting to use map[line] will fail. The program compiled and did the  
> wrong thing because of a bug.
>
> The challenge is devising a means to make the program compile and work  
> as expected. Looking up an uint[string] with a char[] should work, and  
> if the char[] is to be inserted, a copy should be made (via .idup or  
> to!string). The rule needs to be well defined and reasonably general.
>
> The effect is something like this:
>
> void main() {
>    uint[string] map;
>    foreach (line; stdin.byLine()) {
>      auto p = line in map;
>      if (p) ++*p;
>      else map[line.idup] = 1;
>    }
> }
>
> Ideally the programmer would write the simple code (first snippet) and  
> achieve the semantics of the more complex code (second snippet). Any  
> ideas?

To be honest I find the 2nd snippet more readable, it's just one line more:

   uint[string] map;
   foreach (line; stdin.byLine()) {
     if (auto p = line in map) ++*p;
     else map[line.idup] = 1;
   }

You know exactly what it does and it's const correct. I don't see value in  
implicit cloning.

The first example smells of STL map[key] -- if key is not found, it  
implicitly inserts key, initializes the value, and returns a reference.  
Let's not go there.

-- 
Tomek


More information about the Digitalmars-d mailing list