On Thursday, 17 May 2012 at 05:48:44 UTC, Nick Sabalausky wrote:
- A range is not a collection, it's a *view* of a collection (or of something else). This is a necessary distinction because ranges and collections work in fundamentally different ways: A range is, *by necessity*
consumed as it's iterated - that's what popFront *does*, that's
fundamentally how ranges work. For many collections, OTOH, it makes *no* sense to consume the collection while iterating it. Thus, range !=
collection, it's a view of a collection.

- Ranges are D's answer to iterators. I don't think people used to iterators from other languages would expect their iterator to magically reset itself after being used. So I see no reason why they would expect a range (ie, an
iterator-pair-with-benefits) to behave differently than that.

- D's arrays conflate the ideas of "collection" and "range", hence the odd edge case Era pointed out, and hence the "need" for foreach to automatically make a copy. But in my (not super-extensive) experience creating ranges, I've found that to be a problematic pattern (due to the fundamental distinction between a range and a collection), and learned to prefer making my iterable things *return* a range, rather than actually *be* ranges.

- Admittedly, it would be annoying if foreach had to be used like this on all collections: "foreach(e; myArray.rangeOf)", so I guess it would make sense for a range to automatically be obtained when foreach-ing over a collection. However, I'm still not 100% sold on the current method of doing that (making foreach automatically copy struct-based ranges), partly because of the questionable implications it has for input ranges, and partly because (for struct-ranges) it leaves no way to access the range that's actually
being iterated.

- At the very least, perhaps input ranges just shouldn't be allowed to be structs? After all, structs are intended to be copied around, but input
ranges, by definition, can't have their current state copied.

I would be very much in support of having ranges and containers be distinct, with a standard way to get a range from a container. Something very similar is done in C#, where containers have a getEnumerator() method. The enumerator itself has a Current property and moveNext method (similar to front and popFront of a range), and thus is consumed as you use it. In my experience, this system works very well.

Another advantage of giving arrays a method to obtain a range instead of them being a range themselves is that using foreach on a const/immutable array would work as expected without having to perform a slice to make it work. I would even go so far as to say that having an array BE a range really doesn't make any sense, conceptually.

Reply via email to