On Tue, 15 Feb 2011 09:00:54 -0500, Steven Schveighoffer wrote: > On Mon, 14 Feb 2011 21:18:39 -0500, jam <[email protected]> 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
