2017-01-26 12:15 GMT+01:00 Niall Douglas
On 25/01/2017 16:22, Andrzej Krzemienski wrote:
Ok, so I had a short glimpse at Part A. Actually, the first thing I did was to scroll down to the example showing how I will be using this library. Again, I feel uncomfortable about the choice of the example (so I changed the irritation into non-comfort). The situations that are tested, I would classify them as precondition violations, and I wouldn't think of checking them in return value. If this was a real program, and I didn't trust the values of x and y, I can check the preconditions prior to invoking functions:
I couldn't agree more. It's an example of bad design and programming. But I had at least five people email me saying "please put the Rust example of use of Result side by side with an example of C++ Expected".
Wow. Indeed Rust docs do it. This is what you are referring to: http://rustbyexample.com/std/result.html This example doesn't do good service to Rust, does it?
I mean, if it is equally easy to check the condition before and after the function, it is better to do it before, and I do not have to "pollute" the return value with potential error conditions. I think the value of these expected<> types becomes clear, when we cannot see the erroneous situation from the arguments. Maybe a better illustration of expected<> with a code would the following situation:
Upon closing the application, I store its state in a text file. When I reopen the application the next time, I load the state from the file. Here is the function:
expected
state = load_state(); And now, the error conditions are: * file missing * file is not a text file * file contains erroneous contents
And I might want to respond to each of these conditions in a different way.
The first version of the tutorial had a reduced real world use example from AFIO's implementation of opening a file where we perform a series of syscalls and do different stuff depending on the result<T>'s returned. Everybody hated it, they said it was too confusing. Yet in fact the use of result<T> has *greatly* simplified that code. In AFIO v2 it's merely dozens of lines, in AFIO v1 it was approaching a thousand lines so the use of Outcome has been a big improvement in readability and maintainability.
I suspect people want contrived toy examples rather than examples of what you'd actually write. I remember thinking the same about the ASIO tutorial, and I personally speaking found the ASIO tutorial so reduced in real world detail as to be confusing at best, productivity damaging at worst. You end up having to grok through the ASIO source code to figure out answers to stuff. Not a good tutorial.
I think, what other libraries do is to put real-life practical examples as source code in `examples` folder. You can compile and run them to verify if they are really correct, and you can also see how to get headers and namespaces right.
So I'm really not sure what to do. I've slowed down the pace of the tutorial several fold over the original now to the point where it's become anodyne. I've reduced the length of the code examples so they always fit onto a screen because according to feedback anything longer than a single screen is "too long". I've also ramped up the frequency of code examples because my prose is "too confusing" and "you need lots more C++ code examples". But all this hand holding comes with the cost that the code examples become really contrived, and the tutorial has become so long it needs three parts, which is frankly ridiculous for something so simple as a slightly enhanced std::optional<T> with a bit of std::variant<...> muxed in. I really don't get what's so hard here, just throw std::optional and std::variant into a bowl and apply a blender. All the APIs and semantics stay the same and there are no surprises in behaviour, it's all STL idiomatic. You're done.
LOL. This indeed must be very frustrating. The expectations of different people are just contradictory. The way you put it now, "a slightly enhanced std::optional<T> with a bit of std::variant<...> muxed in", is in fact a quite simple and illustrative description of the library. Maybe the problem here was with how this library was initially introduced: as "monads" and "transports".
I'm still aiming to end Tutorial part C with a real world code example that is actually realistic and taken from actual use case. It will, necessarily, span multiple screens. But I suspect I won't be allowed anything but daft examples in the middle. Sorry.
When I first learned about Boost. I was amazed by the documentation the libraries offer. Quite a number of the libraries has a very nice documentation, which describe not only the library, but also the problem domain the library addresses, why the alternatives are inferior. I learned quite a lot about type safety, generic programming, exception safety, and C++ in general only from reading Boost docs. I have also learned a number good idioms and programming practices. It would be a shame if the library shows in the tutorial page (one of the first we read) an example of a bad programming practice. Some people my get the message that this is how we encourage you to write your code. If someone wants to have a comparison with a poor but popular Rust example, I do see value in it, but maybe not as the flag example of your library. Maybe put it somewhere further, in section dedicated to Rust users. I know people come from different backgrounds and with different preferences. Mine is: show me first a trivial example, than a couple of medium-sized example, finally, show me a real-life example and reference. I know, I am complaining a lot. But all-in-all, I find the current iteration of the docs acceptable: they provide initial motivation that is sufficient to dig further. Regards, &rzej;