www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to remove all items in an associative array?

reply Yang Bo <pop.atry gmail.com> writes:
http://www.digitalmars.com/d/statement.html said:

The aggregate must be loop invariant, meaning that elements to the
aggregate cannot be added or removed from it in the
NoScopeNonEmptyStatement.

So, how can I remove them?
Oct 18 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Yang Bo wrote:
 http://www.digitalmars.com/d/statement.html said:
 
 The aggregate must be loop invariant, meaning that elements to the
 aggregate cannot be added or removed from it in the
 NoScopeNonEmptyStatement.
 
 So, how can I remove them?

I don't understand the body, but the answer to the question in the subject line is AA = null; or AA = AA.init; http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Arrays
Oct 18 2007
parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Bill Baxter wrote:
 Yang Bo wrote:
 http://www.digitalmars.com/d/statement.html said:

 The aggregate must be loop invariant, meaning that elements to the
 aggregate cannot be added or removed from it in the
 NoScopeNonEmptyStatement.

 So, how can I remove them?

I don't understand the body, but the answer to the question in the subject line is AA = null; or AA = AA.init;

Since quite a while ago, the D associative arrays have become pure reference types. While the above has the apparent effect of clearing the array, it does in fact just reassign the current reference. If you have several references to the same associative array, the above will not clear the actual array referred to. To clear the actual array, you need to resort to hackery. Something like this should definitely be included in the compiler/runtime. private struct BB { void*[]b; size_t nodes; } private union ToPtr(T) {T x; void * ptr; } void clear(T,E)(T[E] aa) { ToPtr!(typeof(aa)) toptr; toptr.x = aa; BB* b = cast(BB*) toptr.ptr; if (b) { b.b = null; b.nodes = 0; } }
 http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Arrays

I rewrote that section in a way that hopefully explains the semantics better. This question comes up frequently enough to merit an addition to the official documentation and a clear/deleteAll implementation (like the one above) should definitely be added to the language and phobos/internal/aaA.d. -- Oskar
Oct 18 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Oskar Linde wrote:
 Bill Baxter wrote:
 Yang Bo wrote:
 http://www.digitalmars.com/d/statement.html said:

 The aggregate must be loop invariant, meaning that elements to the
 aggregate cannot be added or removed from it in the
 NoScopeNonEmptyStatement.

 So, how can I remove them?

subject line is AA = null; or AA = AA.init;

Since quite a while ago, the D associative arrays have become pure reference types. While the above has the apparent effect of clearing the array, it does in fact just reassign the current reference. If you have several references to the same associative array, the above will not clear the actual array referred to. To clear the actual array, you need to resort to hackery. Something like this should definitely be included in the compiler/runtime. private struct BB { void*[]b; size_t nodes; } private union ToPtr(T) {T x; void * ptr; } void clear(T,E)(T[E] aa) { ToPtr!(typeof(aa)) toptr; toptr.x = aa; BB* b = cast(BB*) toptr.ptr; if (b) { b.b = null; b.nodes = 0; } }
 http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Arrays

I rewrote that section in a way that hopefully explains the semantics better. This question comes up frequently enough to merit an addition to the official documentation and a clear/deleteAll implementation (like the one above) should definitely be added to the language and phobos/internal/aaA.d.

Interesting tidbit. Thanks for the info and for updating that page. --bb
Oct 18 2007
parent reply Gregor Richards <Richards codu.org> writes:
Bill Baxter wrote:
 Oskar Linde wrote:
 Bill Baxter wrote:
 Yang Bo wrote:
 http://www.digitalmars.com/d/statement.html said:

 The aggregate must be loop invariant, meaning that elements to the
 aggregate cannot be added or removed from it in the
 NoScopeNonEmptyStatement.

 So, how can I remove them?

subject line is AA = null; or AA = AA.init;

reference types. While the above has the apparent effect of clearing the array, it does in fact just reassign the current reference. If you have several references to the same associative array, the above will not clear the actual array referred to. To clear the actual array, you need to resort to hackery. Something like this should definitely be included in the compiler/runtime. private struct BB { void*[]b; size_t nodes; } private union ToPtr(T) {T x; void * ptr; } void clear(T,E)(T[E] aa) { ToPtr!(typeof(aa)) toptr; toptr.x = aa; BB* b = cast(BB*) toptr.ptr; if (b) { b.b = null; b.nodes = 0; } }
 http://www.prowiki.org/wiki4d/wiki.cgi?DocComments/Arrays

better. This question comes up frequently enough to merit an addition to the official documentation and a clear/deleteAll implementation (like the one above) should definitely be added to the language and phobos/internal/aaA.d.

Interesting tidbit. Thanks for the info and for updating that page. --bb

Unless the performance is a huge hit, it would probably be wiser to use code that isn't dependent on the current implementation of AAs: foreach (k; aa.keys.dup) { aa.remove(k); } I think that's in O(nlogn). The other code is free, but implementation-specific. Ideally there would just be a .clear property :) - Gregor Richards
Oct 18 2007
parent reply Matti Niemenmaa <see_signature for.real.address> writes:
Gregor Richards wrote:
 Unless the performance is a huge hit, it would probably be wiser to use
 code that isn't dependent on the current implementation of AAs:
 
 foreach (k; aa.keys.dup) {
     aa.remove(k);
 }

I believe aa.keys is a duplicate already, meaning there is no need for the .dup. -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Oct 18 2007
parent Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Matti Niemenmaa wrote:
 Gregor Richards wrote:
 Unless the performance is a huge hit, it would probably be wiser to use
 code that isn't dependent on the current implementation of AAs:

 foreach (k; aa.keys.dup) {
     aa.remove(k);
 }

I believe aa.keys is a duplicate already, meaning there is no need for the .dup.

You are both right. I updated the DocComments page. Actually, the proper way to efficiently clear an aa might be to explicitly clear or delete the referred aaA*[] array. Leaving the GC a potentially quite large array full of pointers to dead objects might be a source of memory leaks in an imprecise GC implementation. The same potential memory leak exists in _aaRehash() today. Deleting, clearing or even mark-as-not-containing-pointers the old array when rehashing/resizing the AA should, I believe, improve the situation for the GC. -- Oskar
Oct 19 2007