...sounds good to me!
...sounds good to me!
If I call into a library and something goes awry I don't want to have to care about the inner workings of that library. Most of the time it's sufficient for me to try/catch that call and if it fails I'll handle it as gracefully as possible at my level.
Useful effect systems allow the end user to decide where and when to have the compiler enforce errors are handled. Nim has had an effect system for a while but became much more useful when `forbids: [IOError]` was added. It makes it easy to ensure certain type of errors are handled at specific points.
More languages should embrace effect systems. Ocaml's is even used to implement multithreading support, albeit effect systems vary widely in design and theory.
But errors-as-values are all the rage today. But modifying types, especially every type in the chain, is annoying and overly manual IMO.
Checked exceptions were annoying because you had to manually annotate the exceptions all the way up your chain. The list of effects should be generated by the compiler, and the IDE should show them when desired. Maybe manually annotated at external API boundaries which double as forcing the API dev to handle unlisted exceptions.
Yes and I'm opposed to such "if err != nil" boilerplate.
That is not what Rust boilerplate looks like.
Acknowledging the error is handling the error even if partially. The point of exceptions is to only acknowledge error that one can/knows how to properly handle
In Rust this takes a single character. There's effectively no cost to having the programmer acknowledge the error, and there's a large benefit in that you now know that there's no such thing as an error that the programmer ought to have handled but was simply unaware of. That's a huge benefit for writing resilient software.
Alternatively everything just gets put into a `dyn trait` and you're effectively just bubbling up errors just like with exceptions, but with way more programmer overhead. The performance overhead of constantly doing if/else branches for errors adds up as well in some situations.
Of course a fair bit of Rust code just uses `unwrap` to deal with inconvenient errors.
All functions are capable of producing an unbounded set of errors.
(Yes, programming is hard.)
It takes statically typed C++ and turns it into dynamically typed language. Throwspec is dead, anything can throw, except when noexcept, then nothing can throw.
It is next to impossible to reason about control flow. Dynamic linking opens whole new dimension of this wormcan. Do you handle exceptions in your constructors? How about constructors of your function arguments?
Not to mention the non-trivial cost in code size, that makes exceptions a non-option for embedded use.
It allows, for example, std::vector's resize operation to move its contents rather than copying them, iff its element's move constructor is [[noexcept]]. If the move constructor could throw, the items must be copied so the original buffer is unchanged until the entire copy transaction is complete.
std::move_if_noexcept <https://en.cppreference.com/w/cpp/utility/move_if_noexcept>
"N3050: Allowing Move Constructors to Throw (Rev. 1)" (2010) <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n30...>
"P2861R0: The Lakos Rule – Narrow Contracts and noexcept Are Inherently Incompatible" (2023) <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p28...>
"P2946R1: A Flexible Solution to the Problems of noexcept" (2024) <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p29...>
At least delegation (IIUC closer to concatenation as defined in [1]) is currently being implemented, but I can't say how much weight it can actually carry for the OOP efforts.
[1] "On the Notion of Inheritance": https://users.csc.calpoly.edu/~gfisher/classes/530/handouts/...
> These discrepancies are responsible for an impedance mismatch when interfacing the two languages. Most code generators for inter-language bindings aren’t able to represent features of one language in terms of the features of another.
Function overloads are evil evil evil. Requiring some mental gymnastics by the reader to pretend to be the compiler what function is actually called. That sucks.
Take Pattern. One way to look at Pattern is to say that this way we can provide the ad hoc polymorphism of overloading, for functions like str::contains or str::split or str::trim_end_matches -- but as a trait we can see that actually Pattern has discernible semantic properties, clearly a compiled regular expression could be a Pattern for example (and with some feature flags that's exactly correct)
In contrast in C++ there are often functions which use/ abuse overloading to deliver separate features in the same interface, expecting that you'll carefully read the documentation and use the correct feature by passing the right type and number of parameters. Constructors are the worst for this, Rust's Vec::with_capacity gets you a growable array with a certain capacity already allocated ready for use -- C++ does not have such a thing - you must make a std::vector and then separately reserve enough space, but it looks like it might have this feature in its constructor as an overload because the constructor has an overload which is the right shape - however that's actually a very different feature, it will fill the std::vector with default initialized objects, rather than reserving capacity for such objects.
Calling x.some_func() in rust means there is either a type specific function or an impl trait. If more than one option is there rust requires more explicitly calling the types function with x as a parameter.
E.g.
Something::some_func(x)
I’ve never read rust code where I’m entirely guessing which overloaded function is being called. C++ has an entire set of overload resolution rules around this! https://en.cppreference.com/w/cpp/language/overload_resoluti...
Having learned Go and Rust in the last two years, it occurs to me that -- if this can be made into a trivia, and considering all the things in C++ like friend class, nested class, public/protected/private inheritance matrix and all the "possibilities" out there, it seems this language is seriously f*cked up.