Open utterances-bot opened 1 year ago
To paraphrase a well-known saying "It's C++, Bartek, but not as we know it..."
Great article, someday when our project makes it to c++23, will love using these. One comment, you make the statement "the subsequent operations are skipped" in the section Improved Error Handling. This is not entirely true, as each operation is still invoked, just the behavior is based on the std::optional. For example, or_else only calls it's callable if the std::optional is empty.
Thanks @sjames1958gm ! I updated the text with "operations (custom callables))", maybe that's better.
The return type should not be another std::optional.
It's worth mentioning IMO that it works just fine, creating nested std::optional. And the "should not" admonition sounds strange to functional programmers who do such stuff all the time. In these times of growing influence of functional programming on (among others) C++, as this very article exemplifies, a more open embrace thereof would be appreciated by me and probably many others who like this style newly available in C++.
U must not be std::in_place_t or std::nullopt_t.
Probably most of your readers are C++ veterans for whom the reasons of these restrictions are obvious. But I still dare ask, hoping for an answer: why?
the same can be written in old way (i used boost 1.70):
int main()
{
const int userId = 12345;
std::optional<int> age;
std::optional<UserProfile> profile = fetchFromCache(userId) ? fetchFromCache(userId) : fetchFromServer(userId);
cout << (profile && (age = extractAge(*profile))
? format("Next year, the user will be {} years old", *age + 1)
: "Failed to determine user's age.\n");
}
in my experience, the functional way of programming could be handy sometimes, but practically not used much. Sometimes I think - stop beating the dead horse (i.e add unnecessary features to c++), instead switch to python ;)
doesn't have many sense w/o coroutines/async support
What is the best way to use monadic API for operations requiring 2+ values stored in optionals.
Just for example purposes - assume we have "int func(int, int);" and "optional
Is the following way the only way, or we can do shorter/more readable?:
auto res = opt1.and_then([&opt2](auto v1)
{
return opt2.transform([v1](auto v2){ return func(v1, v2); });
}).value_or(-1);
Imagine you have an operation that requires 5 values stored in optionals, then sequence of and_then,..and_then...transform... with lots of lambdas and captures can be quite challenging comparing to:
if (opt1 && opt2 && opt3 && opt4 && opt5)
{
return func(*opt1, *opt2, *opt3, *opt4, *opt5);
}
return -1;
How to Use Monadic Operations for
std::optional
in C++23 - C++ StoriesIn this post we’ll have a look at new operations added to std::optional in C++23. These operations, inspired by functional programming concepts, offer a more concise and expressive way to work with optional values, reducing boilerplate and improving code readability. Let’s meet and_then(), transform() and or_else(), new member functions. Traditional Approach with if/else and optional C++20 In C++20 when you work with std::optional you have to rely heavily on conditional checks to ensure safe access to the contained values.
https://www.cppstories.com/2023/monadic-optional-ops-cpp23/