Boost logo

Boost :

From: FlSt_at_[hidden]
Date: 2005-07-27 10:58:21


Rob Stewart wrote:

>[...]
>
>Don't include the editor swap files in your zip file, please.
>
Sorry, I forgot to quit my editor before zipping the files.

>>discussion. But it's very inefficient, because it makes a lot of copies.
>>
>>
>I don't plan to look at the implementation until we reach some
>conclusion as to desirable interface and behavior.
>
That's ok, but I like to implement the ideas while discussing, because
it helps me to find new approaches.

>For example, your junction base class template provides size(),
>is_empty(), values(), operator container_type(), be(), and
>operator bool(). I'm not sure all of those are appropriate.
>Indeed, your design requires the junction to contain the values
>over which it operates. Why not have it reference the values
>over which it operates?
>
Using references instead of value copies is one of the points I wanted
to think about. This would make the is_empty(), size() and values()
functions unnecessary. The operator bool() is necessary for the duality
of the junctions, because a false result of a comparison isn't mandatory
an empty junction. And the be()-function exists just for completeness,
but i think we can live without it. But when using container-references,
how can I return junctions with a new container? Either there must be
two types of junctions (one holding references and one holding a
container) or a mechnism like this:

[...]
ContainerA a, b, result;
disjunction< ContainerA > resultJunction( result ); // explicit
specification of the result-container

resultJunction = ( all_of( a ) <= all_of( b ) );
[...]

But this has some disadvantages: It needs more typing and if the result
container is the same as one of the operand's container, then a
temporary copy is needed. And the do_comparison() and do_arithmetic_op()
functions need two parameters for the operands.
Result and operands-Container must be different or we need temporaries.
Temporaries needed by the operators anyway.

[...]

>(Actually, I can envision the possibility of
>constructing a junction in such a way that it creates, populates,
>and owns a container if you don't have one already. Then, you
>can adapt an existing container or create one on demand.)
>
This is what i meant with "two types of junctions". How do I determine
the type of the result container? One operand has a std::set and the
other one has a std::vecor, which type should the resulting container
stored in the junction have? Should they depend on the operands?

>That approach obviates the limited container interface you have
>created via size(), is_empty(), etc.
>
I should read the complete message before replying ;-) That's what I
said above.

>BTW, the bool conversion should, probably, use the safe bool
>idiom.
>
It's on my ToDo list. I had already a problem with operator bool() and
unary operators. That's why the unary operators now class members,
because my compiler (an outdated gcc 2.95) converted the junction first
to bool and then applied the unary operator. Why?
I read about the safe bool idiom in Matthew Wilson / Imperfect C++ /
Chapter 24. I don't know whether the extra complexity justifies the
advantage.

[...]

>>I see junctions as a expressive way to write comparisons and aritmethic
>>operations on lists and as a alternative to loops.
>>
>Let's discuss the use cases. That discussion will form the basis
>for later documentation, and will focus the design.
>
Porbaly the discussions of the Perl community are a good source to get
an idea. I think they don't added this feature to Perl without a reason.
In the Quantum::Superpositions module manual page are examples to get
the min/max of a list in one line of code, which is based on the
resulting junction of a comparison: (And I must admit that in this
module the values are called eigenstates and not eigenvalues, to answer
your question in one of your last messages. I called them eigenvalues,
because I renamed the use of the term state to value without considering
the meaning of this in the linear algebra ;-)

Minimum of a : any_of( a ) <= all_of( a )
Maximum of a : any_of( a ) >= all_of( a )

But I think the most use cases are something like this, instead of
writing loops:

if( any_of( a ) < 42 ) { /* one element of list is smaller then 42 */ }
or
b = any_of( a ) * 2; /* multiply all elements with 2 */

The aritmethic operations not the focus of junctions, because they don't
depend on the junction type, but they are very usefull. The
junction-type is unecessary, if I want to perform arithmetic operations
only. Although I had to write any_of( a ) or all_of( a ) ....

>>[...]
>>
>
>You make a good point. Junctions are useful to adapt other
>containers that match some concepts. That makes them more
>general than they otherwise would be. We need to decide what
>those concepts are, though.
>
The current implementation only needs a constructor for initializing
with input iterators and forward-iterator support.

>>are now four classes: conjunction<T>, disjunction<T>, abjunction<T> and
>>injunction<T>. Whereas T is a Container-Type. And the Functions all_of,
>>any_of, one_of, none_of create instances of this classes from a
>>
>
>Ah, you liked my ideas, eh?
>
They were ok. ;-)

>>My idea is that the junctions are given a range over which to
>>operate and evaluate to a Boolean when compared with a given
>>value.
>>
I also had this idea.

>>[...]
>>
>>What do you think of this approach? Boost.Range gives us a wide
>>range of types over which to operate, and putting the logic in
>>the equality operators rather than the junction types gives us
>>compile-time logic selection. The junction types merely serve as
>>selectors for the appropriate equality operator.
>>
I think boost.range and junction would fit good together, but you forgot
to adhire the duality of the result of a comparison. In the
minumum/maximum example showed above the values of the resulting
junctions were interesting.
There are three ways how to use the result in the current implementation:

disjunction< Container > a, b;

[...]

disjunction< Container > r = a <= b; // assign to another junction
Container r_c = a <= b; // use values of the resulting junction ( if
junctions are refs, then this isn't necessary )
bool r_b = a <= b; // use boolean result

Florian.


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