Boost logo

Boost :

From: Dean Michael Berris (mikhailberis_at_[hidden])
Date: 2008-07-01 06:50:04


On Tue, Jul 1, 2008 at 6:22 PM, Giovanni Piero Deretta
<gpderetta_at_[hidden]> wrote:
> On Tue, Jul 1, 2008 at 7:12 AM, Dean Michael Berris
> <mikhailberis_at_[hidden]> wrote:
>>
>> I think the point of using expression templates is to be able to do
>> something like:
>>
>> copy( range(source) | taken(10) | map(mapper()),
>> make_function_output_iterator(reducer()) // should have a better name?
>> );
>>
>
> You do not need anything more than what is in Lambda/Phoenix here.
> Instead of having a different function for piping an generating views,
> you use the same function and curry it:
>
> auto reduced = source | take(_, 10) | map(_, mapper()) | fold(_, reducer()) ;
>
> the _ is like _1 in bind/lambda/phoenix, but it doesn't make the whole
> expression a lambda expression (it stops at one level). The pipe in
> practice works like a compose operator. If you put the range at the
> end, you wouldn't even need the '_' (just provide one less argument,
> hey it is haskell :) ), but you give up variadic (or overloaded)
> functions.
>

Isn't the whole point of creating an expression template
based-approach to create these (maybe using proto I guess) and allow:

1. The same placeholders used in Phoenix+Proto to be used in the pipe
syntax in range_ex (or an imaginary new RangeEx implementation).
2. Allow for efficient (i.e., compiler optimized/assisted)
implementations of the composition of these new
views/ranges/iterators.

?

Although I do like how this looks granted that you are using C++0x's
auto -- in today's C++, the reason I used the STL was to avoid having
to compute the actual type produced by the pipe syntax. Maybe this is
why Dave is asking for a better BOOST_TYPEOF. ;-)

>>
>>> I think that the basic ranges that should (at least) be supported are:
>>>
>>> - mapped_range
>>> - filtered_range
>>> - taken_range (i.e. just the first n elements of a range)
>>> - taken_while_range (i.e. the first elements such as a predicate is true)
>>> - zipped_range
>>> - unfold_range (with which you can pretty much express any other
>>> range, see http://tinyurl.com/5mus25)
>>>
>>> An eventual 'drop' (take all the elements after the first n) and
>>> 'drop_while' (drop the first elements such as a predicate is true)
>>> probably need strict evaluation anyway and aren't worth supporting
>>> explicitly.
>>>
>>
>> I also think there should be a zipped_function which:
>>
>> - takes N function objects and an N-tuple
>> - applies each function to the appropriate tuple
>> - returns a tuple of results
>
> D'oh, of course, forgot this.
> I think that zipped_range on top of zipped_iterator is enough, you
> get the other functionality by composing with transformed_iterator.
>

Okay, but shouldn't this composition with transform_iterator be done
with something that 'comes out of the box'?

> <snip>
>>> [2] I think that this is quite similar to the deforestation technique
>>> used by functional languages compilers. (see the wikipedia page and
>>> the linked articles). In FP it is used mostly to eliminate
>>> intermediate (lazily evaluated) lists, but the same technique can be
>>> applied in c++. In fact the rewrite rules used map perfectly to c++
>>> templates.
>>>
>>
>> Here I think you need the zipped_function idiom where you can create
>> an 'in-step' function that can deal with tuples of inputs.
>>
>> zipped_function(zipped_input) -> zipped_output
>>
>> Another thing that's missing is a way to transform tuples of one form
>> into another -- possibly ignoring tuple elements. I've posted a
>> possible implementation based on Fusion's at_c, which allows:
>>
>> map<int, string> source;
>> // populate source..
>> for_each(source.begin(), source.end(),
>> select<1> | (cout << arg1 << endl) //using fusion
>> );
>> // select will choose the second element of the pair
>>
>
> Ok, but this is beyond boost range. I think that fusion svn already
> provides function objects for every algorithm/accessors, so this would
> becomes
>
> for_each(source | map(_, select<1>() ) , coust << arg1 << endl )
>
> BTW I call select<1>() simply first (and of course also have second,
> third, etc...).
>

Ok.

I'd love to see Phoenix 2.0 come out and 'just work' with
Boost.Range/RangeEx/Iterator/Algorithms -- I think now I "get" what
Dave is looking for. :D

-- 
Dean Michael C. Berris
Software Engineer, Friendster, Inc.

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk