Array types not treated uniformly when passed as ranges

jam gr0v3er+d at gmail.com
Tue Feb 15 11:01:31 PST 2011


On Tue, 15 Feb 2011 09:00:54 -0500, Steven Schveighoffer wrote:

> 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.
> 
> 
> -Steve

I'm glad I came to the same conclusions on my own after perusing the docs 
and src files some more. 

I still find it a bit odd that I'm not testing whether my data structure 
is sorted or not, but a full-length slice of the structure.  Although, I 
guess when I really think about it, it's not that mechanically different 
than passing a pair of iterators.

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

Indeed, and operations like fill and isSorted also do not make sense on 
such containers.  However, popFront makes a world of sense for a range 
representing a traversal.

Thanks to both Jonathon and yourself for your help


More information about the Digitalmars-d-learn mailing list