
on Mon Mar 02 2009, Rogier van Dalen <rogiervd-AT-gmail.com> wrote:
Dear Dave,
Do I correctly understand your opinion can be summarised as "for linear structures operator| is clearest; for complicated trees, function syntax; and combinations, a combination"?
That's how it looks to me so far, yeah.
On Mon, 2009-03-02 at 10:01 -0500, David Abrahams wrote:
Every bit of runtime functionality is most naturally-expressed as a function call, according to some people. Those people end up writing code with lots and lots of parentheses, and they cite this uniformity as a source of expressiveness. Personally, I don't get it. If there's a more evocative syntax, we should consider using it.
You give a convincing argument. But is this different from ranges than for any expression?
Of course not.
Taking the n-th power of a complicated expression is pow((... complicated expression ...), n) but might be more clearly expressed as (... complicated expression ...) #pow# n
Yeah, but Xⁿ is already a well-established accepted syntax in standard math notation.
Shouldn't this go into a more general library? Shouldn't RangeEx by default offer the well-known syntax of function calls?
The only standard syntax I know for stringing together sequence modifications like that is "|"
(Even though I agree that also providing operator| is sensible, and not very hard at all.)
It should be the only syntax.
What we're doing with RangeEx (in general) only expresses a degenerate tree structure (i.e. a linear structure):
Is that true? I've used RangeEx-like facilities (that I wrote) mostly for more complicated trees, such as set operations.
"in general," meaning "most of the time."
What is wrong with saying "uniqued(rng)"? Why is it vital that the name has "make_ _range" to remind me that this returns a lazy range rather than a range?
I don't think "make_ _range" does anything to indicate laziness.
Sorry, I was trying (and clearly failed) to ask a Socratic question (echoing Neil's "I like the make_XXX_range because I instantly recognise that this creates a range adaptor"). We agree here.
I don't want to see that level of detail. What I want to get /instantly/ when I read the code is the high-level abstraction, e.g. "this transforms the range using that function." What kind of object is getting created is a secondary concern, and we shouldn't force into the foreground. Taken to an extreme, that approach leads to "Hungarian notation" naming.
Currently merge(), transform(), and the set algorithms use output iterators as a substitute for return values. Rephrasing them as functions would also get rid of output iterators, which would improve their interface.
While value semantics are wonderful, I have doubts that everything that operates on output iterators can be effectively reformulated to return a range without limiting expressiveness and efficiency.
Re efficiency, it would make sense to have copy (lazy_operation (rng), output_it) forward to the standard library operation.
Naturally.
Re expressiveness, I am not sure what you mean. The output iterator versions of the operations I mention can be mimicked with "copy".
Good, then I withdraw my objection.
I do know that I find that "merge()" returning ranges copy (merge (rng1, rng2) | transform (f), output_it); gives expressiveness than ^^^^^^^^^^^^^^^^^^^ Parse error. I don't understand what you're trying to say.
the implementation of the same using the standard library, which requires storing the intermediate values. To be fair, I have never compared performance, but I don't think the lazy range version is obviously slower.
But maybe by "everything" you mean all possible operations, not just those currently in the standard library.
That's what I meant.
In that case I'm sure you're right, but I don't see how that would make it undesirable to eliminate output iterators where possible, especially in a library that's bound to be used a lot.
OK -- Dave Abrahams BoostPro Computing http://www.boostpro.com