> I see it more as explicit. You HAVE to decide what you're going to do in case of an error.
I've often read this argument, but i don't see how that is an advantage over using exceptions.
With exceptions you don't have to decide what to do in every function call that might raise an error. You just have to know that they can raise one, and code accordingly. For example:
f = File.open(...)
foo(f)
bar(f)
f.close()
Is buggy if foo or bar could raise exceptions (the file would not be closed if an exception is raised there). Fixing it could imply adding a `finally` block around f.close() so the file always gets closed (same as Go's defer) or using a higher order function that already does that for us:
File.open(...) do |f|
foo(f)
bar(f)
end
The thing is, this code didn't need to worry about which of foo or bar was raising an error; it just needed to worry about closing the file if anything went wrong. And i could add a new baz(f) call in there, or maybe refactor the foo(f) and bar(f) calls into a foobar(f) function that does just that and the code will still be as linear. There'd be no need to add extra `if`s there nor in the refactored foobar(f) function.
> Usually it's as simple returning that error...
I'd say that it's rather "most of the time" than "usually". And exceptions give you exactly that default behaviour of propagating the error up the stack. Without having to obfuscate the logic of some intermediate code (that doesn't care about what error could happen, as long as they are propagated to the caller) with superfluous `if`s and `return`s.