On 21/03/12 21:41, Alvaro wrote:
El 21/03/2012 19:39, Jonathan M Davis escribió:
On Wednesday, March 21, 2012 11:29:14 H. S. Teoh wrote:
A question was asked on the d-learn forum about why this throws a
RangeError:

int[string][int] map;
map["abc"][20]++;

This is understandable, since the compiler translates the second line
to:

map.opIndex("abc").opIndexUnary!"++"(20);

Since map["abc"] doesn't exist yet, opIndex throws RangeError before we
ever get to the ++.

I'd like to propose the following fix: if a given chained indexing
expression has any operator applied to its final result (either a unary
operator like ++ or --, or an assignment operator like +=), then instead
of translating previous indexes into opIndex, the compiler should map it
to a new operator overload, say opIndexCreate, which creates the
relevant entry with default value if it doesn't exist yet. That is to
say:

map["abc"][20]++;

should be translated to:

map.opIndexCreate("abc").opIndexUnary!"++"(20);

where opIndexCreate looks something like:

Slot opIndexCreate(Key k) {
Slot *s = findSlot(k);
if (s is null) {
s = createNewSlot(k);
}
return s;
}

Similar changes should be made for expressions like a[b][c][d]=100, or
a[b][c][d]+=100.

In other words, if the tail of a chain of indexing operations maps to
opIndexAssign, opIndexUnary, or opIndexOpAssign, then all preceding
opIndex calls should be converted to opIndexCreate instead.

Comments?

IMHO, it's _horrible_ that C++ creates entries in a std::map when you
ask for
values that aren't there. A RangeError is _exactly_ what should be
happening
here. There's no element to increment, because it hasn't been added
yet. I
think that the current behavior is very much what the behavior
_should_ be.

- Jonathan M Davis

I partially disagree. I think items should be added if we try to *write*
to them, but not when we *read* them (lvalue vs rvalue). The problem is
that it's hard to distinguish those cases in C++ without an intermediate
class that makes its use uglier. So:

int[int] a;
a[3] = 1; // OK, add key 3
b = a[5]; // error, add nothing

And, compound assignment and increment/decrement are forms of *writing*.

Yes, but they read before they write.

So, they should trigger an element creation with the .init value.

a[5]++; // create a[5] = int.init; and then increment

Reply via email to