Boost logo

Boost :

Subject: Re: [boost] Assign V2 - first impression
From: er (er.ci.2020_at_[hidden])
Date: 2011-06-24 11:09:31


On 6/24/11 9:08 AM, Stewart, Robert wrote:
> er wrote:
>>
>>> I am sure that it is a powerful library, but I really have no
>>> idea at all what is going on. I can't even parse the first
>>> line as valid C++ in any way. You need better examples, and
>>> also is that really the best way you could find to express
>>> repeating?
>>
>> If I try to imagine what the interface would look like after
>> taking into account some of the suggestions that were made, this
>> sentence:
>>
>> "Create data elements by mapping 1, 10, 100, 1000 by function
>> f, and insert each result in cont by invoking modifier
>> push_front."
>
> If I interpret that correctly, it would be clearer as:
>
> "Create elements in cont, using push_front(), by calling f() 1, 10, 100, and 1000 times."
>

Noted, thanks.

>> translates to
>>
>> (
>> push_front<1>( cont ) % ( _data = f ) % ( _repeat = n )
>> )( 1, 10, 100, 1000 );
>
> Why the leading underscores on "_data" and "_repeat?"

It's part of a set of conventions that are pervasive throughout the
library: trailing underscore for types, leading one for const objects:

const name_ _name = {};

Names without underscores are reserved for functions.

>
>> Questions :
>> - is it more readable, now?
>> - What if each example was preceded by its English equivalent.
>
> Preceding each by a clear English equivalent is necessary.

Noted.

>
> Could that code be spelled like the following instead?
>
> push_front<1>(cont).from(f).repeated(1, 10, 100, 1000);
>
> That is, instead of operator overloading, member functions would make things clearer and more succinct. Is there more to the operator

overloading than I know making the member function approach too
restrictive? What happens to your operator overloading approach when a

To use a proverbial expression, the member function approach is "carved
in stone", if you like. Not using operator%. I'm going to assume that
'object' is returned by put( cont ) or deque<T>( _nil ). It doesn't
matter which, since they rely on the same implementation. Consider

( object % option1 % ... % optionn )(1, 10, 100, 1000);

object has two (orthogonal) components : the data-generator, which maps
arguments to a data-element, and the modifier which takes care of
inserting that data-element. Each option modifies either of these two
components. For example

( object % ( _data = f ) )( 1, 10, 100, 1000 );

changes the data-generator to f. For example,

( object % ( _repeat = n ) )( 1, 10, 100, 1000 );

wraps a new modifier around the one that already resides in object (say
push_back), such as to invoke it n times.

While this is perhaps not as intuitive as desired, it's in my view an
irreducible price to pay to have modularity and open for extension : one
can customize an option.

I anticipated that this would be a problem and already provided some
remedy (I won't delve on it), but did not push the reasoning far enough.
The next step, I think, is to try to get back to functions, as you
suggest, but free functions, not member functions. I already proposed a
new syntax. Let me repeat it:

push_front<1>( cont )( 1, 10, 100, 1000 );

would be equivalent to the less eye candy

( put<1>( cont ) % _push_front )( 1, 10, 100, 1000 );

Consequently, using the first form, the use of operator% would appear,
only for additional options:

( push_front<1>( cont ) % ( _data = f ) % ( _repeat = n ) )( 1, 10,
100, 1000 );

One way to see that being able to encapsulate an option as an object is
a good thing, however, is to imagine to have to write two unit tests:

void unit_test1()
{
     std::deque<T> v;
     v.push_back( T( args1... ) ); ...; v.push_back( T( argsn...) )
     // whatever
}

void unit_test2()
{
     std::deque<int> v;
     v.push_front( T( args1... ) ); ...; v.push_front( T( argsn...) )
     // whatever
}

With V2, you can do the same like this:

template<typename Option>
void unit_test(Option option)
{
     std::deque<int> vec;
     ( put( vec ) % option )( args1... )...( argsn... );
     // whatever
}

unit_test( _push_back );
unit_test( _push_front );

Some people might find this contrived. Fair enough, but it's meant to
make a point about modularity, which should have some benefit in less
contrived situations.

HTH, and thanks for your interest.


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