Michel Fortin wrote:
On 2009-01-18 22:00:17 -0500, Andrei Alexandrescu <seewebsiteforem...@erdani.org> said:

dsimcha wrote:
== Quote from Walter Bright (newshou...@digitalmars.com)'s article
dsimcha wrote:
One point of clarification: opApply isn't going to be deprecated anytime soon, is it? It seems like ranges still have a bunch of rough edges, and although I like the idea in principle, I'm only willing to convert to ranges if I can define iterable objects with the same level of syntactic sugar as opApply gives me. For simple cases this is already true and I have begun converting some stuff. However, for more complicated cases, opApply is still a lot more flexible.
opApply isn't going away. For one thing, it works very well with
recursive data structures.

So besides performance, what advantages does using ranges instead of opApply for iteration over structs/classes offer? According to some testing that I just finished on the hash table implementation I was talking about earlier today, the penalty for using opApply is small enough that, if using ranges requires a bunch of extra bookkeeping overhead that opApply doesn't, then opApply can reasonably be
faster.

Speed is a small part of the equation, in fact a perk only. Ranges are composable; you can combine them to e.g. do parallel iteration over two ranges. Ranges really open std.algorithm to all data structures. I find opApply incredibly obtuse and fostering bad design. I wish it goes away.

Andrei

But if it goes away, that'd prevent a lot of cool things that could be done with foreach. You could create a template that automatically distributes iterations to various threads with very little code (assuming the loop delegate is pure):

    foreach (i; paralelize(myArray))
        doSomethingComplicated();

All the complexity would lay in the opApply. You can't do this with ranges.

Parallelization crossed my mind too, although in the context of finding files in subdirectories recursively. Using foreach for such stuff looks cute, maybe too cute. Let's not forget that there is always the option of calling a higher-order function:

distribute(myArray, &doSomethingComplicated);

Other possible things involves a rudimentary profiler (checking for the elapsed time at each loop iteration), or a progress monitoring template (notifying another thread of the progress of a particular task).

    foreach (task; progessUpdater(timeProfiler(listOfTasks)))
    { ... }

You can't compose iteration based on opApply. How would progessUpdater and timeProfiler look like? This example pretty much transforms your argument into mine :o).

For basic data manipulation algorithms, ranges are better. But for more fancy stuff, opApply still rules.

Depends on how you define "fancy". If "fancy" includes "composable", opApply isn't that.


Andrei

Reply via email to