
Le 20/11/14 23:42, Olaf van der Spek a écrit :
On Thu, Nov 20, 2014 at 11:49 AM, Andrzej Krzemienski <akrzemi1@gmail.com> wrote:
http://www.boost.org/doc/libs/1_57_0/libs/optional/doc/html/boost_optional/q...
By containers you specifically mean map, right? Unordered map for example would not require operator<
Containers (maps) always come up as the primary rationale for operator< However, the user could also define his own comparison function for this purpose.
Perhaps other use cases of operator< could be presented.
I was trying to illustrate how it is useful to think of optional<T> as extending the domain of T (rather than representing "either T or error"). Not to illustrate the storage in containers. Optional really is either T or none (no value) isn't it?
What do other languages do? Do they have something like optional? How are comparisons defined? In Haskell data Maybe = Just T | Nothing
You can not convert a maybe implicitly from a T (the concept doesn't exist in the language as AFAIK). You need to use the constructor Just x = Just 1 y = Nothing This is equivalent to our auto x = make_optional(1); auto y = none; // nullopt You can extract the value of a Maybe by pattern matching. IIUC, that means that you need to consider all the cases, as if we have a switch on an enum and the compiler forced us to have the case for all the enum literals. zeroAsDefault:: Maybe Int -> Int zeroAsDefault mx= case mxof Nothing-> 0 Just x-> x We don't have yet pattern matching in C++. This pattern matching is not equivalent to the optional::value function. We could have a match function that do this in C++14 (maybe C++11) // zeroAsDefault:: Maybe Int -> Int auto zeroAsDefault(optional<int> mx){ return match(mx, [] (pattern<none_t, nothing>) {return 0; } [] (pattern<int, just> x) {return x.value(); } For those that know tagged<T,Tag>, pattern has the same role. We could surely have also something like auto zeroAsDefault(optional<int> mx){ return match(mx, [] (nothing) {return 0; } [] (just<int> x) {return x.value(); } Note that the call to x.value() is safe as we know by pattern matching that pattern<int, just> or just<T> has a T. Maybe is Eq and Ord if T is. data Maybe a= Just a| Nothing deriving (Eq, Ord) I don't know how the Minimal Complete Definition for Eq and Ord are defined, but in any case Maybe T and T don't compare. Just T and Nothing compare however. value_or_eval is called maybe value_or is called fromMaybe value_or(x) = value_or_eval(id(x)) Clearly the safe_optional we are talking of is related to the Haskell Maybe type. In addition Haskell Maybe can be a Functor, an Applicative, an Alternative, a Monad, a ... depending on the type T. It is all this additional functionality that render the use of Maybe simple, even if we don't have conversions.
But is it what people have problems with isn't it?
Some people are surprised by the implicit conversion, because they expect it would not be there. the have this expectation because they do not understand the conceptual model behind optional<T>.
True, they have a problem. I claim, the root of the problem is not understanding the tool they have.
Should the tool match common user expectations (including novice users) or do you expect users to bend their models to the tools? ;)
Maybe the user needs a different tool. Boost or the standard can provide it if there is a real need. Of course having too much tools makes things more complex, but tools that are less suitable to the users are used less or just not used. Boost is a laboratory where tools can be experimented. std::experimental also, but the cost to get accepted a proposal is very high. As Nevin has said, if for the time to move something from std::experimental to std we have two tools that do almost the same thing, but with different interface, and we have no probes that one is better than the other, there is a high risk that none goes to std:: Should the discussion wait until we have a std::optional in C++17 and then propose a std::experimental::maybe (or whatever is called)? I don't think we can wait. Some people is demanding now for these alternative interfaces. If they are not in Boost or in the standard, they will build its own libraries with minimal different flavors (there already a lot of them). Reassuming, I think that providing these alternative (less imperative safe types) as safe_optional or maybe must be done together with a good functional library including Functor, Applicative, Alternative, Monad. This will take some time but I really think it is worth working on it, at least in Boost. C++14 is giving a lot of different design opportunities to those available in C++98. People is experimenting just now. I'm not sure we can have an acceptable solution with C++98. C++14 allows a good experimentation, but I think that the complete solution will be really there when C++ include sum types and pattern matching. Tis could not be done for C++17 as there is not a proposal yet. Best, Vicente