== Quote from Michel Fortin (michel.for...@michelf.com)'s article > Indeed. I certainly agree that both ranges and opApply have their place. > So what the implementer can do with opApply is write an optimized > iteration algorithm for use with foreach. Which may mean that when both > opApply and ranges are available for generating foreach's code, the > compiler should favor opApply. Currently, I believe it's the reverse.
You probably have a point. If the range interface is "good enough" for the implementer of the object to write an optimal implementation without defining opApply, then the implementer will probably not define opApply. On the other hand, it could make sense to define a range interface for when the user of the object needs that flexibility and an opApply interface that is more efficient internally in the same object. What I think it really boils down to, and what should be emphasized in the documentation, is control of the stack. If the implementer of the object needs control of the stack during iteration, use opApply to get this control. Otherwise, use ranges to allow the user more control over the iteration process. However, what I care more about, upon thinking more about it, is that the concept of an iterable gets defined "officially" in Phobos and in the documentation. An iterable is any object of type T such that the following code works: foreach(elem; T.init) { // do stuff. } This can be considered a superset of input ranges, since all input ranges are iterables but not all iterables are input ranges. Of course, stuff that works like: foreach(key, value; T.init) { // do stuff. } uses opApply but would not be considered an iterable because it iterates more than one item. Therefore, strictly speaking, the model is broken, but these kinds of oddball situations are few enough and far enough between that I think they can be ignored, at least until the issue of making ranges do this kind of thing too is addressed. The idea, then, is that if all you need is an iterable for some generic function in Phobos or in any 3rd party library, make the constraint be that it only requires an iterable. To encourage this, an isIterable template should be included in Phobos, and std.range.ElementType should be generalized to return the element type for all iterables, not just ranges.