5 ms·
I actually miss exceptions sometimes in rust. I know all about Result, it's great for errors that are recoverable. But there's a lot of errors that aren't real
by LAC-Tech 2y ago
I actually miss exceptions sometimes in rust.
I know all about Result, it's great for errors that are recoverable. But there's a lot of errors that aren't really recoverable inside a library, but you may not want to cause the code using that library to crash - perhaps your buggy component can be worked around.
Ocaml has both algebraic data types and exceptions, and works really well.
- tmtvl 2y agoI believe Rust has ADTs as well, though I don't know whether it has Lisp-style ad-hoc ADTs, with which you could easily do something like: (defun* foo ((bar Bar)) (:returns (or Baz QuuxException ZotException YendorException)) ...) But in Rust syntax.
- brabel 2y agoRust doesn't support that, but there's an RFC trying to figure out how that could be done (hasn't gone anywhere after more than 10 years of discussions): https://github.com/rust-lang/rfcs/issues/294 https://github.com/rust-lang/rfcs/issues/294 But Rust supports macros, just like Lisp, so of course someone wrote a library that provides something similar: https://docs.rs/some-error/latest/some_error/ https://docs.rs/some-error/latest/some_error/ Their post about how they came up with this crate is quite interesting: https://jam1.re/blog/anonymous-sum-types-for-rust-errors https://jam1.re/blog/anonymous-sum-types-for-rust-errors
- tmtvl 2y agoCool, that's the value of languages with macros: adding useful features which help combat needless infrastructure code (AKA boilerplate).
- Expurple 2y agoYeah, but there's always a cultural struggle to prevent everyone from using their own incomprehensible DSL. See "The Lisp Curse" [1]. Even vanilla Haskell (without macros, i.e. without Template Haskell) takes it too far by allowing to define arbitrary custom operators with arbirtary associativity and precedence. Many Haskell libraries are an incomprehensible soup of symbols instead of regular functions with readable names. Rust does pretty well so far. Macros are used appropriately in the ecosystem. [1] http://www.winestockwebdesign.com/Essays/Lisp_Curse.html http://www.winestockwebdesign.com/Essays/Lisp_Curse.html
- kazinator 2y agoThe Lisp Curse was written by someone who never worked on a Lisp project, let alone with other people. It's a good example of what hallucination looked like before AI took it over. Macros are super helpful in communicating ideas to future maintainers. The alternative to writing a macro and using it seventeen times is to just open code some similar logic in seventeen places. The macro calls can all be found by name, and if something is wrong, it can be fixed in one place: the macro definition. Macros run in your development system, and so do not have to be debugged in the live target. Most macris are functional and have only one input: the unexpanded macro call. They can be debugged simply by inspecting the output, and iterating on it.
- Expurple 2y ago> But there's a lot of errors that aren't really recoverable inside a library Aren't all propagated `Result`s examples of errors that the library itself doesn't recover from and lets the caller decide what to do? IMO, panics in libraries are for cases that are either "impossible" (`panic` as `assert`) or the library author made a judgement call that the application is also helpless in this situation (`panic` as `exit`, like OOM in most of `std`). > you may not want to cause the code using that library to crash - perhaps your buggy component can be worked around. That's a question of isolation! Rust libraries operate within the same process and address space as the application code. A buggy library could arbitrarily modify the application data or the process state and violate arbitrary application invariants. I'm not even talking about UB here. Just application-level invariants and assumptions. Given this, the Rust's choice to either "abort the thread and poison held mutexes" or "abort the process" sounds very reasonable. In other discussions, I was pointed to Erlang's "let it fail" error handling with multiple isolated processes. [The Error Model](https://joeduffyblog.com/2016/02/07/the-error-model/ https://joeduffyblog.com/2016/02/07/the-error-model/), which I reference in my post, also touches on this topic.
- LAC-Tech 2y agoRight but in Erlang when individual components (processes) "panic", the whole beam VM doesn't crash.
- John23832 2y agoThat difference is bigger than the language though. The BEAM runtime protects handles process lifetimes.
- bryanlarsen 2y agoPanics in rust threads do not crash the process. Only panics in the main thread crash the process. So if you run nothing in the main thread, you can take advantage of this.
- LAC-Tech 2y agoI didn't know that.