Namespaces
Variants
Views
Actions

Talk:cpp/utility/optional/and then

From cppreference.com

Why do these methods require that the return type is drived from std::optional? It would be far more convenient if the method itself constructed the optional and more in keeping with convenient syntax in other languages such as C#: a?.foo()?.bar()?.baz(). It also requires a default constructible result type, which is another needles(?) restriction.

Never mind - The method I was expecting is called "transform".

[edit] Difference between optional<T>::transform() and optional<T>::and_then()

It is hard to see the difference between optional<T>::transform() and optional<T>::and_then(), so it would be nice if the function description (or an example) would make it clear. --217.229.69.239 08:42, 21 March 2022 (PDT)

I totally agree. The examples should be more explicit: I think it's
std::optional<int>(1).and_then([](auto x) double { return x * 2.5; }) == 2.5
std::optional<int>(std::nullopt).and_then([](auto x) double{ return x * 2.5; }) == 0.0 (lambda returns `double` so `and_then` on `nullopt` returns default-constructed `double`).
The other typical-but-interesting case of `and_then`:
std::optional<int>(1).and_then([](auto x) -> std::optional<double> { return x * 2.5; }) == std::optional<double>(2.5)
std::optional<int>(1).and_then([](auto x) -> std::optional<double> { return x * 2.5; }) == std::optional<double>(std::nullopt) (lambda returns `std::optional<int>` so `and_then` on `nullopt` returns std::optional<int>(std::nullopt)).
std::optional<int>(1).transform([](auto x) -> double { return x * 2.5; }) == std::optional<double>(2.5)
std::optional<int>(std::nullopt).transform([](auto x) -> double { return x * 2.5; }) == std::optional<double>(std::nullopt)
Non-typical use of `transform`, where the lambda returns an optional, resulting in nested optionals:
std::optional<int>(1).transform([](auto x) -> std::optional<double> { return x * 2.5; }) == std::optional<std::optional<double>>(2.5)
std::optional<int>(std::nullopt).transform([](auto x) -> std::optional<double> { return x * 2.5; }) == std::optional<std::optional<double>>(std::nullopt)
Right? BenFrantzDale (talk) 13:45, 28 November 2022 (PST)
the point of monadic ops (in any language) is to work well in combination: they let us code the happy path and not worry about special cases. So IMO it's important to demonstrate that a) you can process a collection containing a mix of values and nullopts as if nullopts aren't even there and b) you can chain the ops. An example that executes a single op on a single predefined optional doesn't add to what the spec already said. --Cubbi (talk) 06:19, 29 November 2022 (PST)
(but looking at it now, it will be useful to drop a few more notes on these pages explaining all that, and also that flatmaps avoid nesting.. instead of just mentioning the common names for those with other language experience) --Cubbi (talk) 06:24, 29 November 2022 (PST)