[Tuple] What's the point?
I know that sounds like a slightly flippant question, but I really don't get it. I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like t.get<1>( ) = "fred"; is a bit non-obvious, compared to t.forename = "fred"; So have I entirely missed the point of tuples? Thanks, Rob.
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
For one, a struct is not generic. For example, there is no generic way to do a for_each on each element of all structs. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
On Fri, Jul 10, 2009 at 09:13:39AM +0100, Robert Jones wrote:
So have I entirely missed the point of tuples?
The point is that tuple
On Fri, Jul 10, 2009 at 9:31 AM, Joel de Guzman
For one, a struct is not generic. For example, there is no generic way to do a for_each on each element of all structs.
On Fri, Jul 10, 2009 at 9:35 AM, Zeljko Vrba
The point is that tuple
is the same type as any other tuple .
Thank you gents - good points, which I had not considered. - Rob.
Robert Jones wrote:
Thank you gents - good points, which I had not considered.
Sure, but also, see http://tinyurl.com/l9p3g7 You do have the best of both worlds, so either way (tuple/struct) is ok. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare. - Volodya
Vladimir Prus wrote:
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
So, what's wrong with using named constants for the indices? That's what I've been most of the time when using tuples. / Johan
Johan Nilsson wrote:
Vladimir Prus wrote:
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
So, what's wrong with using named constants for the indices? That's what I've been most of the time when using tuples.
Named constants are fragile. If you add a member (say in the middle), it breaks. You have to make sure they are in sync. Better use associative tuples (e.g.): t.at_key<name>( ) = "fred"; But, IMO, that's not better than plain struct's: t.name = "fred"; I'd say: * use structs with non-generic code. * use tuples with generic code. * use FUSION_ADAPT_STRUCT to bridge between the two. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
On Fri, Jul 10, 2009 at 11:06 AM, Vladimir Prus
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
I think your point is valid, and often a structure will be preferable. However there are examples that are killer cases for tuple. My favourite is when combining functors. It is possible to use a tuple of functors that uses the generic for_each mechanism to provide superb maintainable composition, allowing lightweight orthogonally separated pieces of functionality that are when composed suffer zero performance overhead. I have to stop... because I'm getting excited! I can send some examples to the list or to you (Robert) if desired.
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
Often this is true, but it's a magnificent tools when it is appropriate.
- Volodya
Regards,
Neil Groves
On Friday 10 July 2009 11:23:16 Neil Groves wrote:
I think your point is valid, and often a structure will be preferable. However there are examples that are killer cases for tuple. My favourite is when combining functors. It is possible to use a tuple of functors that uses the generic for_each mechanism to provide superb maintainable composition, allowing lightweight orthogonally separated pieces of functionality that are when composed suffer zero performance overhead. I have to stop... because I'm getting excited! I can send some examples to the list or to you (Robert) if desired.
Yes please, I'm interested Neil. Giles Anderson
Vladimir Prus wrote:
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
Before Fusion, if you don't need the genericity, structs are just fine. With Fusion, even if you use structs and one day need the genericity, Fusion allows you to adapt any struct into a conforming fusion sequence(tuple), hence, still taking advantage of introspection, etc. So, IMO, either way is fine! Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Joel de Guzman wrote:
Vladimir Prus wrote:
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
Before Fusion, if you don't need the genericity, structs are just fine.
With Fusion, even if you use structs and one day need the genericity, Fusion allows you to adapt any struct into a conforming fusion sequence(tuple), hence, still taking advantage of introspection, etc.
This is very neat, I'll keep this in mind. - Volodya
Vladimir Prus wrote:
Robert Jones wrote:
I know that sounds like a slightly flippant question, but I really don't get it.
I've used tuples a few times, always for the multiple return value behaviour using tie( ), but in the end it always seems to be a better solution to use a struct. Code like
t.get<1>( ) = "fred";
is a bit non-obvious, compared to
t.forename = "fred";
So have I entirely missed the point of tuples?
FWIW, I've stopped using tuples because using indices as opposed to names turned out to a maintenance nightmare.
- Volodya
There are usages where you don't use any indices! My favorite is: struct A { int k; std::string n; double x; Other o; }; bool operator<(A const& lhs, A const& rhs) { return tie(lhs.k, lhs.n, lhs.x, lhs.o) < tie(rhs.k, rhs.n, rhs.x, rhs.o); } I'm sure Joel, could point out that this is done automatically with with the adapt struct macro. Jeff
This may cause some disagreements but I'm honestly not sure that I agree with the idea that tuples should behave like sequences. Most other languages that enable functional programming style explicitly disallow this, and for good reason. It leads to bad programming style, and makes it all too easy and comfortable to make an arbitrary sized tuple, when usually a tuple of larger than a few elements indicates a programming design problem. I also kind of agree with the philosophy that "sequence" should imply "collection of homogeneous types", which viewing a tuple as a sequence violates. In other functional languages if you need to manually operate on each element of a tuple other methods are provided like matching. I actually think that it might be possible to achieve some matching like constructs in C++, but I don't think (?) much if any research has been devoted to that.
Zachary Turner wrote:
This may cause some disagreements but I'm honestly not sure that I agree with the idea that tuples should behave like sequences. Most other languages that enable functional programming style explicitly disallow this, and for good reason.
Really? "explicitly"? Can you provide an example of a language that explicitly states this and the reasons why?
It leads to bad programming style,
Not in my world... Why?
and makes it all too easy and comfortable to make an arbitrary sized tuple, when usually a tuple of larger than a few elements indicates a programming design problem.
Why?
I also kind of agree with the philosophy that "sequence" should imply "collection of homogeneous types",
Why? which viewing a tuple as a sequence violates. In other
functional languages if you need to manually operate on each element of a tuple other methods are provided like matching. I actually think that it might be possible to achieve some matching like constructs in C++, but I don't think (?) much if any research has been devoted to that.
Erm... every sentence above begs the question: why? Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Zachary Turner wrote:
This may cause some disagreements but I'm honestly not sure that I agree with the idea that tuples should behave like sequences. Most other languages that enable functional programming style explicitly disallow this, and for good reason.
Really? "explicitly"? Can you provide an example of a language that explicitly states this and the reasons why? I didn't say they explicitly wrote in the standard "tuples cannot be
On Fri, Jul 10, 2009 at 11:26 AM, Joel de
Guzman
________________________________________ De: boost-users-bounces@lists.boost.org [boost-users-bounces@lists.boost.org] En nombre de Zachary Turner [divisortheory@gmail.com] Enviado el: viernes, 10 de julio de 2009 19:44 Para: boost-users@lists.boost.org Asunto: Re: [Boost-users] [Tuple] What's the point?
I consider it a C++ design problem that there are actually situations where iterating over elements of a tuple is the "quickest" way to accomplish something. When you're iterating over a collection and performing some operation on the items in the collection, the elements neecssarily having something in common otherwise the operation wouldn't make sense. But at the same time, the common aspect is determined by the function, not by any aspect of the types themselves. From a theoretical perspective I think it's better to approach this with typeclasses
C++0x concepts are very akin to type classes. Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
On Fri, Jul 10, 2009 at 12:52 PM, JOAQUIN M. LOPEZ MUÑOZ
________________________________________ De: boost-users-bounces@lists.boost.org [boost-users-bounces@lists.boost.org] En nombre de Zachary Turner [divisortheory@gmail.com] Enviado el: viernes, 10 de julio de 2009 19:44 Para: boost-users@lists.boost.org Asunto: Re: [Boost-users] [Tuple] What's the point?
I consider it a C++ design problem that there are actually situations where iterating over elements of a tuple is the "quickest" way to accomplish something. When you're iterating over a collection and performing some operation on the items in the collection, the elements neecssarily having something in common otherwise the operation wouldn't make sense. But at the same time, the common aspect is determined by the function, not by any aspect of the types themselves. From a theoretical perspective I think it's better to approach this with typeclasses
C++0x concepts are very akin to type classes.
That's true, and they help in some ways. But it doesn't address other aspects. I suppose my complaint with iterating over tuples is mostly of a theoretical nature and maybe nobody really cares. But even so, I think that tuples should be completely distinct from sequences, and that anyone using a tuple should be required to know exactly how many elements are in it, and the type of every element in order for it to be possible to use the tuple. In a sense, allowing generic iteration over the elements of a tuple allows one to treat different tuples (including tuples of different lengths) as the same type, or at the very least being able to use two tuples of different types without realizing they're different types. Once variadic templates are more widely supported, then I think there will be even less of a case for "tuple-sequences", because most (all?) of the things it makes simpler can be achieved more naturally with v-templates. If you have an arbitrarily sized collection of objects, then there should at least be some kind of well-defined structure connecting the types to each other. If you're going to iterate over these elements and then perform a completely different action on each item, then obviously you need to know what the individual items are to select the appropriate action. On the other hand, if you're not going to be performing a completely different action on them, but rather performing the same action on all of them, then perhaps the action you're trying to perform should accept the tuple as its argument and let it decide what to do with each item. Of course, it will in turn need to make the same decision, and either understand the structure or pass it to something that does.
On Fri, Jul 10, 2009 at 11:26 AM, Joel de Guzman
wrote: functional languages if you need to manually operate on each element of a tuple other methods are provided like matching. I actually think that it might be possible to achieve some matching like constructs in C++, but I don't think (?) much if any research has been devoted to that.
Erm... every sentence above begs the question: why?
? I'm not sure what you mean by this sentence begging the question of
why. If you know of any research that has been done regarding match
constructs in C++ then please refer me to it. But the reason I don't
think much has been done is because I've never heard of any. OTOH I
don't claim to be aware of everything going on in the C++ world, so
I'd be interested to read any such research you know of.
That being said, given the amount of progress that has been been made
regarding conditional constructs in lambda expressions, I think such
techniques could be extended to allow for matching as well. A match
is generally specified much like a switch statement anyway. For
example, consider:
boost::tuple
Zachary Turner wrote:
On Fri, Jul 10, 2009 at 11:26 AM, Joel de Guzman
wrote: functional languages if you need to manually operate on each element of a tuple other methods are provided like matching. I actually think that it might be possible to achieve some matching like constructs in C++, but I don't think (?) much if any research has been devoted to that. Erm... every sentence above begs the question: why?
? I'm not sure what you mean by this sentence begging the question of why. If you know of any research that has been done regarding match constructs in C++ then please refer me to it. But the reason I don't think much has been done is because I've never heard of any. OTOH I don't claim to be aware of everything going on in the C++ world, so I'd be interested to read any such research you know of.
For this case, we are actually in agreement. And, actually, I am investigating pattern matching (like in FP) for Fusion. Yes, in many cases, this is very powerful. I can agree with you that simple iteration is too low level. But Fusion is not limited to plain for_each iteration. The power is in the composition of the algorithms to do more complex functionalities, like pattern matching, complex traversals, etc. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Zachary Turner wrote:
On Fri, Jul 10, 2009 at 11:26 AM, Joel de Guzman
wrote: This may cause some disagreements but I'm honestly not sure that I agree with the idea that tuples should behave like sequences. Most other languages that enable functional programming style explicitly disallow this, and for good reason. Really? "explicitly"? Can you provide an example of a language
Zachary Turner wrote: that explicitly states this and the reasons why?
I didn't say they explicitly wrote in the standard "tuples cannot be treated as sequences by design", I said that it was a conscious design decision not to allow tuples to be treated as sequences.
Woa! Whose conscious decision? which language? Unless you can provide some basis/references, this is all nonsense.
Lisp is the exception which I forgot about, if there are other widely used functional languages that allow one to treat tuples as sequences that I'm not aware of then I'd be interested to know what they are.
Are you talking about FP only? I can name a lot of languages with heterogeneous sequences. All dynamically typed languages like Lisp inherently have hetero-sequences. C++ and Fusion is unique in that we can have statically typed heterogeneous sequences.
For starters, the word "sequence" implies (in the mathematical sense) that there is a possibility of the length being unbounded.
Sure. Sequences can be finite and infinite.
While one could argue that it's possible to design a tuple class that could hold a number of elements bounded only by the amount of memory in one's computer (which for all intents and purpose we can consider an infinite tuple), a programmer can only define a finite number of types, so there must exist at least one type in the tuple that has values occuring an infinite number of times.
Wrong. Composition of a finite set of types can lead to a virtually(*) infinite number of *unique* types. Of course the limit now is the compiler. Seems you haven't done any expression templates yet? (*the number of permutations is very very large)
So this begs the question of why not change the design of the application, and group similar types together. After all, if you've actually _specified_ an
Sure, why not? There's no-one preventing you from doing that in that particular case. But you forget that in many cases the position in the sequence is important. Seems you haven't done any expression templates alright. It's a very good use-case and exemplifies why we need heterogeneous sequences.
infinite number of values of said types to put into said tuple, then there is necessarily a relation between the values, or a formula if you will allowing one to generate them.
Fusion deals mostly with finite sequences. Infinite sequences are limited to specialized views such as repetitive_view. Anyway, your promise is flawed so I'll stop here. It seems you are against the whole concept of MPL and Fusion purely on pedantic reasons, and even so, without sufficient basis. Sorry, but I don't have time to engage in such a debate. So, unless you have a stronger basis for your claims in the form of real code/examples/use-cases, I'll leave it as it is. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Joel de Guzman wrote:
Fusion deals mostly with finite sequences. Infinite sequences are limited to specialized views such as repetitive_view. Anyway, your promise is flawed so I'll stop here. It seems you are against the
^^^^^^^ --> premise
whole concept of MPL and Fusion purely on pedantic reasons, and even so, without sufficient basis. Sorry, but I don't have time to engage in such a debate. So, unless you have a stronger basis for your claims in the form of real code/examples/use-cases, I'll leave it as it is.
Cheers, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
Zachary Turner wrote:
I didn't say they explicitly wrote in the standard "tuples cannot be treated as sequences by design", I said that it was a conscious design decision not to allow tuples to be treated as sequences. Lisp is the exception which I forgot about, if there are other widely used functional languages that allow one to treat tuples as sequences that I'm not aware of then I'd be interested to know what they are.
For starters, the word "sequence" implies (in the mathematical sense) that there is a possibility of the length being unbounded. This would be relevant if we claimed that tuples *are* sequences, instead of that we can treat them as fixed-length sequences, which is all Fusion's for_each does. I consider it a C++ design problem that there are actually situations where iterating over elements of a tuple is the "quickest" way to accomplish something. When you're iterating over a collection and performing some operation on the items in the collection, the elements neecssarily having something in common otherwise the operation wouldn't make sense. But at the same time, the common aspect is determined by the function, not by any aspect of the types themselves. From a theoretical perspective I think it's better to approach this with typeclasse C++03 only has implicit typeclasses in the form of implicit requirements and documentation. But to have such requirements is indeed a (implicit)
Are you talking about treating tuples as sequences, or simply about heterogenous sequences? Because even Haskell has the latter (Data.HList). Incidentally, Haskell's inability of writing a generic function that operates on tuples of any size is considered a weakness by most sources I have read. precondition of using for_each. For example, you place the implicit requirement of all types being OutputStreamable by doing a for_each that inserts each element into cout. You've lost track of your argument here, though. Typeclasses in Haskell, for example, still don't allow a list to be heterogenous. So are you saying now that it's OK to treat tuples as sequences if all elements are instances of some typeclass (conform to some concept)? Because, as I just said, this is actually a precondition to using for_each. Sebastian
participants (11)
-
Giles Anderson
-
Jeff Flinn
-
JOAQUIN M. LOPEZ MUÑOZ
-
Joel de Guzman
-
Johan Nilsson
-
Neil Groves
-
Robert Jones
-
Sebastian Redl
-
Vladimir Prus
-
Zachary Turner
-
Zeljko Vrba