Thread overview
Bad AA behavior
Dec 24, 2006
BCS
Dec 24, 2006
Dave
Dec 24, 2006
BCS
Dec 24, 2006
Kirk McDonald
Dec 27, 2006
Serg Kovrov
Dec 24, 2006
%u
Dec 24, 2006
BCS
Dec 26, 2006
%u
Dec 27, 2006
BCS
December 24, 2006
void main()
{
	byte[char[]] set;
	char[] it = "it".dup;
	set[it] = 0;
	assert("it" in set);	// pass
	it[0] = 'a';
	it[1] = 'a';
	assert("it" in set);	// fail
}


This can't be correct.

Anyone second that?
December 24, 2006
BCS wrote:
> void main()
> {
>     byte[char[]] set;
>     char[] it = "it".dup;
>     set[it] = 0;
>     assert("it" in set);    // pass
>     it[0] = 'a';
>     it[1] = 'a';
>     assert("it" in set);    // fail
> }
> 
> 
> This can't be correct.
> 

I believe it is correct because of the distinction between value and reference types made throughout D. I don't find the behavior inconsistent, although I've been bitten by it once or twice so I'd agree that it's not always intuitive.

byte[char[]] set; // is an array of bytes indexed by char[]'s (a reference type)

//set[it] = 0;
set[it.dup] = 0; // this (obviously) will do what you expect

To get the behavior you suggest (and be consistent), then UDT's would all have to have a copy ctor, either explicit or implicit. If implicit, then how is the compiler supposed to do a deep copy on objects defined like:

class C
{
    char* ptr;
    //...
}

?

If manual memory management for D was the norm, then I'd say you have a much stronger argument. But since GC is the norm. (and in part because GC is the norm D also does away with copy ctor's) the current behavior is correct, IMHO.

- Dave
December 24, 2006
Dave wrote:
> BCS wrote:
>> void main()
>> {
>>     byte[char[]] set;
>>     char[] it = "it".dup;
>>     set[it] = 0;
>>     assert("it" in set);    // pass
>>     it[0] = 'a';
>>     it[1] = 'a';
>>     assert("it" in set);    // fail
>> }
>>
>>
>> This can't be correct.
>>
> 
> I believe it is correct because of the distinction between value and reference types made throughout D. I don't find the behavior inconsistent, although I've been bitten by it once or twice so I'd agree that it's not always intuitive.
> 
> byte[char[]] set; // is an array of bytes indexed by char[]'s (a reference type)
> 
> //set[it] = 0;
> set[it.dup] = 0; // this (obviously) will do what you expect
> 
> To get the behavior you suggest (and be consistent), then UDT's would all have to have a copy ctor, either explicit or implicit. If implicit, then how is the compiler supposed to do a deep copy on objects defined like:
> 
> class C
> {
>     char* ptr;
>     //...
> }
> 
> ?
> 
> If manual memory management for D was the norm, then I'd say you have a much stronger argument. But since GC is the norm. (and in part because GC is the norm D also does away with copy ctor's) the current behavior is correct, IMHO.
> 
> - Dave

Good point. But what about this

void main()
{
    byte[char[]] set;
    char[] it = "it".dup;
    set[it] = 0;
    assert("it" in set);    // pass
    it[0] = 'a';
    it[1] = 'a';
    assert(set.keys[0] in set);    // fail
}

Furthermore, once the underling data is changed, the member can't be accessed even to remove it.

set.remove(set.keys[0]); // has no effect

I'll admit that I don't known what to do with the object/struct case, but I think the current behavior isn't good.
December 24, 2006
== Quote from BCS (BCS@pathilink.com)'s article
> 	set[it] = 0;

This should read

        set[it.dup] = 0;
December 24, 2006
BCS wrote:
> Good point. But what about this
> 
> void main()
> {
>     byte[char[]] set;
>     char[] it = "it".dup;
>     set[it] = 0;
>     assert("it" in set);    // pass
>     it[0] = 'a';
>     it[1] = 'a';
>     assert(set.keys[0] in set);    // fail
> }
> 
> Furthermore, once the underling data is changed, the member can't be accessed even to remove it.
> 
> set.remove(set.keys[0]); // has no effect
> 
> I'll admit that I don't known what to do with the object/struct case, but I think the current behavior isn't good.

And this is why dictionary keys are required to be immutable in Python (and numbers, strings, and tuples are all immutable types).

-- 
Kirk McDonald
Pyd: Wrapping Python with D
http://pyd.dsource.org
December 24, 2006
%u wrote:
> == Quote from BCS (BCS@pathilink.com)'s article
>> 	set[it] = 0;
> 
> This should read
> 
>         set[it.dup] = 0;

This is my point, actual. Doing anything else is asking for trouble, so why doesn't the runtime do it for you?
December 26, 2006
== Quote from BCS (BCS@pathilink.com)'s article
> Doing anything else is asking for trouble

No. In case the coder knows that the key is immutable a duplication is superfluous. A superfluous duplication is dangerous if the duplicated key is relatively large to the remaining free memeory.
December 27, 2006
Kirk McDonald wrote:
> BCS wrote:
>> Furthermore, once the underling data is changed, the member can't be accessed even to remove it.
>>
>> set.remove(set.keys[0]); // has no effect
>>
>> I'll admit that I don't known what to do with the object/struct case, but I think the current behavior isn't good.
> 
> And this is why dictionary keys are required to be immutable in Python (and numbers, strings, and tuples are all immutable types).

I have stepped on arrays-related rakes in D, oh-so-many times...
Wonder what Walter will comment on that one.

-- 
serg.
December 27, 2006
%u wrote:
> == Quote from BCS (BCS@pathilink.com)'s article
>> Doing anything else is asking for trouble
> 
> No. In case the coder knows that the key is immutable a duplication
> is superfluous. A superfluous duplication is dangerous if the
> duplicated key is relatively large to the remaining free memeory.

OK so you end up asking for trouble either way.

I still don't /like/ it, and will still live with it. maybe some note should be added to the AA section of the docs.