I was struck by how similar the conventions around scala error handling are to go’s error handling. Go also discourages programmers from panic'ing in a way that’s visible outside of a package. Frankly I think most go programmers never panic/recover except on their root http.Handler.
Given scala’s gargantuan type system I thought they’d some awesome monad error handling mojo. Not “use errors as values”, “don’t throw”, “don’t call things that might throw”.
This is not an isolated case - awesome monad mojo mostly just enables good engineering. The great advantage of Scala and of type systems in general is that you don’t need language-level special cases for your functionality. There’s no magic, just boring old values.
Go has one half of it right. But it’s the monads that enable for/yield, which makes it possible to treat errors as values without having to keep typing the same lines over and over again. It’s the monads which allow you to treat async operations as just values, without having to make them invisible like Go (analogous to runtime exceptions) or painfully clunky like many languages. Most of all it’s the monads that allow you to write your own similar “context” structures and reuse library functions with them, that let you do the ordinary, boring thing of factoring out common code even if that code involves async, errors, audit trails or any other exciting concern that you might be tempted to handle magically.