'auto' with AA
David Held via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Mon Apr 28 00:12:55 PDT 2014
On 4/27/2014 9:32 PM, Ali Çehreli wrote:
> fOn 04/27/2014 06:00 PM, David Held wrote:
>
> > I would like to do something like this:
> >
> > Foo[Bar][Baz] nestedAA;
> > auto innerAA = nestedAA[someBaz];
> > innerAA[someBar] = someFoo;
> > assert(someFoo in nestedAA[someBaz]);
>
> in operator uses a key, not a value. This should work:
>
> assert(someBar in nestedAA[someBaz]);
Sorry, that is what I meant to say.
That is, modifying nestedAA through innerAA does not seem to work, which
is why I assumed it was a copy. However, I'm pretty sure that if I use
auto on an array, I will get a reference:
int[][] matrix = [[1, 2, 3, 4]];
auto array = matrix[0];
array[3] = 42;
assert(matrix[0][3] == 42);
This works just fine. I assumed that AAs were like arrays, and thus,
would work like references. Here is a compilable example which fails:
void main()
{
double[int][string] nestedAA;
nestedAA["test"] = null;
auto innerAA = nestedAA["test"];
innerAA[42] = 3.14;
assert(42 in nestedAA["test"]);
}
Note that I can even assign 'null' to the nested AA, which implies to me
that it's a reference type! Now, the problem may be that null is
exactly what gets assigned to innerAA. But then, why am I able to
happily index it on the very next line? And what exactly does it mean
for an AA to be assigned 'null'? This is perfectly legal, but I don't
know what it means:
double[int] aa = null;
It appears to be a NOP, and indistinguishable from:
double[int] aa;
In fact, this appears to be the source of the problem. If I change the
null assignment above to:
nestedAA["test"] = [1:1.0];
then everything works as expected, which means that innerAA really is a
reference. What is really bizarre is this idea that it starts out as a
presumed null reference, and becomes instantiated through use. Note
that this is inconsistent with arrays:
double[] a = null;
a[0] = 3.14; // Range violation
I suppose the difference is that naming an invalid key in an AA inserts
the key, but naming an invalid index in an array does not. What is
peculiar is that the above is a *range violation* and not an *access
violation*. It seems to me that the real problem is that a doesn't
*refer to an actual array*. So how can an index into 'a' violate its range?
The problem I have with the AA solution above is that I have to create
some mapping to "instantiate" the nested AA. I thought I would be
clever and create a default initializer, like so:
nestedAA["test"] = (double[int]).init;
Unfortunately, this appears to be equivalent to assigning null, which I
assume is the actual value of .init above[1]. Of course, arrays and AAs
are "magical" types in D, but it is a little frustrating that an empty
initializer is reduced to the null initializer, even though the empty
state is not the same as the null state:
double[int][string] nestedAA;
nestedAA["test"] = null;
auto innerAA = nestedAA["test"];
assert(innerAA.length == 0); // empty
assert(innerAA is null); // null
innerAA[42] = 3.14;
assert(innerAA !is null); // not null
innerAA.remove(42);
assert(innerAA.length == 0); // empty
assert(innerAA !is null); // still not null!
If there were an initializer which put the AA in the final state above,
then I would be happy. I'm sure that .init == null for performance
reasons, but I don't see why there isn't some initializer syntax which
creates a truly empty-but-not-null state, other than that not enough
people needed it. I propose something like:
double[int] aa = [void:void];
assert(aa.length == 0);
assert(aa !is null);
Unfortunately, this is exactly backwards. This *should* be the syntax
to make a "null" AA, and .init should make the empty one. But history
has prevented that solution. Anything I'm missing?
Dave
[1] Unfortunately, .init is not documented here:
http://dlang.org/hash-map.html even though it is documented for arrays
More information about the Digitalmars-d-learn
mailing list