www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Bad AA behavior

reply BCS <BCS pathilink.com> writes:
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?
Dec 23 2006
next sibling parent reply Dave <Dave_member pathlink.com> writes:
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
Dec 23 2006
parent reply BCS <BCS pathilink.com> writes:
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.
Dec 23 2006
parent reply Kirk McDonald <kirklin.mcdonald gmail.com> writes:
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
Dec 24 2006
parent Serg Kovrov <kovrov no.spam> writes:
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.
Dec 26 2006
prev sibling parent reply %u <it set.com> writes:
== Quote from BCS (BCS pathilink.com)'s article
 	set[it] = 0;

This should read set[it.dup] = 0;
Dec 24 2006
parent reply BCS <BCS pathilink.com> writes:
%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?
Dec 24 2006
parent reply %u <u digitaldaemon.com> writes:
== 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.
Dec 25 2006
parent BCS <BCS pathilink.com> writes:
%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.
Dec 27 2006