3 ms·
Good post. Not capturing a stack trace is a Rust specific thing -- this is easy to do in Scala, for example, and still maintain the benefits of monads + algebra
by noelwelsh 11y ago
Good post. Not capturing a stack trace is a Rust specific thing -- this is easy to do in Scala, for example, and still maintain the benefits of monads + algebraic data types. I'm sure Rust will get similar utilities with time.
The main issue I have with this technique is the higher mental overhead when getting started. That goes away with a bit of practice.
- seanmcdirmid 11y agoScala gets stack traces automatically from the JVM though, along with much of its debugging support. The Rust team will have to do this all by themselves, being a natively compiled language and all.
- noelwelsh 11y agoSure. The author mentioned lack of stack traces as a downside of the technique. I wanted to clarify this was Rust specific (and likely to change).
- masklinn 11y agoYou can get stack traces on panics by running with RUST_BACKTRACE=1. I don't know that it makes much sense on Error objects though, there's no requirement that they're even able to store backtraces, and collecting backtraces any time an error object is created would be really expensive and would make the runtime a dependency of errors.
- seanmcdirmid 11y agoMost VMs put most of the overhead of stack creation at where the error is created, so it usually works out fine (throw is expensive, everything else is cheap). Stack traces are usually dependent on whatever debug symbols are loaded, so in the CLR you'll get huge blank spaces if an exception propagates through some dynamically generated or even native code. Just printing stack traces is a distraction though. The only thing that is required that on an exception, the entire stack above the the exception site can be inspected in the debugger.
- masklinn 11y agoThat's a completely different concern, and it only makes sense on panics, not any time an Err result is created.
- seanmcdirmid 11y agoAnd how do you tell where an error originated without a panic being called? Is the programmer expected to just instrument the their code to put the panic in as soon as possible? Anyways, this is a well-known problem with monadic error handling, and one of the main reasons it doesn't get more widespread adoption.
- masklinn 11y ago> I'm sure Rust will get similar utilities with time. Unlikely. Scala gets tracebacks for Try because the left arm stores a JVM Throwable, and throwables reify a stacktrace during initialisation. For Rust, this would mean: * Result's Err mandates an Error (currently has no trait bound at all) * Errors must be able to store a traceback * Error/Result requires rt in order to collect a stacktrace * Rather than stack-allocating a struct or two, Err results now require significant heap allocation and data collection completely breaking existing usage patterns
- seanmcdirmid 11y agoAs long as Err results are only created under exceptional circumstances, there should be no performance hit right? This is one significant reason why errors should get a path separate from normal return values, but that isn't the case in Rust (or monadic error handling in general, which doesn't really consider debugging).
- noelwelsh 11y agoI'm not suggesting `Err` stores a backtrace. I am suggesting that the programmer could choose to store a backtrace in the error objects they choose to store in an `Err`. I don't do this in my Scala code because I rarely find I need a backtrace. (I don't use `Try` for reasons described here: http://underscore.io/blog/posts/2015/02/23/designing-fail-fast-error-handling.html http://underscore.io/blog/posts/2015/02/23/designing-fail-fa...)
- masklinn 11y ago> I am suggesting that the programmer could choose to store a backtrace in the error objects they choose to store in an `Err`. That's already possible, though it requires nightly as it's an unstable "feature": http://doc.rust-lang.org/stable/std/rt/backtrace/index.html http://doc.rust-lang.org/stable/std/rt/backtrace/index.html This will collect a stacktrace in the provided buffer, the result can then be stored in whatever object the developer wants (likely after decoding it to a String): http://is.gd/tOD8Ho http://is.gd/tOD8Ho