[fusion] constructing all elements of the fusion vector with the same argument

Hello, I recently ran into a need to initialize a fusion vector with a single argument which is then used to construct all of the vector elements. For example, something that would allow: fusion::vector<int, float, double> ones(initialize_all_with(),1); // at_c<0>(ones) == 1 // at_c<1>(ones) == 1.0f // at_c<2>(ones) == 1.0; I hacked fusion::vector so that the above works. Is this addition of interest to anyone else? There is another (perhaps more elegant) solution in implementing a new fusion "array" Sequence (one where all element types are identical) which can construct all elements from a single constructor argument, and then using that sequence to do the above initialization. E.g., fusion::vector<int, float, double> ones(fusion::array<int, 3>(1)); ... or (another solution) a make_array function that returns a fusion::vector: fusion::vector<int, float, double> ones(fusion::make_array<3>(1)); It would be great if one of these solutions (or a different solution) were added to fusion. I can take a stab at putting something together, if any of them are acceptable. That is, unless this is already possible in some way that I can't see at the moment :-) Regards, Stjepan

Stjepan Rajko wrote:
Hello,
I recently ran into a need to initialize a fusion vector with a single argument which is then used to construct all of the vector elements. For example, something that would allow:
fusion::vector<int, float, double> ones(initialize_all_with(),1);
// at_c<0>(ones) == 1 // at_c<1>(ones) == 1.0f // at_c<2>(ones) == 1.0;
I hacked fusion::vector so that the above works. Is this addition of interest to anyone else?
Definitely. I'm not sure about the interface though. It seems there could be a more generic "lazy-construction" scheme that can have a more general appeal. After thinking about it, we don't even have to do anything -- fusion already supports it, but we haven't taken advantage of it yet. As you know, *all* fusion containers can be initialized from arbitrary fusion sequences. For example: vector<int, double> v(std::pair<char, short>(1, 2)); schematically: C c(s); where C is a fusion container, s in a fusion sequence. Now... If we have a /lazy-sequence/ s, that generates the ones for you, then you can use that for s: vector<int, float, double> ones(all_ones); all_ones is a lazy-sequence. It generates the ones every time the iterator is dereferenced. A nice strategy is to write a function adaptor that creates a fusion sequence. Example: int one() {return 1} ... vector<int, float, double> ones(fusion::make_lazy_sequence(&one)); make_lazy_sequence can take in a function pointer or a function object -anything callable. It simply calls /one/ each time its iterator is dereferenced.
There is another (perhaps more elegant) solution in implementing a new fusion "array" Sequence (one where all element types are identical) which can construct all elements from a single constructor argument, and then using that sequence to do the above initialization. E.g.,
fusion::vector<int, float, double> ones(fusion::array<int, 3>(1));
... or (another solution) a make_array function that returns a fusion::vector:
fusion::vector<int, float, double> ones(fusion::make_array<3>(1));
It would be great if one of these solutions (or a different solution) were added to fusion. I can take a stab at putting something together, if any of them are acceptable. That is, unless this is already possible in some way that I can't see at the moment :-)
How about hacking on the /lazy_sequence/ idea? Thoughts? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Tue, Jul 15, 2008 at 3:49 AM, Joel de Guzman <joel@boost-consulting.com> wrote:
If we have a /lazy-sequence/ s, that generates the ones for you, then you can use that for s:
vector<int, float, double> ones(all_ones);
all_ones is a lazy-sequence. It generates the ones every time the iterator is dereferenced.
A nice strategy is to write a function adaptor that creates a fusion sequence. Example:
int one() {return 1}
...
vector<int, float, double> ones(fusion::make_lazy_sequence(&one));
[snip]
How about hacking on the /lazy_sequence/ idea? Thoughts?
I *love it*. Attached is something... similar ;-) (I used the triple.cpp example as a starting point, it was pretty straightforward) What do you think? Stjepan

Stjepan Rajko wrote:
How about hacking on the /lazy_sequence/ idea? Thoughts?
I *love it*. Attached is something... similar ;-) (I used the triple.cpp example as a starting point, it was pretty straightforward)
What do you think?
I Love it! I think this should be an official part of Fusion. There are some matters though that we should consider very well: 1) The concept of an infinite-sequence. I'm not quite happy that all sequences has a finite size. Perhaps we can return something like fusion::infinite_size for size for such kind of sequences. We'll have to tweak the library though to cater to these kinds of sequences. IFAIR, these size checks are only done with algos dealing with 2 sequences and one sequence need to have equal or more elements than the other. Better check on this one. If this is possible, then we should have a new infinite-sequence concept. I wonder where and how that will fit in the fusion concepts hierarchy. 2) If this is not possible, then the interface should at least be compatible with the at_c and at interfaces: make_lazy_sequence<MPL-N>(f); make_lazy_sequence_c<N>(f); and of course, its result_of counterparts. Then, oh well... docs. Where should we put this? views, I guess. A lazy_sequence is a kind of a view, I would say. I'll need docs before something can be an official citizen. Hmmm.. I'll add a "contributions" section for acknowledgment of these and future contributions. At any rate, amazing! THANK YOU! Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

