Remove array element within function
jfondren
julian.fondren at gmail.com
Mon Jul 5 14:22:24 UTC 2021
On Monday, 5 July 2021 at 13:10:55 UTC, Rekel wrote:
> Am I the only one slightly unamused by how arrays/ranges work?
> They keep backfiring on me, or require weird additions other
> languages wouldn't require such as manually changing .length,
> or worrying about what operation returns a copy etc. (Kind of
> jealous of java's ease here)
It's easy to start to learn about D's dynamic arrays and ranges
and then welcome them as false friends. They're genuinely great,
but they're not quite the same thing as what you recognized them
as, and as long as this confusion persists, frustration will
occur. You were probably expecting dynamic arrays to work like a
class:
```d
import std.array, std.algorithm;
class Array {
int[] data;
this(int[] xs) { data = xs; }
}
void removeEvens(Array a) {
a.data = a.data.filter!"a%2".array;
}
unittest {
auto h = new Array([1, 2, 4, 5]);
h.removeEvens;
assert(h.data == [1, 5]);
}
```
removeEvens gets a reference to a thing, it mutates it, job done.
An int[] parameter though is a copy of a slice. It's more like
like this struct:
```d
import std.array, std.algorithm;
struct Array {
int* data;
size_t length;
this(int[] xs) { data = xs.ptr; length = xs.length; }
}
void removeEvens(Array a) {
for (size_t i = 0; i < a.length; ++i) {
if (a.data[i] % 2 == 0) {
a.data[0 .. a.length].remove!(SwapStrategy.stable)(i);
a.length--;
i--; // !
}
}
}
unittest {
auto h = Array([1, 2, 4, 5]);
h.removeEvens;
assert(h.data[0 .. h.length] == [1, 5, 5, 5]);
}
```
before removeEvens exits, its copy of a has become the intended
2-length array with only odd elements, but that copy is thrown
away and the original 4-length array just sees its memory changed
to have a 2-array prefix of its old odd elements, and then it has
a suffix of garbage.
Of ranges, they look like visual pipelines of functions that
directly alter data that flows through them, but their actual
result is *the pipeline* and not the data. Range functions take
shorter bits of pipeline as an argument and produce longer bits
of pipeline as a result, and their errors are all pipeline
related: "I only connect to sorted ranges", "I only connect to
randomly-accessible ranges", etc.
On Monday, 5 July 2021 at 13:34:50 UTC, Rekel wrote:
> Also, is my use of long correct? The documentation wasn't very
> clear on the return type of remove, just calling it a 'number'.
What use of long?
remove returns the same type of range as it gets:
```
Range remove(SwapStrategy s = SwapStrategy.stable, Range,
Offset...)(Range range, Offset offset)
^^^^^ ^^^^^
^^^^^
```
The first Range is the return type, the second Range is a
template type parameter, and the third Range is the argument
type. When you remove from an int[] you're calling a specialized
function that returns an int[]
More information about the Digitalmars-d-learn
mailing list