Jump to page: 1 2
Thread overview
`clear`ing a dynamic array
Oct 24, 2015
Shriramana Sharma
Oct 24, 2015
Cauterite
Oct 24, 2015
anonymous
Oct 24, 2015
John Colvin
Oct 24, 2015
rsw0x
Oct 25, 2015
Shriramana Sharma
Oct 25, 2015
Olivier Pisano
Oct 25, 2015
Jonathan M Davis
Oct 25, 2015
Shriramana Sharma
Oct 26, 2015
Jonathan M Davis
Oct 25, 2015
Shriramana Sharma
Oct 25, 2015
anonymous
Oct 25, 2015
Shriramana Sharma
Oct 26, 2015
Jonathan M Davis
Oct 25, 2015
qsdfghjk
October 24, 2015
Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code:

import std.stdio;
void main()
{
  int a[] = [1,2,3,4,5];
  int b[] = a;
  writeln(a);
  writeln(b);
  //a.clear();
  a = [];
  writeln(a);
  writeln(b);
}

which outputs:

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[]
[1, 2, 3, 4, 5]

How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is:

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5]
[]
[]

... and any further items added to `a` should also reflect in `b`.

-- 
Shriramana Sharma, Penguin #395953
October 24, 2015
I'm afraid what you're asking for is impossible. Because 'a' and 'b' are both slices, they each have their own 'length' field. When you do 'a = []', you're effectively doing 'a.length = 0'. There's no way to change 'b.length' through 'a'. To get that effect, you'd have to do something like this:
	int[] a = [1,2,3,4,5];
	int[]* b = &a;
	a = [];
	assert(*b == [] && b.length == 0);

On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote:
> Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code:
>
> import std.stdio;
> void main()
> {
>   int a[] = [1,2,3,4,5];
>   int b[] = a;
>   writeln(a);
>   writeln(b);
>   //a.clear();
>   a = [];
>   writeln(a);
>   writeln(b);
> }
>
> which outputs:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> [1, 2, 3, 4, 5]
>
> How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> []
>
> ... and any further items added to `a` should also reflect in `b`.


October 24, 2015
On 24.10.2015 15:18, Shriramana Sharma wrote:
>    int a[] = [1,2,3,4,5];

Aside: `int[] a;` is the preferred style for array declarations.

> How to make it so that after clearing `a`, `b` will also point to the same
> empty array? IOW the desired output is:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> []
>
> ... and any further items added to `a` should also reflect in `b`.
>

You can't do that with built-in arrays. The length of a dynamic array is a value member of the array structure. So to update `b`'s length you need access to the actual `b`.

October 24, 2015
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote:
> Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code:
>
> import std.stdio;
> void main()
> {
>   int a[] = [1,2,3,4,5];
>   int b[] = a;
>   writeln(a);
>   writeln(b);
>   //a.clear();
>   a = [];
>   writeln(a);
>   writeln(b);
> }
>
> which outputs:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> [1, 2, 3, 4, 5]
>
> How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> []
>
> ... and any further items added to `a` should also reflect in `b`.

D's arrays are not pure reference types, they work like `struct Array(T) { size_t length; T* ptr; }` with some extra methods and operators. If you think of them like that it should be clear what is/isn't possible.

If you want to have two references to the same array, including the length, use T[]* or a ref argument to a function or wrap it in a class.
October 24, 2015
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote:
> Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code:
>
> [...]

use std.container.array
October 25, 2015
rsw0x wrote:

> use std.container.array

Thanks all for all the recommendations. When would one use std.array.appender with a built-in array vs std.container.array.Array? What are the pros and cons on either side?

-- 
Shriramana Sharma, Penguin #395953
October 25, 2015
On Saturday, 24 October 2015 at 13:18:26 UTC, Shriramana Sharma wrote:
> Hello. I had first expected that dynamic arrays (slices) would provide a `.clear()` method but they don't seem to. Obviously I can always effectively clear an array by assigning an empty array to it, but this has unwanted consequences that `[]` actually seems to allocate a new dynamic array and any other identifiers initially pointing to the same array will still show the old contents and thus it would no longer test true for `is` with this array. See the following code:
>
> import std.stdio;
> void main()
> {
>   int a[] = [1,2,3,4,5];
>   int b[] = a;
>   writeln(a);
>   writeln(b);
>   //a.clear();
>   a = [];
>   writeln(a);
>   writeln(b);
> }
>
> which outputs:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> [1, 2, 3, 4, 5]
>
> How to make it so that after clearing `a`, `b` will also point to the same empty array? IOW the desired output is:
>
> [1, 2, 3, 4, 5]
> [1, 2, 3, 4, 5]
> []
> []
>
> ... and any further items added to `a` should also reflect in `b`.

If you don't want to mess with pointers (as sugggested in the first answer) you can also use std.typecons.RefCounted:

---
import std.stdio;
import std.typecons;

RefCounted!(int[]) b;

void main()
{
  int[] a = [1,2,3,4,5];
  b = a;
  writeln(a);
  writeln(b);
  a = [];
  writeln(a);
  writeln(b);
}
October 25, 2015
On Sunday, 25 October 2015 at 04:04:29 UTC, Shriramana Sharma wrote:
> rsw0x wrote:
>
>> use std.container.array
>
> Thanks all for all the recommendations. When would one use std.array.appender with a built-in array vs std.container.array.Array? What are the pros and cons on either side?

Appender is a small wrapper that enables you to get an output range from a built-in array. It allocates using the GC. If you have an array and you need to pass it to a function that takes an output range, you can use it.

std.container.Array is a reference counted container that is equivalent to std::shared_ptr<std::vector<T>> in C++. It is not reliant on the GC.
October 25, 2015
On Sunday, October 25, 2015 09:34:25 Shriramana Sharma via Digitalmars-d-learn wrote:
> rsw0x wrote:
>
> > use std.container.array
>
> Thanks all for all the recommendations. When would one use std.array.appender with a built-in array vs std.container.array.Array? What are the pros and cons on either side?

Appender is for when you you know that you're going to be doing a whole bunch of appending to an array, and you'd normally only use it when initially filling in the array, after which you'd just get the array out of it and use the array. Appender really isn't intended to be used as a container - just as a way to make appending more efficient or to have an output range which is an array but which is appended to by put rather than just assigning to its existing elements. You don't use Appender to not use arrays or to get full reference semantics from an array.

If you want a container rather than a dynamic array - especially if you're looking for full reference semantics - then use std.container.array.Array.

- Jonathan M Davis

October 25, 2015
Thanks all, for your replies.

Jonathan M Davis via Digitalmars-d-learn wrote:

> If you want a container rather than a dynamic array - especially if you're looking for full reference semantics - then use std.container.array.Array.

Hmmm, pardon me but while I'm sure I don't specifically require reference semantics, I'm not sure how you mean to contrast a "container" vs a "dynamic array". Both are aware of their content count and both are iterable, no? Is it that by "container" you mean that something that owns its contents and is responsible for deleting them all when it itself is deleted?

-- 
Shriramana Sharma, Penguin #395953
« First   ‹ Prev
1 2