October 04, 2008
Reply to Saaa,

>> uint at = 0;
>> 
>> if(extra <= at) data.length = (at+1)*2;
>> 
> extra=data.length; ?
> 

Yes, Oops, (darn remnants :-)

>> data[at] = t;
>> at++;
>> //when done adding
>> data.length = at;
> Initially I'd be adding a lot, but after that only sparsely.
> 
>> another option would be to use an AA if order isn't relevant.
>> 
>> T[int] data;
>> 
> Is this code? I mean should there be an int or 'int'?
> 

It's a variables declaration (with T being the type that is needed).

>> void reg(T b)
>> {
>> static int a = 0;
>> data[a++] = b;
> How does this work when it's no dynamic array?
> 

http://www.digitalmars.com/d/1.0/arrays.html#associative

It's a hash table, the key is "a". It's incremented so that you get a unique value for each insertion. ("data[rand()] = b;" might work also)

you can also flip it the other way

int[T] data;
...
data[b] = 0;

to access the data:  data.keys.


>> }
>> 



October 04, 2008
Reply to Denis,

> On Sat, 04 Oct 2008 16:34:56 +0400, Saaa <empty@needmail.com> wrote:
> 
>>>>> deleting is even more annoying.
>>>>> 
>>>> You don't have to delete anything.  This is what the GC is for.
>>>> 
>>> delete could be "remove element 42 from an array of 54 resulting an
>>> an array of 53"
>>> 
>>> data = data[0..42] ~ data[43..$];
>>> or
>>> data[42..$-1] = data[43..$].dup; // in-place sortof
>>> data.length = data.length-1;
>> Yes, like that :)
>> What is the difference between those two? I mean, what do you mean by
>> in-place.
> First one allocates new memory block.
> Second one attempts to erase an element in-place. Dupping, however,
> allocates new memory, too.
> The best solution would be as follows:
> void eraseNth(ref T[] data, int n) {
> data[n] = data[$-1];
> data.length = data.length - 1;
> }

The added speed from array copy optimizations might overcome the cost of alocing. OTOH use memmove and you will do even better.


October 04, 2008
"bearophile" wrote
> Steven Schveighoffer:
>> If you want the memory removed as soon as possible, you should zero out
>> the
>> last element, otherwise, the GC will still think the element is being
>> pointed to:
>> data[n] = data[$-1];
>> data[$-1] = null;
>> data.length = data.length - 1;
>
> Really?? Is that another bug of dynamic arrays? I have assumed that
> dynamic arrays do such things automatically.
> I do that in my collections, for example:
>
> ...
> void length(int newlen) {
>    if (newlen < 0 || newlen > this._length)
>        throw new ArgumentException("ArrayBuilder.length(newlen):"
>                                    " newlen < 0 || newlen >
> ArrayBuilder.length");
>    static if (IsReferenceType!(T)) {
>        static if (IsStaticArray!(T)) {
>            T Tinit;
>            this.data[newlen .. this._length][] = Tinit;
>        } else {
>            this.data[newlen .. this._length] = T.init;
>        }
>    }
>    this._length = newlen;
> }
> ...
>
> If what you say is true, then it deserves a space on bugzilla and to be fixed soon.

Setting data.length to one less is equivalent to:

data = data[0..$-1];

Which effectively leaves the pointer to the class untouched in the unused portion of the memory.  However, the memory is still valid in terms of the GC.  The GC scans the entire block for pointers, even if you aren't using all of the block.  That is why it always zeros out memory before giving it to you.

If setting the length to less than the original value did something special like zero out the now unused elements, then weird things would happen.

for example:

int[] data = [0,1,2,3,4].dup;

int[] dataslice = data[0..2];
dataslice.length = 1;

assert(data[1] == 1); // this would fail

-Steve


October 04, 2008
> for example:
>
> int[] data = [0,1,2,3,4].dup;
why the dup?

>
> int[] dataslice = data[0..2];
> dataslice.length = 1;
>
> assert(data[1] == 1); // this would fail
>
> -Steve

Rest makes sense.


October 04, 2008
reading . . :)


October 04, 2008
Steven Schveighoffer:
> int[] data = [0,1,2,3,4].dup;
> int[] dataslice = data[0..2];
> dataslice.length = 1;
> assert(data[1] == 1); // this would fail

I see, the current light semantics of slices require the extra data to be kept. You are right, and I am glad to be wrong :-)
(That collection I have shown can't be sliced, but in special situations that problem may be present. I'll have to think about it).

Thank you for your answers,
bye,
bearophile
October 04, 2008
On Sun, 05 Oct 2008 01:37:30 +0400, Saaa <empty@needmail.com> wrote:

>
>> for example:
>>
>> int[] data = [0,1,2,3,4].dup;
> why the dup?
>

because [0,1,2,3,4] is readonly

>>
>> int[] dataslice = data[0..2];
>> dataslice.length = 1;
>>
>> assert(data[1] == 1); // this would fail
>>
>> -Steve
>
> Rest makes sense.
>
>
October 04, 2008
On Sat, 04 Oct 2008 22:02:43 +0400, Steven Schveighoffer <schveiguy@yahoo.com> wrote:

>
> "Saaa" <empty@needmail.com> wrote in message
> news:gc8314$24e0$1@digitalmars.com...
>>
>>>
>>> First one allocates new memory block.
>>> Second one attempts to erase an element in-place. Dupping, however,
>>> allocates new memory, too.
>>> The best solution would be as follows:
>>>
>>> void eraseNth(ref T[] data, int n) {
>>>     data[n] = data[$-1];
>>>     data.length = data.length - 1;
>>> }
>>
>> Yay, thats how I do it :)
>
> If you want the memory removed as soon as possible, you should zero out the
> last element, otherwise, the GC will still think the element is being
> pointed to:
>
> data[n] = data[$-1];
> data[$-1] = null;
> data.length = data.length - 1;
>
> -Steve
>
>

Great advice, thanks!
October 05, 2008
On Sat, Oct 4, 2008 at 2:22 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> Saaa:
>> foreach (Fruit f; fruit)
>> {
>> f.stuff();
>> }
>
> Note that often this is enough:
>
> foreach (f; fruit)
>    f.stuff;
>
> But I generally put the parentheses:
>
> foreach (f; fruit)
>    f.stuff();
>
> Bye,
> bearophile
>

Uh, ok, who cares what coding style you use?
October 05, 2008
Jarrett Billingsley:
> Uh, ok, who cares what coding style you use?

Python and Ruby teach that in a language a more uniform coding style helps people understand each other code faster (and similar things), and that leads to more modules done. And nowadays already done modules that you can find on the net make a language successful instead of an ignored one. I know that the usual culture of C/C++ may be a little against such "freedoms", so I presume a significant part of the D community may not appreciate that.
That also shows a disadvantage of Lisp-style macros, because having lot of customizations makes code less easy to understand by other people.

And the OP may be unaware of some of the syntactic peculiarities of D, so it's useful to show them.

Bye,
bearophile