----- Original Message ----- From: "Dave Gomboc" <[EMAIL PROTECTED]> To: "Boost Mailing List" <[EMAIL PROTECTED]> Sent: Thursday, December 12, 2002 11:19 PM Subject: [boost] (corrected) review of optional library
> Adjusted at five points; please ignore the previous one. > > ---------- Forwarded message ---------- > At this point in time, I vote to reject the library. My vote is based > upon a review of the interface and implementation in optional.hpp of the > zip file I downloaded from the link posted by Fernando on Dec. 12, and > following the discussion via the mailing list digests. I will qualify my > vote by indicating that this is my first review for boost. > Welcome! > The interface is undergoing a considerable amount of flux during the > review period, and I think that significantly more change is still > required before I would vote for its inclusion. > I understand. I as said in my previous post, we better reject it until we do find a well thought interface. > The operators that (unsuccessfully) attempt to provide pointer semantics > are misleading, and should be removed. To me, appeals to optional being a > container (or giving it pointer semantics, as if it were an iterator!) > are misguided. > Point taken. It is consufing, granted. Wouldn't say that misleading though. > In my opinion, optional<T> [which perhaps ought to be may_be<T> or > maybe<T>, as an earlier poster suggested, also see below] The class name can be reconsidered, yes, on the light of this precedence. But I'll get to that point once we setlle on the interface. > works best as > denoting a type T', whose assignable values are the legal values for type > T unioned with the value "nil", or "nothing" (as in Haskell). (It > shouldn't be called "uninitialized", because that would be misleading. > "nil" is a perfectly valid value for a variable of type T' to take.) > This is a possible model. Another model is that of a container of fixed capacity 1 which can have 0 or 1 elements. The term uninitalized is unappropriate for the Union model, but entirely appropriate IMO for the _concept_ of optional values. > Because "nil" is just another value, operator== can be defined > straightforwardly. If both are "nil", return true; if exactly one is, > return false; otherwise the normal comparison value is returned. > > operator< could be left undefined, but it is simple enough to arbitrarily > choose that "nil" is strictly less than every other value. I don't see a > downside to this, and it would ensure that T' is a strict weak ordering > whenever T is, which is useful for STL usage. > > The operators !=, >, <=, and >= directly follow from definitions of the > above two operators. > Agreed. Notice that the 0-1-elements container model also allows for a well defined definition of relational operators. > Conversion from T' to T is straightforward except when the value of type > T' is nil. In this case, the developer may want to throw, > default-construct the value of T, or assert. Template policy choice? > (Perhaps that's overkill.) > As Peter said, default-construct T undermines the whole purpose of optional. The best is, IMO, to leave it undefined in that case. > > One could possibly provide a test for the nil state by declaring an enum > (in some scope) that defined some (arbitrary) value to "nil", then > providing an operator== that allowed comparisons on that enum type, to > allow code such as: > > using boost::may_be; > ... > > may_be<int> blah(void) { > > may_be<int> x(5); // x is constructed to value 5 > may_be<int> y; // y is default-constructed to value nil > ... > if (y != nil) { ... }; > ... > x = nil; > ... > return std::max(x, y); // defined since std::less uses operator< > }; > Such a syntax is possible, granted, and we would have it out of the box with variant<T,nil_t> provided nil_t is a class type. It is, however, IMO, _too_ cumbersome. > It is possible, but not necessarily desirable, to include "is_nil()" or > "is_not_nil()" functions. operator!() already exists in Fernando's code > as the equivalent to "is_nil()"; a double invocation (e.g. "!!x") would > be equivalent to "is_not_nil(x)". I suspect it is probably not worth > fattening the interface for them, but this may be a matter of taste. > Agreed. > (Also, below is a message I had sent to Fernando already, but I suppose it > might as well be sent to boost also.) > --- which I left unresponded... sorry :-) > Dave > > > ---------- Forwarded message ---------- > > "Maybe" is a built-in type constructor in Haskell, which AFAIK is the most > widely used functional programming ("FP") language. It is used to denote > exactly what your suggested optional<T> is. (Which is why I am > recommending use of "maybe<T>" or "may_be<T>" instead of optional<T>.) > > > Maybe is defined in Haskell as > > data Maybe a = Nothing | Just a deriving (Eq, Ord, Read, Show) > > (here "a" is an arbitrary type; "Nothing" is like "nil", "NULL", > "uninitialized", or whatever you want to call it.) > > > An example in Haskell syntax: > > safe_division :: Float -> Float -> Maybe Float > safe_division x y = > if y == 0 then Nothing > else Just (x/y) > > > Consider this Haskell declaration: > get_maximum_value :: BTree Int -> Maybe Int > > The equivalent (free function) declaration in C++ would be: > may_be<int> get_maximum_value(const BTree<int> &); > > > Yet another function prototype: > > get_cached_value :: a -> [(a, b)] -> Maybe b > > which can return Nothing if the function does not have "a" as the first > item of any of the pairs in the list. > > > > As an example, currently the C++ standard includes > T & stack<T>::top(), with precondition !(stack.empty()). > > Instead, it could be > may_be<T> & stack<T>::top(); // no precondition required > > > <set> could be improved also, instead of: > pair<iterator, bool> set::insert(const value_type & x) > > we would use > may_be<iterator> set::insert(const value_type & x) > > where the return value is initialized to the place of insertion if x > was inserted, or is uninitialized if x was not inserted. > > > Of course, it is possible to use variables of type may_be<T>: > > int blah(int x) { > > may_be<int> y; // default-constructed to uninitialized, right? > . > . > . > // expressions involving y here are okay instead of invalid. > . > . > . > }; Those are interesting examples! Thanks. They can all be paralleled with optional<> whatever the model and interface we choose. Which can of shows that the concept is useful. > > (The use as an optional function parameter is no doubt what you had in > mind in the first place, and where you got the "optional" name from.) > Actually, the named was coined originally by Peter Dimov; it used to be called statefull_t<> Fernando Cacciola _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost