On 05/01/2012 12:54 AM, Kapps wrote:
On Monday, 30 April 2012 at 19:50:36 UTC, Walter Bright wrote:

I'm surprised nobody has mentioned opApply. That was a good idea at
the time, but Ranges are a superior solution. I'd like to see new code
not use opApply. It's a dead end, though it'll still be supported for
a long time.

I practically never use ranges, and instead use opApply for all my code.

1) Ranges force me to use a specific naming convention. My naming
convention that I use for my projects is upper camel case. Ranges do not
allow this.

Yes they do. (If you are willing to have both kinds of symbols around.)

mixin template AddAliasesForBuiltInRange(){
    alias Front front;
    alias Empty empty;
    alias PopFront popFront;
}

struct R{
    ...
    @property Front(){...}
    @property bool Empty(){...}
    void PopFront(){...}

    mixin AddAliasesForBuiltInRange;
}


Technically opApply is still lower camel case, but my code
doesn't directly call it.


The same would hold for the above example.

2) Ranges don't have a way of determining when the iteration ends.
Sometimes you want to do something once iteration stops. For example, by
far the most common action when executing a database call for me, is to
iterate over it and close it. I can then have a helper method that
executes the command and closes it when the foreach is done (whether by
break or by the function ending). This saves quite a bit of boiler plate
code.


An important point.

3) Ranges can be difficult to implement. You now have to keep track of
state instead of simply leaving everything inside a single method call.
This can also cause significant problems with multi-threaded code.

4) Ranges take a lot more code, which when all you want is basic
iteration, is pointless to have


Those two could be mitigated by moving the range concept further into the language.

I'd much rather just see things with opApply being able to have a
forward-range magically created for it, much like the reverse. Not sure
if this is possible or practical though.


Am implementation (that is possible now) could use coroutines (core.thread.Fiber), but that is not very efficient for simple iteration. Compiler support would be a solution. See eg. C# yield return. (In D the compiler would generate anonymous struct types instead of IEnumerable interface implementations).




Reply via email to