Andrei Alexandrescu <seewebsiteforem...@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

Reply via email to