4 ms·
I feel a lot of that has to do with Googlers not daring to question the famous authors, and the same authors seem to have been asleep for the last three decades
by papito 4y ago
I feel a lot of that has to do with Googlers not daring to question the famous authors, and the same authors seem to have been asleep for the last three decades in terms of modern programming language developments. I geared up to learn Go one day, got the book and everything, and after just a few hours of trying to write and rewrite error-handling code, I was wondering how this ever got out of the Request for Proposal stage.
Oh, you have to manually chain your errors and no you don't get stack traces out of the box. If you want to to know where the error message is, I don't know, guess?
It's insane.
Exceptions happened precisely because manual error-handling was messy and did not scale, but suddenly it's The Way.
- leetrout 4y agoComing from Python I appreciated that there were no exceptions. I much prefer the explicit error returns instead of exceptions being used for flow control.
- metaltyphoon 4y agoBut thats the programmer’s fault. You shouldn’t use exceptions for flow control.
- leetrout 4y agoTo an extent, sure, and that can apply arbitrarily to lots of things. The Python community, by and large, embraces "easier to ask forgiveness than permission" and some features in the standard library use exceptions for their flow control. It's much more likely to run into overuse of exceptions in Python than not.
- kaba0 4y agoIt’s not explicit error returns any more than C code with all those larger than 0 checks. You will leave it out or get angry at the line noise and will miss(handle) an important error case and will have a bad program and you won’t know about that until it’s too late. A loud exception is way better.
- candiddevmike 4y agoYou do get stack traces out of the box? Exceptions trigger stack traces, or you can PrintStack
- thequux 4y agoExceptions reflect the realization that the proper place to handle an error is generally not where the error itself occurs. The problem with exceptions (and error returns, for that matter) is that the best place to handle an error is also not the same as the best place to decide how to handle the error. So far, the only programming environment I've seen that makes a three-way distinction between raising, recovering, and deciding how to recover from an error is Common Lisp with its condition system[1]. However, I've successfully implemented the idea in Java using exceptions as the non-local control flow primitive, and in C using setjmp/longjmp. [1]: https://lispcookbook.github.io/cl-cookbook/error_handling.html https://lispcookbook.github.io/cl-cookbook/error_handling.ht...
- XorNot 4y ago> the best place to handle an error is also not the same as the best place to decide how to handle the error. I'm not sure I follow the distinction here, or at least why it would be important? i.e. if I parse "decide how to handle the error" as catching the exception, where I handle it is surely basically anywhere since I'm not restricted in calling into other code to do so.
- lmz 4y agoCommon Lisp exceptions are resumable which is the main difference between it and more common languages like Java and C++. e.g. "Decide" can also include deciding to retry the operation with different inputs.
- kajaktum 4y agoThe answer to error handling is ADT like Result<T, E> or Maybe<T>. The problem with old exception is that it is not part of the function signature. If a function says it accept a key and return a value; why should I expect it to return NullPointerException?
- papito 4y agoAnd what if an underlying library returns the exception? All the opposition to exceptions I have encountered are theoretical, and I have never seen it work that way in practice. What signature do you get from "if err := myFunction()"? It's still just a generic error object, possibly a string. You still have to write a handler for it. Why do it every time? I have a web application. There is a SQL query that produced no results for an object. I throw an ObjectNotFoundException. It results in an HTTP 404, producing a web page or a JSON response, depending on the request location, and I handle it all once.
- kajaktum 4y ago>What signature do you get from "if err := myFunction()"? You provided an example from Go which is almost like an exception. And I think it is bad. You have a function that returns....something?? Instead, if you have something like Result<T,E>, it tells you exactly what you're getting. ``` value = myFunction(); match value { Ok(v) => // whatever Err(MalformedSQL) => // oh something with sql happened? Err(UserNotFound) => // oh can't find user? ``` Then you get "BZZZZZ, compile error. You forgot to check for another variant of the Error (ThirdPartyLibraryError)" which is a million time better than catch-all exception handling because you are afraid something might get out of this function call. If you do want to have a catch-all exception handling, then that is also possible by using "_ => {}" which is explicit. So just glancing at a piece of code, you know you have handled ALL the possible error cases. >I have a web application. There is a SQL query that produced no results for an object. I throw an ObjectNotFoundException. It results in an HTTP 404, producing a web page or a JSON response, depending on the request location, and I handle it all once. Also possible in axum. You have an error enum and then you implement a trait that converts said enum into an HTTP response. So your code looks something like ``` value = myFunction()?; ``` and if there's any error it will automagically turned into the appropriate response. So I get all the ease of exception but the type signature is not lying to me. If I forgot to implement a conversion from some new error to HTTP I get compile time error.