Array types not treated uniformly when passed as ranges

Steven Schveighoffer schveiguy at yahoo.com
Tue Feb 15 06:00:54 PST 2011


On Mon, 14 Feb 2011 21:18:39 -0500, jam <gr0v3er at gmail.com> wrote:

> Hi all,
>
> Just curious as to the difference in the built-in variable length
> array vs. the std.container.Array and fixed length arrays when it
> comes to using them in functions that take Ranges.
>
> For instance the following does not compile:
>
> import std.algorithm;
> import std.stdio;
> import std.range;
> import std.conv;
> import std.container;
> import std.array;
>
> void main() {
>
>     int[5] builtin_fixed;
>     int[] builtin_variable;
>     Array!(int) con_array;
>
>     con_array.length(5);
>     builtin_variable.length = 5;
>
>     fill(builtin_variable, 9); //ok, no error
>     isSorted(builtin_variable); //ditto
>
>     //The following 4 statements produce errors
>     fill(builtin_fixed, 9);
>     fill(con_array, 9);
>
>     isSorted(con_array);
>     isSorted(builtin_fixed);
>
> }
>
> The errors are variations on:
>
> Error: template std.algorithm.fill(Range,Value) if
> (isForwardRange!(Range) && is(typeof(range.front = filler))) does not
> match any function template declaration
> Error: template std.algorithm.fill(Range,Value) if
> (isForwardRange!(Range) && is(typeof(range.front = filler))) cannot
> deduce template function from argument types !()(int[5LU],int)
>
> If I change those 4 statements to:
>
>     fill(builtin_fixed[], 9);
>     fill(con_array[], 9);
>
>     isSorted(con_array[]);
>     isSorted(builtin_fixed[]);
>
> effectively passing ranges (std.container.Array!(int).Array.Range in
> the case of con_array, and int[] for builtin_fixed) which then works
> as expected.  This all makes sense, and it's easy enough to write
> wrappers,   but I would (well and I did) expect the first way to just
> work.   This may just be a nitpick I guess, but being new to the
> language this little detour involved quite a bit of time research (not
> a bad thing, I did learn quite a bit in the process), but makes me
> wonder if I am missing something fundamental regarding when I should
> be using these different array types.

This is because:

1. a fixed-sized array is not a range.  It is passed by value, not by  
reference.  The problem there is IFTI thinking you want to pass the fixed  
array as a fixed array and not as a slice.
2. a container is not a range.  An Array is a container, so you must  
extract a range from it to use it in range-like activities.

The second point seems odd, since builtin arrays are ranges, but an Array  
is different because it's a true reference type (changing the length from  
one reference alters the length of another reference) and it "owns" the  
memory contained within, unlike a builtin array which just references the  
memory.

But it's also easy to consider other things.  Consider a RedBlackTree  
container, should that be a range?  What happens when you popFront?

-Steve


More information about the Digitalmars-d-learn mailing list