digitalmars.D.learn - Why are static arrays not ranges?
- Jack Stouffer (14/14) Sep 21 2015 import std.range;
- anonymous (4/22) Sep 21 2015 How would popFront work on an `int[6]`? popFront can't change the type, ...
- Adam D. Ruppe (15/17) Sep 21 2015 try:
- Jesse Phillips (7/21) Sep 21 2015 A static array has a constant length, so it is not possible to
- Jack Stouffer (4/10) Sep 21 2015 Thanks for all of the replies. I was under the impression that
- Jonathan M Davis via Digitalmars-d-learn (18/30) Sep 21 2015 All that slicing a static array does is give you a dynamic array which
- cym13 (4/18) Sep 21 2015 For an element of explanation see my answer at a similar question
- jmh530 (78/81) Sep 21 2015 I had done basically the same thing. Below is my naive
import std.range; void main() { int[6] a = [1, 2, 3, 4, 5, 6]; pragma(msg, isInputRange!(typeof(a))); pragma(msg, isForwardRange!(typeof(a))); pragma(msg, isRandomAccessRange!(typeof(a))); } $ dmd -run test.d false false false That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives? Is there an actual reason for this?
Sep 21 2015
On Monday 21 September 2015 22:33, Jack Stouffer wrote:import std.range; void main() { int[6] a = [1, 2, 3, 4, 5, 6]; pragma(msg, isInputRange!(typeof(a))); pragma(msg, isForwardRange!(typeof(a))); pragma(msg, isRandomAccessRange!(typeof(a))); } $ dmd -run test.d false false false That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives?You can just slice them: `a[]` is an `int[]` which is a range.Is there an actual reason for this?How would popFront work on an `int[6]`? popFront can't change the type, but it must remove an element.
Sep 21 2015
On Monday, 21 September 2015 at 20:33:10 UTC, Jack Stouffer wrote:pragma(msg, isInputRange!(typeof(a)));try: pragma(msg, isInputRange!(typeof(a[]))); Notice the addition of the [] after the a. That's the slicing operator and it will yield a range.Is there an actual reason for this?A static array is a container; a block of memory. A range is a *view* into a container. When you popFront a range, you aren't modifying the underlying memory, you are just advancing the view to the next element. popFront of a static array is impossible anyway due to the immutability of its length, but even if it was possible, advancing your view to the next item should not actually delete the item if at all possible. Dynamic arrays are actually similar btw, the underlying container for them is just hidden from view because the garbage collector manages it, so all you see is the slice (view/range).
Sep 21 2015
On Monday, 21 September 2015 at 20:33:10 UTC, Jack Stouffer wrote:import std.range; void main() { int[6] a = [1, 2, 3, 4, 5, 6]; pragma(msg, isInputRange!(typeof(a))); pragma(msg, isForwardRange!(typeof(a))); pragma(msg, isRandomAccessRange!(typeof(a))); } $ dmd -run test.d false false false That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives? Is there an actual reason for this?A static array has a constant length, so it is not possible to popFront on a static array. Making a dynamic array from it is easy, just slice it with []: pragma(msg, isInputRange!(typeof(a[]))); pragma(msg, isForwardRange!(typeof(a[]))); pragma(msg, isRandomAccessRange!(typeof(a[])));
Sep 21 2015
On Monday, 21 September 2015 at 20:39:55 UTC, Jesse Phillips wrote:A static array has a constant length, so it is not possible to popFront on a static array. Making a dynamic array from it is easy, just slice it with []: pragma(msg, isInputRange!(typeof(a[]))); pragma(msg, isForwardRange!(typeof(a[]))); pragma(msg, isRandomAccessRange!(typeof(a[])));Thanks for all of the replies. I was under the impression that the slicer allocated GC, but some tests show that's not true.
Sep 21 2015
On Monday, September 21, 2015 20:46:51 Jack Stouffer via Digitalmars-d-learn wrote:On Monday, 21 September 2015 at 20:39:55 UTC, Jesse Phillips wrote:All that slicing a static array does is give you a dynamic array which refers to the static array. It's then the same as any other dynamic array except that you have to make sure that it doesn't continue to refer to the static array after the static array no longer exists, and it's guaranteed to have no extra capacity, so if you do append to it, it's guaranteed to reallocate, whereas one allocated via new may or may not have extra capacity, depending on what's been done with that dynamic array and any other dynamic arrays were sliced from it and thus may or may not have to be reallocated when it's appended to. Similarly, slicing malloced memory gets you a dynamic array which refers to malloced memory and thus has no extra capacity, and you have to be careful to not still have it around when the malloced memory is freed. I would suggest that you read this http://dlang.org/d-array-article.html and possibly watch this http://dconf.org/2015/talks/davis.html - Jonathan M DavisA static array has a constant length, so it is not possible to popFront on a static array. Making a dynamic array from it is easy, just slice it with []: pragma(msg, isInputRange!(typeof(a[]))); pragma(msg, isForwardRange!(typeof(a[]))); pragma(msg, isRandomAccessRange!(typeof(a[])));Thanks for all of the replies. I was under the impression that the slicer allocated GC, but some tests show that's not true.
Sep 21 2015
On Monday, 21 September 2015 at 20:33:10 UTC, Jack Stouffer wrote:import std.range; void main() { int[6] a = [1, 2, 3, 4, 5, 6]; pragma(msg, isInputRange!(typeof(a))); pragma(msg, isForwardRange!(typeof(a))); pragma(msg, isRandomAccessRange!(typeof(a))); } $ dmd -run test.d false false false That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives? Is there an actual reason for this?For an element of explanation see my answer at a similar question here: http://forum.dlang.org/post/xdhuberedpjuxydbwdip forum.dlang.org
Sep 21 2015
On Monday, 21 September 2015 at 20:33:10 UTC, Jack Stouffer wrote:That's ridiculous. Do I have to wrap my static arrays in structs to get range primitives? Is there an actual reason for this?I had done basically the same thing. Below is my naive implementation. import std.traits; import std.range; import std.array : array; import std.stdio : writeln; import std.algorithm : map; struct hybrid_array(T : U[N], U, size_t N) if ( isStaticArray!T ) { T static_array; private auto _length = static_array.length; auto domain = iota(0, static_array.length); this(T x) { static_array = x; } property bool empty() { return domain.empty; } property size_t length() { return _length; } property U front() { assert(!empty); return static_array[domain.front]; } void popFront() { assert(!empty); domain.popFront; _length--; } property hybrid_array save() { return this; } property U back() { assert(!empty); return static_array[domain.back]; } void popBack() { assert(!empty); domain.popBack; _length++; } U opIndex(size_t val) { assert(!empty); return static_array[domain[val]]; } } void main() { int[5] x = [0, 10, 2, 6, 1]; //auto squares = map!(a => a * a)(x); //doesn't work auto range = iota(0, x.length).array; alias h_array = hybrid_array!(int[5]); auto y = h_array(x); writeln( isRandomAccessRange!(typeof(y)) ); auto squares = map!(a => a * a)(y); //success, does work writeln(squares); }
Sep 21 2015