Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
October 24, 2015 `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to rsw0x | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Shriramana Sharma | 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 Re: `clear`ing a dynamic array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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 |
Copyright © 1999-2021 by the D Language Foundation