on Tue Jul 15 2008, Joel de Guzman <joel-AT-boost-consulting.com> wrote:
Stjepan Rajko wrote:
How about hacking on the /lazy_sequence/ idea? Thoughts?
I *love it*. Attached is something... similar ;-) (I used the triple.cpp example as a starting point, it was pretty straightforward)
What do you think?
I Love it! I think this should be an official part of Fusion. There are some matters though that we should consider very well:
1) The concept of an infinite-sequence.
I'm not quite happy that all sequences has a finite size.
Where does that restriction come from? You know you can always give infinite sequences an (unreachable) end iterator. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Tue Jul 15 2008, Joel de Guzman <joel-AT-boost-consulting.com> wrote:
Stjepan Rajko wrote:
How about hacking on the /lazy_sequence/ idea? Thoughts?
I *love it*. Attached is something... similar ;-) (I used the triple.cpp example as a starting point, it was pretty straightforward)
What do you think? I Love it! I think this should be an official part of Fusion. There are some matters though that we should consider very well:
1) The concept of an infinite-sequence.
I'm not quite happy that all sequences has a finite size.
Where does that restriction come from? You know you can always give infinite sequences an (unreachable) end iterator.
Here: http://tinyurl.com/4b9m8q The size(s), result_of::size<S> gives this restriction. The result should be "MPL Integral Constant. Convertible to int.". This is inherited from MPL: http://tinyurl.com/6cbx9c IMO, and we've been discussing this with Tobias and Dan offlist, both MPL and Fusion should have a more relaxed concept for infinite sequences without the "size" requirement. Or... At the very least, both MPL and Fusion forward sequences should relax the result type of size to allow a special "inf", "positive_inf" and "negative_inf" types, in addition to "Integral Constant". Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Tue, Jul 15, 2008 at 7:53 PM, Joel de Guzman <joel@boost-consulting.com> wrote:
1) The concept of an infinite-sequence.
I'm not quite happy that all sequences has a finite size. Perhaps we can return something like fusion::infinite_size
That would be really nice! I will make the Size template parameter a typename, so fusion::infinite_size can be specified if/when it becomes supported. I think the implementation will only need to change its behavior related to the end iterator. That way, we can have both finite and infinite lazy_sequences.
If this is possible, then we should have a new infinite-sequence concept. I wonder where and how that will fit in the fusion concepts hierarchy.
It seems orthogonal to other Sequence concepts... Maybe the Sequence concept should have the "size is an integral constant" requirement pulled out of it, and then have FiniteSequence and InfiniteSequence concepts that refine that?
2) If this is not possible, then the interface should at least be compatible with the at_c and at interfaces:
make_lazy_sequence<MPL-N>(f); make_lazy_sequence_c<N>(f);
and of course, its result_of counterparts.
OK
Then, oh well... docs. Where should we put this? views, I guess.
I had thought of it as a container, but I think you are right - should be a view. It is conceptually similar to single_view (in that it is not a view into a Sequence), perhaps described as "a view into the return values of a unary callabale object or function". That maybe suggests changing the name to something like "callable_view" (perhaps there is a better variant that doesn't suggest that the view is callable). Also - do you think we should support both unary and nullary callable entities (in the current naming convention, have both something like "lazy_sequence" and "uniform_lazy_sequence", or in the alternate naming convention, both "unary_callable_view" and "nullary_callable_view")? I started the docs at: http://www.dancinghacker.com/code/dataflow/dataflow/utility/lazy_sequence.ht... I will tease out the docs,tests,naming,directory location,etc. within the dataflow library sandbox until we have something that seems good. Best, Stjepan

Stjepan Rajko wrote:
On Tue, Jul 15, 2008 at 7:53 PM, Joel de Guzman <joel@boost-consulting.com> wrote:
1) The concept of an infinite-sequence.
I'm not quite happy that all sequences has a finite size. Perhaps we can return something like fusion::infinite_size
That would be really nice! I will make the Size template parameter a typename, so fusion::infinite_size can be specified if/when it becomes supported. I think the implementation will only need to change its behavior related to the end iterator. That way, we can have both finite and infinite lazy_sequences.
If this is possible, then we should have a new infinite-sequence concept. I wonder where and how that will fit in the fusion concepts hierarchy.
It seems orthogonal to other Sequence concepts... Maybe the Sequence concept should have the "size is an integral constant" requirement pulled out of it, and then have FiniteSequence and InfiniteSequence concepts that refine that?
Perhaps we need not add new concepts if we simply relax the size requirement. We simply state that a Forward Sequence may be finite or infinite, and add an /fusion::inf/ type representing infinity. The library has to be tweaked though for code (using size) that may break with this new size representation. This is a potentially breaking change, so the user must also be warned (docs).
2) If this is not possible, then the interface should at least be compatible with the at_c and at interfaces:
make_lazy_sequence<MPL-N>(f); make_lazy_sequence_c<N>(f);
and of course, its result_of counterparts.
OK
Then, oh well... docs. Where should we put this? views, I guess.
I had thought of it as a container, but I think you are right - should be a view. It is conceptually similar to single_view (in that it is not a view into a Sequence), perhaps described as "a view into the return values of a unary callabale object or function".
That's good. Can be better though, me thinks.
That maybe suggests changing the name to something like "callable_view" (perhaps there is a better variant that doesn't suggest that the view is callable).
Yeah, I agree. All views are inherently "lazy" anyway. So it's not a good name. More suggestions, anyone, please? functional_view? computed_view?
Also - do you think we should support both unary and nullary callable entities (in the current naming convention, have both something like "lazy_sequence" and "uniform_lazy_sequence", or in the alternate naming convention, both "unary_callable_view" and "nullary_callable_view")?
I think we need only one. You can use bind anyway, to ignore the unneeded arguments. What I am thinking of though, are stateful functions (ala fold). Perhaps it's a good idea to have an initial state that is then subsequently passed to the function at each iteration. Similar to (fold/accumulate): http://tinyurl.com/5hv7bb This can be quite powerful. It means though that the iterator cannot be random-access. Man! The fold algorithm can even be implemented in terms of this view. The only difference is that each "fold" is computed along the way. Maybe we should just call it "fold_view" ?
I started the docs at: http://www.dancinghacker.com/code/dataflow/dataflow/utility/lazy_sequence.ht...
That's a good start. What's still not clear though is the requirements for the function. The fold docs, I think, is a good model for this kind of thing.
I will tease out the docs,tests,naming,directory location,etc. within the dataflow library sandbox until we have something that seems good.
Cool! Thanks! Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

AMDG Joel de Guzman wrote:
Yeah, I agree. All views are inherently "lazy" anyway. So it's not a good name. More suggestions, anyone, please? functional_view? computed_view?
I just looked at lazy_sequence.hpp. Isn't it equivalent to transform(mpl::range_c<int, 0, N>(), f)?
Man! The fold algorithm can even be implemented in terms of this view. The only difference is that each "fold" is computed along the way. Maybe we should just call it "fold_view" ?
Awesome. In Christ, Steven Watanabe

Steven Watanabe wrote:
AMDG
Joel de Guzman wrote:
Yeah, I agree. All views are inherently "lazy" anyway. So it's not a good name. More suggestions, anyone, please? functional_view? computed_view?
I just looked at lazy_sequence.hpp. Isn't it equivalent to transform(mpl::range_c<int, 0, N>(), f)?
Hah! Yeah. You just spoiled the fun! ;-)
Man! The fold algorithm can even be implemented in terms of this view. The only difference is that each "fold" is computed along the way. Maybe we should just call it "fold_view" ?
So, can this too be implemented in terms of fusion/mpl alone? Either way, what we should probably do is add some of these examples with accompanying docs. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

