Boost logo

Boost :

Subject: Re: [boost] Formal Review: Boost.RangeEx
From: Giovanni Piero Deretta (gpderetta_at_[hidden])
Date: 2009-02-25 17:01:14

On Wed, Feb 25, 2009 at 10:11 PM, Thorsten Ottosen
<thorsten.ottosen_at_[hidden]> wrote:
> Vicente Botet skrev:
>>> Dear Giovanni,
>>> On Wed, Feb 25, 2009 at 5:13 PM, Giovanni Piero Deretta
>>> <gpderetta_at_[hidden]
>>>> wrote:
>>> Yes, I think I might have over-emphasised the difference. Would you
>>> prefer
>>> the function overload to be in the boost::adaptors namespace, the boost
>>> namespace or something else?
>>>>> I had considered
>>>>> creating a range adaptor to be highly different to applying an
>>>>> algorithm,
>>>>> perhaps I over-emphasised this distinction when making the decision.
>>>> FWIW, I have code like this:
>>>> total = ( r | filter(_r, f) | map(_r, m) | accumulate(_r, zero, a)  );
>>>> i.e. I don't have a strong distinction between adaptor and algorithms.
>>> Yes, I'm sold!
>>  I agree, the introduction of the parameter (_r) makes the library
>> homogeneus. An adaptor is a functor with a placeholder for the input
>> parameter.
> I my examples I removed the _r from the syntax. I don't see the point in
> having them, if the code can work without them. Are they really needed?

No, not necessarily:

    1: transformed_range<...> r = transformed(range, f);
    2: transformed_range<...> r = range | transformed(f);

you could have the single argument variant of transformed (and in
general the variant with arity N-1 of an adaptor) return 'something'
that can function in a pipe. I would expect that 'something' to be a
full fledged unary function object (the equivalent of
bind(transformed, _1, f)) that can also work outside of pipes or even

    boost::function<transformed_range<range_t, f_t>(range_t)> mapper =
    // or alternatively
    boost::result_of<mapper_t(f_t)>::type mapper = transformed(f);
    BOOST_FOREACH( v_t v, range | mapper) { ... }

Which implies that transformed (and other adaptors) should store 'f'
(and other parameters) by value (modulo boost::ref and friends).

( BTW If you decide to adopt this solution, I suggest putting the
range parameter last. This way It would sort of simulate the automatic
currying syntax of some functional languages (where omitting the last
m parameters of n-arity function makes it a higher order function that
returns an (n-m) arity function. )

This approach has unfortunately a big problem. If you have adaptors
with optional arguments, without concepts it is an iteresting problem
figuring out which overload the user wants:

   merged(r1, r2); // uses operator< as comparator
   merged(r1, r2, cmp); // uses cmp as comparator
   r1 | merged(r2, cmp); // interesting problem here!
   r1 | merged(_r, r2, cmp); // much better
   r2 | merged(r1, _r, cmp); // we have a choice of the argument to bind
   r1 ^merged(_r1, _r2, cmp)^ r2; // probably beyond the scope of the library ;)

In my code, I use '_' as a placeholder, instead of '_r'.


Boost list run by bdawes at, gregod at, cpdaniel at, john at