variant - off topic
I've been and observer on the discussions regarding variant, expected, outcome, optional, outcome and ?? for sometime. I'm pretty amazed at the amount of controversy each and everyone of these in every forum - here, C++ committee, etc. I'm beginning to wonder this isn't telling us something. It seems natural that when making a new C++ data type, we should want to implement the assignment operator. Why - well every variable needs to be assigned to from time to time. Why is this so? Well ... Suppose we break this assumption and consider the idea that assignment doesn't make sense for every type. A variant is a "meta-type" or "sum type" which "holds" one of a set of other types. Such a variant can take on the character of any one of type types it is holding. When does it make conceptual sense for a variable to change it's type one it has been initially assigned. I've been trying to think of one and haven't been successful. Here are a few of the scenarios I've considered. a) Returning a sum type - the most common scenario for a variant. Doesn't require a assignment. Copy/move may still be required of course. b) looping through a vector of variants as in vector variant<...> v; for( variant<...> v : [](){...} fix with change to vector variant<...> v; for( variant<...> & v : [](){...} c) set according to condition variant<...> r; if(i < 0) r = v<t1>(...) else r = v<t2>(...) fix with change to variant <...> r = (i < 0) ? v<t1>(...) : v<t2>(...); d) insert your own use case here. That is, look at your own usages of assignment to these types and see if there is not an easy way to re-factor your code to avoid assignment. I'll concede that, influenced by functional programming style, with a little experimentation with F# and propaganda from the Haskell community, I've become accustomed to code in the above way. Also I've become afraid to assign anything to these types. The discussion has made me aware of a raft of unintended consequences of doing what on it's surface seems a trivial operation. I've gotten to the point that assignment to a variant type, or "changing the type" of a value at runtime is not code smell to me. Maybe all this could be just eliminated if this became the accepted position. Of course I realize that by engaging in the practice I do, the whole issue becomes irrelevant to me personally. And I can always create variant types as "const". It's not about that. It's about avoiding the creating of vocabulary types which lead to problems. So - simple proposal. Require that sum types have operator= deleted. Robert Ramey
śr., 3 kwi 2019 o 23:28 Robert Ramey via Boost
I've been and observer on the discussions regarding variant, expected, outcome, optional, outcome and ?? for sometime. I'm pretty amazed at the amount of controversy each and everyone of these in every forum - here, C++ committee, etc. I'm beginning to wonder this isn't telling us something.
It seems natural that when making a new C++ data type, we should want to implement the assignment operator. Why - well every variable needs to be assigned to from time to time. Why is this so? Well ...
Suppose we break this assumption and consider the idea that assignment doesn't make sense for every type. A variant is a "meta-type" or "sum type" which "holds" one of a set of other types. Such a variant can take on the character of any one of type types it is holding. When does it make conceptual sense for a variable to change it's type one it has been initially assigned. I've been trying to think of one and haven't been successful. Here are a few of the scenarios I've considered.
a) Returning a sum type - the most common scenario for a variant. Doesn't require a assignment. Copy/move may still be required of course.
b) looping through a vector of variants as in
vector variant<...> v; for( variant<...> v : [](){...}
fix with change to
vector variant<...> v; for( variant<...> & v : [](){...}
c) set according to condition
variant<...> r; if(i < 0) r = v<t1>(...) else r = v<t2>(...)
fix with change to
variant <...> r = (i < 0) ? v<t1>(...) : v<t2>(...);
d) insert your own use case here. That is, look at your own usages of assignment to these types and see if there is not an easy way to re-factor your code to avoid assignment.
I'll concede that, influenced by functional programming style, with a little experimentation with F# and propaganda from the Haskell community, I've become accustomed to code in the above way. Also I've become afraid to assign anything to these types. The discussion has made me aware of a raft of unintended consequences of doing what on it's surface seems a trivial operation. I've gotten to the point that assignment to a variant type, or "changing the type" of a value at runtime is not code smell to me. Maybe all this could be just eliminated if this became the accepted position.
Of course I realize that by engaging in the practice I do, the whole issue becomes irrelevant to me personally. And I can always create variant types as "const". It's not about that. It's about avoiding the creating of vocabulary types which lead to problems.
So - simple proposal. Require that sum types have operator= deleted.
Robert Ramey
It is an interesting observation. I am not sure about the consequences, though. It is not only assignment. I ti s also swap. STL algorithms, such as sort() use assignment and swap inside. The question is: should std::sort on variants work? Or because of the special properties of a variant some STL algorithms should break, maybe storage in containers should be prohibitted? For sure, the assignment of such containers would be banned. Regards, &rzej;
On 4/3/19 2:58 PM, Andrzej Krzemienski via Boost wrote:
So - simple proposal. Require that sum types have operator= deleted.
Robert Ramey
It is an interesting observation. I am not sure about the consequences, though.
Right - hence the motivation for my post. It is not only assignment. I ti s also swap. STL algorithms, such
as sort() use assignment and swap inside. The question is: should std::sort on variants work?
Just the kind of example I was hoping to get. This would raise the question: Under what circumstance would one want to do this? Of course definition of a comparison function would be non-trivial. Or maybe this should be the red flag which says "you don't really want to do that".
Or because of the special properties of a variant some STL algorithms should break, maybe storage in containers should be prohibitted?
For sure, the assignment of such containers would be banned. interestingly I could also envision storage in containers without sorting being supported. But then as far as I know, all containers require that the member type be assignable? So by deleting the assignment operator - these would already be prohibited with a concept check.
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
śr., 3 kwi 2019 o 23:28 Robert Ramey via Boost
I've been and observer on the discussions regarding variant, expected, outcome, optional, outcome and ?? for sometime. I'm pretty amazed at the amount of controversy each and everyone of these in every forum - here, C++ committee, etc. I'm beginning to wonder this isn't telling us something.
It seems natural that when making a new C++ data type, we should want to implement the assignment operator. Why - well every variable needs to be assigned to from time to time. Why is this so? Well ...
Suppose we break this assumption and consider the idea that assignment doesn't make sense for every type. A variant is a "meta-type" or "sum type" which "holds" one of a set of other types. Such a variant can take on the character of any one of type types it is holding. When does it make conceptual sense for a variable to change it's type one it has been initially assigned. I've been trying to think of one and haven't been successful. Here are a few of the scenarios I've considered.
a) Returning a sum type - the most common scenario for a variant. Doesn't require a assignment. Copy/move may still be required of course.
b) looping through a vector of variants as in
vector variant<...> v; for( variant<...> v : [](){...}
fix with change to
vector variant<...> v; for( variant<...> & v : [](){...}
c) set according to condition
variant<...> r; if(i < 0) r = v<t1>(...) else r = v<t2>(...)
fix with change to
variant <...> r = (i < 0) ? v<t1>(...) : v<t2>(...);
d) insert your own use case here. That is, look at your own usages of assignment to these types and see if there is not an easy way to re-factor your code to avoid assignment.
I'll concede that, influenced by functional programming style, with a little experimentation with F# and propaganda from the Haskell community, I've become accustomed to code in the above way. Also I've become afraid to assign anything to these types. The discussion has made me aware of a raft of unintended consequences of doing what on it's surface seems a trivial operation. I've gotten to the point that assignment to a variant type, or "changing the type" of a value at runtime is not code smell to me. Maybe all this could be just eliminated if this became the accepted position.
Of course I realize that by engaging in the practice I do, the whole issue becomes irrelevant to me personally. And I can always create variant types as "const". It's not about that. It's about avoiding the creating of vocabulary types which lead to problems.
So - simple proposal. Require that sum types have operator= deleted.
Interestingly, the current work on the language variant ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0095r2.html) goes into a somewhat similar direction. If types stored in the variant are unfriendly (strong guarantee cannot be offered) the assignment is implicitly declared as deleted. Users can still choose to define it and provide the implementation of their liking. Regards, &rzej;
On 4/3/19 3:08 PM, Andrzej Krzemienski via Boost wrote:
śr., 3 kwi 2019 o 23:28 Robert Ramey via Boost
So - simple proposal. Require that sum types have operator= deleted.
Interestingly, the current work on the language variant ( http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0095r2.html) goes into a somewhat similar direction. If types stored in the variant are unfriendly (strong guarantee cannot be offered) the assignment is implicitly declared as deleted. Users can still choose to define it and provide the implementation of their liking.
very interesting. I checked the link. Indeed, a cursory examination of
the link convinces me that your abstract is likely correct.
Still, it still requires that the user of the library object investigate
pretty deeply as to what the thing does behind the scenes - which is one
thing I'm always criticizing. One good thing about the current
proposals is that they "just work (usually)" as there are no special
rules to learn how to use them.
And of course whatever variant of variant I choose I can always just
make it const so it can't be changed after initialization.
So maybe it just needs one of the &rzej; blog posts: title - "non const
variant is code smell" and hope that it becomes a design pattern.
it also might be an interesting idea to create "safe_variant
Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Le mercredi 03 avril 2019 à 14:27 -0700, Robert Ramey via Boost a écrit :
I'll concede that, influenced by functional programming style, with a little experimentation with F# and propaganda from the Haskell community, I've become accustomed to code in the above way. Also I've become afraid to assign anything to these types. The discussion has made me aware of a raft of unintended consequences of doing what on it's surface seems a trivial operation. I've gotten to the point that assignment to a variant type, or "changing the type" of a value at runtime is not code smell to me. Maybe all this could be just eliminated if this became the accepted position.
Variants are really usefull as a container for a definite set of messages in message queues between tasks/threads, and that usually involves storing the last received message in a variable. The nice thing is such variants must be variants of POD, so they don't have the issues being discussed here. I like the idea of simply deleting operator= : if you can't guarantee you do something correctly, just don't do it. Optionnaly provide an unsafe interface if it really make sense. Regards, Julien
participants (3)
-
Andrzej Krzemienski
-
Julien Blanc
-
Robert Ramey