AMDG Joel de Guzman wrote:
Man! The fold algorithm can even be implemented in terms of this view. The only difference is that each "fold" is computed along the way. Maybe we should just call it "fold_view" ?
So, can this too be implemented in terms of fusion/mpl alone?
I don't think so. The state would need to be stored in the iterator and the function object called by next(), right? None of the available fusion views supports this. In Christ, Steven Watanabe

On Wed, Jul 16, 2008 at 7:04 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
I just looked at lazy_sequence.hpp. Isn't it equivalent to transform(mpl::range_c<int, 0, N>(), f)?
LOL - well, this was a interestingly roundabout way of finding an existing solution to my original problem. Thanks Steven! Stjepan

Joel de Guzman wrote:
Stjepan Rajko wrote:
On Tue, Jul 15, 2008 at 7:53 PM, Joel de Guzman <joel@boost-consulting.com> wrote: ...
That maybe suggests changing the name to something like "callable_view" (perhaps there is a better variant that doesn't suggest that the view is callable).
Yeah, I agree. All views are inherently "lazy" anyway. So it's not a good name. More suggestions, anyone, please? functional_view? computed_view?
From mathematics/linear algebra: domain_view, field view Jeff
participants (5)
-
David Abrahams
-
Jeff Flinn
-
Joel de Guzman
-
Steven Watanabe
-
Stjepan Rajko