News for hackers. Stuff that matters.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by mhh__ on Friday February 19, 2021 @04:58AM (#26191347)
The only system I think should completely go is Exceptions except in the case of termination or absolutely catastrophic failure - this isn't really about programming but rather that the implementation is a total pain, the compiler struggles to optimize them, and even better they make quite a few safety analyses like borrow checking very difficult because the control flow graph basically explodes when you start considering exceptional control flow - even on a basic block
Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Friday February 19, 2021 @05:27AM (#26191515)
In terms of control flow, this:

  try {
    someCall();
  } catch (ErrorICanHandle err) {
    //handle
  }
perfectly equivalent to this:

  err = someCall();
  if canHandle(err) {
    //do something
  } else {
    return err
  }
I don't see why so many people think exceptions make code harder to analyze. In my opinion, it is errors themselves that make code hard to analyze, regardless of implementation strategy.

The only difference between exceptions and error returns/error codes is in human readability: one makes the bubbling behavior explicit, which clutters the code but makes it obvious; the other makes the bubbling behavior implicit, which keeps the code cleaner, but also less obvious.

After writing professionally in both languages with Exceptions (Java/C#/Python) and in Go, I much prefer Exceptions to error values/codes, but I can appreciate that it may be different in other domains or for other people.

Re:Where Everything Went Wrong: Error Handling and Error Mes... by xpressvideoz on Friday February 19, 2021 @05:41AM (#26191622)
I mean, Go's error handling is one of the worst implementations of the "error code" idea, so it is a bit unfair to disregard the idea just because one particular implementation is bad. You should try Rust or Swift, at least the error handling part, to fully appreciate what a good error code implementation could be.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Friday February 19, 2021 @10:12AM (#26193992)
I'd love to when I get a chance. I did see that Rust seems to favor a ? macro that seems to make error codes behave essentially like exceptions, so I am curious to try it out at some point and see if that ends up being any different from exceptions in practice.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by sensitive-ears on Friday February 19, 2021 @07:11PM (#26199818)
The "?" operator doesn't turn them into exceptions, it's just a "return-early-if-error" shortcut. The main difference being that the caller still has to handle the error of a function using "?". (even if it's by punting further up the call stack with more "?", which you could argue is exactly how exceptions work, but it is at least explicit in what functions can fail and which don't)
Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Monday February 22, 2021 @02:52PM (#26229648)
> even if it's by punting further up the call stack with more "?"

Yes, this is exactly what I meant.

> it is at least explicit in what functions can fail and which don't

So is Java with exceptions (at least as long as developers are even slightly disciplined).

Re:Where Everything Went Wrong: Error Handling and Error Mes... by sensitive-ears on Monday March 01, 2021 @06:12PM (#26309797)
Yeah, I think java had the right idea, but the ergonomics didn't turn out great, so they didn't get the buy in they'd hoped for. Having both checked and unchecked exceptions (ie, NPEs) meant it doesn't offer the same safety guarantees as something like rust does. The implementation of exceptions can also have some implications for the runtime, whereas the enum method of error handling allows you to run in very minimal environments and easily see what's going on. (Exceptions could be implemented this way under the hood, but they often aren't)
Re:Where Everything Went Wrong: Error Handling and Error Mes... by BlackFly on Friday February 19, 2021 @12:48PM (#26195720)
Exceptions are harder to analyze because they create scopes from which you are already "handling" errors, but if you add code to the scope that throws a new error of that type your handler may not actually be able to handle it.

  try {
    someCall();
    someOtherCall();
  } catch (ErrorType err) {
    //handle
  }
Which method throws? If they both throw ErrorType but one of them cannot be handled, then you have to put additional logic into the catch and rethrow.

This is a common source of faulty error handling.

Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Friday February 19, 2021 @01:04PM (#26195925)
Yes, this is an easier mistake to make with exceptions than with error values. Still, the fix is to do exactly the same thing as in the error values case:

  try {
    someCall()
  } catch (ErrorType err) {
    //handle one way
  }
  try {
    someOtherCall()
  } catch (ErrorType err) {
    //handle another way
  }
It's no less verbose than the error values way, though again, it is easier to make the mistake in the first place.

I'm not trying to claim that exceptions are ultimately better than error values, just that the difference isn't so much "non-local control flow" as it is explicitness vs implicitness. Exceptions are implicit, error codes are explicit. Both have benefits and drawbacks.

Re:Where Everything Went Wrong: Error Handling and Error Mes... by gmfawcett on Friday February 19, 2021 @10:44AM (#26194313)
Exceptions make code harder to analyze because they implement non-local control flow. Your two example statements aren't really equivalent. `ErrorICanHandle` may be a kind of exception that the `someCall` function has no idea about whatsoever -- it could be an exception propagated from much farther down the call stack -- while your if statement assumes the error was explicitly returned from the function.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Friday February 19, 2021 @11:23AM (#26194729)
In an exception-based language, assuming all functions potentially throw, code like this:

  someCall()
is equivalent to code in a language without exceptions that looks like this:

  err = someCall()
  if err {
    return err
  }
(ignoring for a moment non-error returns, which don't change the point significantly)

Having functions that are guaranteed not to throw / return errors doesn't significantly change this shape.

So basically it's no more non-local than the code you'll end up writing with error codes, in most cases, any way. The only difference is implicit vs explicit.

> `ErrorICanHandle` may be a kind of exception that the `someCall` function has no idea about whatsoever -- it could be an exception propagated from much farther down the call stack -- while your if statement assumes the error was explicitly returned from the function.

someCall doesn't need to know about the meaning of the error in either case. It only needs to propagate any error it receives from any functions it calls (that it can't handle itself). Think about the function I wrote myself: did it need to know the precise type of err? Nope - it just needed to know that it implements some kind of Error interface (which may be as simple as being a negative number, like a POSIX error code).

Edit to give a more complete example:

  extern void bar();
  void foo() {
    bar()
    doOtherStuff()
  }
  void someCall() {
    foo()
    doMoreStuff()
  }
  void main() {
    try {
      someCall()
      doFinalStuff()
    } catch (BarSpecificException e) {
      doErrorStuff()
    }
  }
Is equivalent to this code:

  extern err bar()
  err foo() {
    err = bar()
    if err {
      return err
    }
    err = doOtherStuff()
    if err {
      return err
    }
  }
  void someCall() {
    err = foo()
    if err {
      return err
    }
    err = doMoreStuff()
    if err {
      return err
    }
  }
  err main() {
    err = someCall()
    if err is BarSpecificException  {      
      err = doErrorStuff()
      if err {
         return err
      }
    } else if err {
      return err
    }
    err = doFinalStuff()
    
    if err is BarSpecificException  {      
      err = doErrorStuff()
      if err {
         return err
      }
    } else if err {
      return err
    }
  }
If I ask you in the second piece of code what will be executed after the call to foo(), is it any easier to reply than in the first version? Personally, I don't believe so.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by _ek94 on Friday February 19, 2021 @02:43PM (#26197159)
For those of us who don’t like exceptions I think the concern is more that the exception might not be caught right there, so an exception may potentially transfer control to an arbitrary point above the current function in the stack.
Re:Where Everything Went Wrong: Error Handling and Error Mes... by metreo on Friday February 19, 2021 @06:49AM (#26192112)
this issue is knowing whether you are catching the right errors
Re:Where Everything Went Wrong: Error Handling and Error Mes... by simiones on Friday February 19, 2021 @01:07PM (#26195957)
You have the same problem with error codes, don't you?

The bigger difference is knowing whether you should expect errors at all - with exceptions, you can forget to handle an error and you may screw up an important assumption, like not unlocking a Mutex if an Exception is raised. With error codes, you have the opposite problem: you may forget to check for an error, and continue to execute in a bad state.

Re:Where Everything Went Wrong: Error Handling and Error Mes... by skinkestek on Friday February 19, 2021 @05:31AM (#26191544)
> the compiler struggles to optimize them,

Nitpick: I'd say if you need the compiler to optimize exception handling you are using them wrong.

Exceptions are for exceptional circumstances.

(if you mean that exceptions mess up optimization of surrounding code that could be a bigger deal but I won't accept that without pointers to benchmarks$

Re:Where Everything Went Wrong: Error Handling and Error Mes... by mhh__ on Saturday February 20, 2021 @01:11AM (#26202055)
Exceptions force a less efficient ABI, for example - take a look at unique_ptr, it should be in a register but it's not.