Subject: Re: [boost] Formal Review: Boost.RangeEx
From: David Abrahams (dave_at_[hidden])
Date: 2009-03-02 10:01:00
on Fri Feb 27 2009, Rogier van Dalen <rogiervd-AT-gmail.com> wrote:
> To me, RangeEx provides functions that take a range and return a range.
> How is it not most natural to make these functions look like
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.
Function call syntax (in general) expresses a tree structure.
f( g( a( b, c ), d( e, z, h) ), i(j, k) )
___|___ / \
/ \ j k
/ \ /|\
b c e z h
What we're doing with RangeEx (in general) only expresses a degenerate
tree structure (i.e. a linear structure):
r | transform(f) | filter(g) | whatever(h)
= whatever(filter(transform(r, f), g, h))
There's a _lot_ wrong with that way of expressing it, not least that
oerations (such as filter) are separated from their essential parameters
(g). Personally I think the top-down order in which the function call
syntax reads is also much harder to understand.
> 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.
Here's how I think of it:
unique_range => a type. No need to say "lazy_unique_range" because if
it weren't lazy, we wouldn't need a type.
unique(r) => a function returning unique_range
> could you state how you would
> integrate lazy merge() or anything that takes two or more ranges in
> operator| syntax?
There are lots of options, but
is not a bad one. The alternatives generally look like
r1 # r2
where # is some operator (or pseudo-operator such as %merge%). In the
end you will usually want to add parentheses as in
(r1 | r2) # (r3 | r4)
and then if you want to continue chaining,
((r1 | r2) # (r3 | r4)) | r5
which I don't think is an improvement over
merge(r1 | r2, r3 | r4) | r5
> I believe that the '|' syntax, however cute (I agree there!) is less
> flexible and less obvious than the function syntax.
Agreed w.r.t. flexibility; disagreed w.r.t. obviousness. As is often
the case, a more limited and specific form of expression makes for
clearer syntax (e.g. BNF illustrates syntax better than a hand-coded
parser in a general-purpose programming languages)
> 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.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk