C 23 adds some "monadic-style" functionality regarding optionals, as methods of optional<T>:
optional<T>::and_then() (and ignoring qualifiers of this):
template<class F> constexpr auto and_then(F&& f);Returns the result of invocation of f on the contained value if it exists. Otherwise, returns an empty value of the return type.
optional<T>::transform() (and ignoring qualifiers of this):
template<class F> constexpr auto transform(F&& f);Returns an
std::optionalthat contains the result of invocation offon the contained value if*thiscontains a value. Otherwise, returns an emptystd::optionalof such type.
So, aren't these two functions doing the same thing?
CodePudding user response:
The phrasing, and the unqualified template, aren't super-helpful in figuring out the difference, but: transform() does "re-boxing" into an optional, but and_then() does not, expecting the function to returned a boxed value on its own. So,
transform()is for when you want to use a function likeT2 foo(T1 x).and_then()is for when you want to use a function likeoptional<T2> bar(T1 x).
Both my_optional.transform(foo) and my_optional.and_then(bar) return a value of type optional<T2>.
See also this question.
CodePudding user response:
and_then is monadic bind aka flatmap aka >>= and transform is functorial map.
One can express map in terms of bind generically, but not the other way around, because a functor is not necessarily a monad. Of course the particular monad of std::optional can be opened at any time, so both functions are expressible in terms of ordinary pre-C 23 std::optional API. Thus the question why the C standard defines both functions is no better than the question why it defines any of the two. Perhaps the Standard wishes to give the programmer a standard functorial interface and a standard monadic interface independently. Either interface is useful and important on its own right.
