Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
August 03, 2020 array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Hi, I just noted that D array slice does not support steps? https://dlang.org/articles/d-array-article.html Ever since Python 1.4, the slicing syntax has supported an optional third ``step'' or ``stride'' argument. For example, these are all legal Python syntax: L[1:10:2], L[:-1:1], L[::-1]. This was added to Python at the request of the developers of Numerical Python, which uses the third argument extensively. https://docs.python.org/2.3/whatsnew/section-slices.html >>> L = range(10) >>> L[::2] [0, 2, 4, 6, 8] Shall we add a DIP for this? |
August 03, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Monday, 3 August 2020 at 23:32:29 UTC, mw wrote: > Hi, > > I just noted that D array slice does not support steps? > You can use std.range.stride for this: http://dpldocs.info/experimental-docs/std.range.stride.html |
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Monday, 3 August 2020 at 23:50:45 UTC, Paul Backus wrote:
> On Monday, 3 August 2020 at 23:32:29 UTC, mw wrote:
>> Hi,
>>
>> I just noted that D array slice does not support steps?
>>
>
> You can use std.range.stride for this:
>
> http://dpldocs.info/experimental-docs/std.range.stride.html
OK, good to know.
But if it's built into the language syntax (as extended array slicing), it will be better: more succinct, and much easier for Python programmers to adopt D.
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Tuesday, 4 August 2020 at 00:03:16 UTC, mw wrote:
> On Monday, 3 August 2020 at 23:50:45 UTC, Paul Backus wrote:
>>
>> You can use std.range.stride for this:
>>
>> http://dpldocs.info/experimental-docs/std.range.stride.html
>
> OK, good to know.
>
> But if it's built into the language syntax (as extended array slicing), it will be better: more succinct, and much easier for Python programmers to adopt D.
In general, D tries to avoid adding special-purpose syntax for things that can be easily solved with library code.
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Monday, 3 August 2020 at 23:32:29 UTC, mw wrote:
> Hi,
>
> I just noted that D array slice does not support steps?
>
> https://dlang.org/articles/d-array-article.html
>
>
> Ever since Python 1.4, the slicing syntax has supported an optional third ``step'' or ``stride'' argument. For example, these are all legal Python syntax: L[1:10:2], L[:-1:1], L[::-1]. This was added to Python at the request of the developers of Numerical Python, which uses the third argument extensively.
>
> https://docs.python.org/2.3/whatsnew/section-slices.html
>
>>>> L = range(10)
>>>> L[::2]
> [0, 2, 4, 6, 8]
>
>
> Shall we add a DIP for this?
Since D slices are just views of memory, this would either change how slicing works (copy the data when using stride), or change the memory layout of slices.
Currently, a slice is essentially a (ptr, length) struct, and adding stride to the mix would require adding another field to every slice. This would break all D code ever, so we can disregard that solution.
Copying the data doesn't actually break any code, since the no-stride case would be unaffected, and is the only case currently in use. However, having a different behavior here would break the principle of least astonishment.
Lastly, there's std.range.stride, which is an excellent workaround with none of these drawbacks.
All in all, a DIP is very unlikely to be accepted given the above.
--
Simen
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to mw | On Tuesday, 4 August 2020 at 00:03:16 UTC, mw wrote:
> On Monday, 3 August 2020 at 23:50:45 UTC, Paul Backus wrote:
>> On Monday, 3 August 2020 at 23:32:29 UTC, mw wrote:
>>> Hi,
>>>
>>> I just noted that D array slice does not support steps?
>>>
>>
>> You can use std.range.stride for this:
>>
>> http://dpldocs.info/experimental-docs/std.range.stride.html
>
> OK, good to know.
>
> But if it's built into the language syntax (as extended array slicing), it will be better: more succinct, and much easier for Python programmers to adopt D.
just act like this is syntax in the language and not a function call:
auto x = array[0 .. 10].stride(2);
I think readability-wise this beats other syntax you can come up with and it's just a library solution :)
If you then want to copy it into an actual array you can pass as slice use
auto x = array[0 .. 10].stride(2).array;
or adjust your functions to handle ranges properly :p
On the function implementation side I can definitely see room for improvement though, like the signatures DIP rikkimax had once made which would make templates not needed for supporting passing and storing ranges.
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On Tuesday, 4 August 2020 at 07:39:04 UTC, Simen Kjærås wrote:
> [snip]
> Currently, a slice is essentially a (ptr, length) struct, and adding stride to the mix would require adding another field to every slice. This would break all D code ever, so we can disregard that solution.
[snip]
I think I've suggested something similar in the past. I don't understand why another field is required as it would just be some special syntax over indexing.
For instance, I would imagine it used like
auto x = [1, 2, 3, 4, 5, 6, 7];
auto y = x[0..2..5];
assert(y == [1, 3, 5]);
This would be marginally different from python, which puts the strides last and uses colons (which I prefer), but its the same general idea (other languages have similar behavior).
A language like Chapel optionally allows for strides (which do take up space). A user-defined type in D could do the same thing. If the stride is a compile-time type, then you could have a specialization where the stride is 1 and does not take up space.
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to jmh530 | On Tuesday, 4 August 2020 at 13:15:39 UTC, jmh530 wrote:
> On Tuesday, 4 August 2020 at 07:39:04 UTC, Simen Kjærås wrote:
>> [snip]
>> Currently, a slice is essentially a (ptr, length) struct, and adding stride to the mix would require adding another field to every slice. This would break all D code ever, so we can disregard that solution.
> [snip]
>
> I think I've suggested something similar in the past. I don't understand why another field is required as it would just be some special syntax over indexing.
>
> For instance, I would imagine it used like
> auto x = [1, 2, 3, 4, 5, 6, 7];
> auto y = x[0..2..5];
> assert(y == [1, 3, 5]);
Currently, when you do `y = x[0..5]`, both x and y point to the same memory.
In order for `y == [1, 3, 5]` to be true, one of the following must hold:
1) y points to memory which contains 1, 3, and 5 in contiguous locations.
2) y has an overloaded == operator which takes the stride into account.
If #1 is true, then y cannot point to the same memory as x, which means a copy has to be made. If #2 is true, then y cannot be a simple int[], but must instead be a custom type that stores the stride in addition to a pointer and a length.
As WebFreak001 pointed out, you can get the "custom type" version with `x[0..5].stride(2)`, and the the "array with copied elements" version with `x[0..5].stride(2).array`.
|
August 04, 2020 Re: array slicing currently does not support steps? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Paul Backus | On Tuesday, 4 August 2020 at 14:52:49 UTC, Paul Backus wrote:
> [snip]
>
> Currently, when you do `y = x[0..5]`, both x and y point to the same memory.
>
> In order for `y == [1, 3, 5]` to be true, one of the following must hold:
>
> 1) y points to memory which contains 1, 3, and 5 in contiguous locations.
> 2) y has an overloaded == operator which takes the stride into account.
>
> If #1 is true, then y cannot point to the same memory as x, which means a copy has to be made. If #2 is true, then y cannot be a simple int[], but must instead be a custom type that stores the stride in addition to a pointer and a length.
>
> As WebFreak001 pointed out, you can get the "custom type" version with `x[0..5].stride(2)`, and the the "array with copied elements" version with `x[0..5].stride(2).array`.
Thanks, that makes sense.
|
Copyright © 1999-2021 by the D Language Foundation