digitalmars.D - Why does std.variant not have a tag?
- evansl (26/26) Nov 04 2012 http://dlang.org/phobos/std_variant.html
- =?ISO-8859-1?Q?Alex_R=F8nne_Petersen?= (11/37) Nov 04 2012 Yes, this is a big problem with the current std.variant implementation
- Robert Jacques (22/81) Nov 04 2012 I've been working on an update to std.variant whose formal
- Johannes Pfau (8/95) Nov 05 2012 A little off-topic, but IIRC the typeid stuff is only used to allow
- evansl (50/128) Nov 05 2012 Robert, I see no bounded types in the above Variant.
- Robert Jacques (8/46) Nov 05 2012 Thank you for the clarification. Implementing an id seems
- evansl (28/94) Nov 05 2012 The bugzilla request looks good to me, especially the way that the
- Era Scarecrow (12/18) Nov 05 2012 I remember a while back asking about the variant. I wanted to be
http://dlang.org/phobos/std_variant.html says: This module implements a discriminated union type (a.k.a. tagged union, algebraic type). Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the std_variant.html page. Another wiki reference: http://en.wikipedia.org/wiki/Disjoint_union is more explicit because it pairs the tag with the value: (x,i) where x is the value and i is the tag. One reason for an explicit tag is that the bounded types may contain the same type twice. This has lead to problems in boost::variant as evidenced by the post: http://article.gmane.org/gmane.comp.parsers.spirit.general/17118 In addition, both variant and tuple have a common part, a metafunction mapping from a tag to a type; hence, this same common part could be used to implement both tuple and a tagged variant. A variant which actually contained a tag field I think would be more general in that it would allow duplicate types among the bounded types just as a tuple's bounded types can contain duplicate types. -regards, Larry
Nov 04 2012
On 05-11-2012 00:31, evansl wrote:http://dlang.org/phobos/std_variant.html says: This module implements a discriminated union type (a.k.a. tagged union, algebraic type). Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the std_variant.html page. Another wiki reference: http://en.wikipedia.org/wiki/Disjoint_union is more explicit because it pairs the tag with the value: (x,i) where x is the value and i is the tag. One reason for an explicit tag is that the bounded types may contain the same type twice. This has lead to problems in boost::variant as evidenced by the post: http://article.gmane.org/gmane.comp.parsers.spirit.general/17118 In addition, both variant and tuple have a common part, a metafunction mapping from a tag to a type; hence, this same common part could be used to implement both tuple and a tagged variant. A variant which actually contained a tag field I think would be more general in that it would allow duplicate types among the bounded types just as a tuple's bounded types can contain duplicate types. -regards, LarryYes, this is a big problem with the current std.variant implementation (among other problems such as no recursive variants....). The best std.variant can offer right now is the 'type' property to identify what's stored in it. std.variant is, unfortunately, not very useful if you want the semantics of variants in ML-style languages. -- Alex Rønne Petersen alex lycus.org http://lycus.org
Nov 04 2012
On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen wrote:On 05-11-2012 00:31, evansl wrote:I've been working on an update to std.variant whose formal submission has been held up by a PhD thesis and some health issues, although I'm currently (slowly) doing a code review/cleanup of it in the hope of finally submitting it. ( Old code: https://jshare.johnshopkins.edu/rjacque2/public_html/ ) Anyways, my implementation has an internal 'tag' as does the current implementation, IIRC. However, as the tag is a meaningless random number, instead .type is provide access to the meaningful typeinfo object of that class. And .type provides most (all?) of the functionality of an int id: auto var = Variant(5); if(var.type == typeid(int)) { // Do something... } else if(var.type == typeid(string)) { // Do something else... } But I am missing something as I found that the linked post wasn't clear what the exact issue was, only that there was an issue. If someone would like to clarify the problem (or any other with Variant) it would be appreciated.http://dlang.org/phobos/std_variant.html says: This module implements a discriminated union type (a.k.a. tagged union, algebraic type). Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the std_variant.html page. Another wiki reference: http://en.wikipedia.org/wiki/Disjoint_union is more explicit because it pairs the tag with the value: (x,i) where x is the value and i is the tag. One reason for an explicit tag is that the bounded types may contain the same type twice. This has lead to problems in boost::variant as evidenced by the post: http://article.gmane.org/gmane.comp.parsers.spirit.general/17118 In addition, both variant and tuple have a common part, a metafunction mapping from a tag to a type; hence, this same common part could be used to implement both tuple and a tagged variant. A variant which actually contained a tag field I think would be more general in that it would allow duplicate types among the bounded types just as a tuple's bounded types can contain duplicate types. -regards, LarryYes, this is a big problem with the current std.variant implementation (among other problems such as no recursive variants....). The best std.variant can offer right now is the 'type' property to identify what's stored in it. std.variant is, unfortunately, not very useful if you want the semantics of variants in ML-style languages.
Nov 04 2012
Am Mon, 05 Nov 2012 07:33:47 +0100 schrieb "Robert Jacques" <sandford jhu.edu>:On Sunday, 4 November 2012 at 22:33:46 UTC, Alex R=C3=B8nne Petersen wrote:A little off-topic, but IIRC the typeid stuff is only used to allow arbitrary types in Variant. This is a valid use case, but could we use a simple enum/integer tag for Algebraic? There was a discussion about Variant's performance some time ago and if you don't need to store arbitrary types you're currently better of writing a custom discriminated union than using Algebraic.On 05-11-2012 00:31, evansl wrote:=20 I've been working on an update to std.variant whose formal submission has been held up by a PhD thesis and some health issues, although I'm currently (slowly) doing a code review/cleanup of it in the hope of finally submitting it. ( Old code: https://jshare.johnshopkins.edu/rjacque2/public_html/ ) Anyways, my implementation has an internal 'tag' as does the current implementation, IIRC. However, as the tag is a meaningless random number, instead .type is provide access to the meaningful typeinfo object of that class. And .type provides most (all?) of the functionality of an int id: =20 auto var =3D Variant(5); if(var.type =3D=3D typeid(int)) { // Do something... } else if(var.type =3D=3D typeid(string)) { // Do something else... } =20 But I am missing something as I found that the linked post wasn't clear what the exact issue was, only that there was an issue. If someone would like to clarify the problem (or any other with Variant) it would be appreciated. =20http://dlang.org/phobos/std_variant.html says: This module implements a discriminated union type (a.k.a.=20 tagged union, algebraic type). Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the=20 std_variant.html page. Another wiki reference: http://en.wikipedia.org/wiki/Disjoint_union is more explicit because it pairs the tag with the value: (x,i) where x is the value and i is the tag. One reason for an explicit tag is that the bounded types may=20 contain the same type twice. This has lead to problems in=20 boost::variant as evidenced by the post: =20 http://article.gmane.org/gmane.comp.parsers.spirit.general/17118 In addition, both variant and tuple have a common part, a=20 metafunction mapping from a tag to a type; hence, this same common part=20 could be used to implement both tuple and a tagged variant. A variant which actually contained a tag field I think would=20 be more general in that it would allow duplicate types among the=20 bounded types just as a tuple's bounded types can contain duplicate types. -regards, LarryYes, this is a big problem with the current std.variant=20 implementation (among other problems such as no recursive=20 variants....). The best std.variant can offer right now is the=20 'type' property to identify what's stored in it. std.variant is, unfortunately, not very useful if you want the=20 semantics of variants in ML-style languages.
Nov 05 2012
On 11/05/12 00:33, Robert Jacques wrote:On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen wrote:Robert, I see no bounded types in the above Variant. Looking back at: http://dlang.org/phobos/std_variant.html I see now that std.Variant doesn't require the set of types to be bounded. It's only Algebraic: http://dlang.org/phobos/std_variant.html#Algebraic that has a bounded set of types. I should have read closer. I mistakenly thought std.variant served the same purpose as Boost.variant, but now I see that Boost.variant and std.Algebraic serve similar purposes in that they require a set of bounded types, but that Boost.any and std.variant are similar in that the types are unbounded (IOW, any type can be stored in std.variant or Boost.any). Sorry for not carefully reading. So my question then is why doesn't ALgebraic have a tag. This would allow: Algebraic!(int,int)On 05-11-2012 00:31, evansl wrote:I've been working on an update to std.variant whose formal submission has been held up by a PhD thesis and some health issues, although I'm currently (slowly) doing a code review/cleanup of it in the hope of finally submitting it. ( Old code: https://jshare.johnshopkins.edu/rjacque2/public_html/ ) Anyways, my implementation has an internal 'tag' as does the current implementation, IIRC. However, as the tag is a meaningless random number, instead .type is provide access to the meaningful typeinfo object of that class. And .type provides most (all?) of the functionality of an int id: auto var = Variant(5); if(var.type == typeid(int)) { // Do something... } else if(var.type == typeid(string)) { // Do something else... }http://dlang.org/phobos/std_variant.html says: This module implements a discriminated union type (a.k.a. tagged union, algebraic type). Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the std_variant.html page. Another wiki reference: http://en.wikipedia.org/wiki/Disjoint_union is more explicit because it pairs the tag with the value: (x,i) where x is the value and i is the tag. One reason for an explicit tag is that the bounded types may contain the same type twice. This has lead to problems in boost::variant as evidenced by the post: http://article.gmane.org/gmane.comp.parsers.spirit.general/17118 In addition, both variant and tuple have a common part, a metafunction mapping from a tag to a type; hence, this same common part could be used to implement both tuple and a tagged variant. A variant which actually contained a tag field I think would be more general in that it would allow duplicate types among the bounded types just as a tuple's bounded types can contain duplicate types. -regards, LarryYes, this is a big problem with the current std.variant implementation (among other problems such as no recursive variants....). The best std.variant can offer right now is the 'type' property to identify what's stored in it. std.variant is, unfortunately, not very useful if you want the semantics of variants in ML-style languages.But I am missing something as I found that the linked post wasn't clear what the exact issue was, only that there was an issue. If someone would like to clarify the problem (or any other with Variant) it would be appreciated.If std.Algebraic is like Boost.Variant, then duplicate bounded types are not allowed and leads to the problem mentioned in the post on the spirit mailing list which I linked to in my OP. OOPS, now I see why reading that post was not clear enough. Maybe this earlier post in same spirit thread would be clearer. http://article.gmane.org/gmane.comp.parsers.spirit.general/17113 In particular, note the phrase: neither can you use variant<string,string,int> because variant can't take duplicate types. This can lead to problems in the spirit parser because the attributes of parsing: a | b where: phrase a has an attribute of type A phrase b has an attribute of type B is: variant<A,B> as noted near the bottom of: http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html and if A and B are the same, then there's a problem because Boost.variant can't handle duplicates. Hope that's clearer. -regards, Larry BTW, recently there was a review of another Boost library that has some similarity to Boost.any. It's called type_erasure: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html Since std.Variant is similar to Boost.any (as noted above), and since Boost.any is, in some ways, like Boost.type_erasure, and since you're working on a revised std.Variant, you might be interested in looking at type_erasure.
Nov 05 2012
On Monday, 5 November 2012 at 14:13:41 UTC, evansl wrote:On 11/05/12 00:33, Robert Jacques wrote:[snip]On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen wrote:On 05-11-2012 00:31, evansl wrote:If std.Algebraic is like Boost.Variant, then duplicate bounded types are not allowed and leads to the problem mentioned in the post on the spirit mailing list which I linked to in my OP. OOPS, now I see why reading that post was not clear enough. Maybe this earlier post in same spirit thread would be clearer. http://article.gmane.org/gmane.comp.parsers.spirit.general/17113 In particular, note the phrase: neither can you use variant<string,string,int> because variant can't take duplicate types. This can lead to problems in the spirit parser because the attributes of parsing: a | b where: phrase a has an attribute of type A phrase b has an attribute of type B is: variant<A,B> as noted near the bottom of: http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html and if A and B are the same, then there's a problem because Boost.variant can't handle duplicates. Hope that's clearer. -regards, LarryThank you for the clarification. Implementing an id seems reasonable feature request for algebraic. I've added a bugzilla request for it: http://d.puremagic.com/issues/show_bug.cgi?id=8962 Please have a look in case I missed anything.BTW, recently there was a review of another Boost library that has some similarity to Boost.any. It's called type_erasure: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html Since std.Variant is similar to Boost.any (as noted above), and since Boost.any is, in some ways, like Boost.type_erasure, and since you're working on a revised std.Variant, you might be interested in looking at type_erasure.Thanks, I'll take a look at it.
Nov 05 2012
On 11/05/12 13:53, Robert Jacques wrote:On Monday, 5 November 2012 at 14:13:41 UTC, evansl wrote:The bugzilla request looks good to me, especially the way that the tuple and algebraic are made as similar as possible. As I mentioned before, the thing that's similar is the metafunction mapping from tags to types. Maybe that could be a future enhancement. BTW, the idea of this metafunction map I first found in NuPrl, where these types of functions are called type-valued functions, expressed as: B:(A -> U_1) where U_1 represents all the types, primitive and user defined, in c++, and A is something like an enum or unsigned or some other type serving as the set of possible tag values. The above B expression is found here: http://www.nuprl.org/book/Introduction_Type_Theory.html#SECTION00321000000000000000 where it's used to define: dependent functions (corresponding to std.tuple) dependent products (corresponding to std.Algebraic) Thought you might find that interesting, as I did.On 11/05/12 00:33, Robert Jacques wrote:[snip]On Sunday, 4 November 2012 at 22:33:46 UTC, Alex Rønne Petersen wrote:On 05-11-2012 00:31, evansl wrote:If std.Algebraic is like Boost.Variant, then duplicate bounded types are not allowed and leads to the problem mentioned in the post on the spirit mailing list which I linked to in my OP. OOPS, now I see why reading that post was not clear enough. Maybe this earlier post in same spirit thread would be clearer. http://article.gmane.org/gmane.comp.parsers.spirit.general/17113 In particular, note the phrase: neither can you use variant<string,string,int> because variant can't take duplicate types. This can lead to problems in the spirit parser because the attributes of parsing: a | b where: phrase a has an attribute of type A phrase b has an attribute of type B is: variant<A,B> as noted near the bottom of: http://www.boost.org/doc/libs/1_51_0/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html and if A and B are the same, then there's a problem because Boost.variant can't handle duplicates. Hope that's clearer. -regards, LarryThank you for the clarification. Implementing an id seems reasonable feature request for algebraic. I've added a bugzilla request for it: http://d.puremagic.com/issues/show_bug.cgi?id=8962 Please have a look in case I missed anything.IIRC, the main difference between Boost.any and Boost.type_erasure is type_erasure can be used to put some constraints on the contained type such as requiring the type to support certain functions. I think type_erasure calls the constraints concepts. You can search for "type_erasure" here: http://thread.gmane.org/gmane.comp.lib.boost.devel to access some interesting discussions. HTH. -regards, Larry -regards,BTW, recently there was a review of another Boost library that has some similarity to Boost.any. It's called type_erasure: http://steven_watanabe.users.sourceforge.net/type_erasure/libs/type_erasure/doc/html/index.html Since std.Variant is similar to Boost.any (as noted above), and since Boost.any is, in some ways, like Boost.type_erasure, and since you're working on a revised std.Variant, you might be interested in looking at type_erasure.Thanks, I'll take a look at it.
Nov 05 2012
On Sunday, 4 November 2012 at 22:31:56 UTC, evansl wrote:Yet, the wiki page: http://en.wikipedia.org/wiki/Tagged_union says: a tag field explicitly indicates which one is in use. and I don't see any indication of a tag field in the std_variant.htmlI remember a while back asking about the variant. I wanted to be able to specify an area in memory and say 'this is xxx', but couldn't; This was to help avoid having to manually make and manage something like 60 structs and far more complex code to manage that. This leads me to develop my own version (for built-in types); My version isn't anywhere complete (or clean enough) for publication, but enough for my own project (as read-only use). Hmmm curiously enough, i might be able to convert/rebuild by using a polymorphic struct that I'm tinkering with, but that seems like a lot of extra work.
Nov 05 2012