Live data from Hacker News

Away from Exceptions: Errors as Values

humanlytyped.hashnode.dev

111–120 of 145 posts

Re: Away from Exceptions: Errors as Values

#111
That second program must be the single worst example of exceptions ever written; a straw man if ever these was one. The key in understanding why this is the case lies in the realisation that ParseInt is a combined parser/validator, and a validation failure isn't actually an error; it's a normal, expected, situation. In C++, you'd solve this by returning std::optional, and end up with code like this:

  std::optional result = ParseInt (input, 8);
  if (!result) result = ParseInt (input);
  if (!result) result = ParseInt (input, 16);
  if (!result) throw ...;
  return *result;
Note how there's no exceptions (in ParseInt, I mean). Note how there's no error codes either. There's just no error handling needed to begin with, except right at the end, if the number is not in any of the three supported formats.

Re: Away from Exceptions: Errors as Values

#112

Earlier quoted context omitted.

> You want, on top of everything else, the computer to refuse to run your program at all, unless you explicitly handle every possible edge case? Precisely! Even better - let the IDE suggest to you all of the possible exceptions and when you're feeling lazy or are hacking away at a prototype, either let it add a "throws SomeException" to the method signature and make it someone else's problem up the call chain, or jus…

If I had to write that kind of boilerplate every time I had an artistic inspiration, I'd never ship anything! We are on far apart sides of a wide industry. I couldn't work productively in your dream language but hey, I'm happy we can have our different tools for our different needs. More power to us! :) > let the IDE suggest to you all of the possible exceptions So, programming without an IDE becomes untenable. I use…

I definitely agree that we're on the complete opposite ends of a wide spectrum of concerns and goals!

> So, programming without an IDE becomes untenable. I use a text editor. It feels like you're shifting language features into the IDE. What's the difference between the compiler doing it automatically vs the IDE doing it automatically?

I very much agree with this observation, but from the opposite side - for many development stacks and frameworks, working without an IDE feels like being a fish out of the water, since there are numerous plugins, snippets and integrations that provide intelligent suggestions, auto-completions and warnings about things that are legal within the language but are viewed as an anti-pattern.

I'd say that the difference between the two is pretty simple, just a matter of abstraction layers. Something along the lines of:

  - the business people have certain abstract goals, which they can hopefully synthesize into change requests
  - the developer has to implement these features, by thinking about everything from the high level design, to the actual code
  - the IDE takes some of the load off from the developer's shoulders, by letting them think about the problem and offering them suggestions, hints and assistance of other sorts to help in translating the requirements into code; of course, it's also useful in refactoring and maintenance as well, letting them navigate the codebase freely
  - the language server, linter, code analysis tools, plugins, AI autocomplete and anything else that the developer should want hopefully integrate within the IDE and allow using them seamlessly, to make the whole experience more streamlined
  - the compiler mostly exists as a tool to get to executable artifacts, while at the same time serving as the last line of defense against nonsensical code or illegal constructs
In essence, the IDE gives you choices and help, whereas the compiler works at a lower level and makes sure that any code (regardless of whether written by the developer with an IDE, one with a text editor or an AI plugin) is valid. In practice, however, the parts that the IDE handles are always more pleasant because of the plethora of ways to interact with it, whereas the output of a compiler oftentimes must be enhanced with additional functionality to make it more useful (for example, clicking on output to navigate to the offending code).

In my eyes, the interesting bits are where static code analysis tools and linters fit into all of this, because i think that those should be similarly closely integrated within the ecosystem of a language, instead of being seeked out separately, much like how RuboCop integrates with both Rails and JetBrains RubyMine. Our views may differ here once again, but i think that some sort of a convergence of tooling and its concerns is inevitable and as someone who uses many of the JetBrains tools (really pleasant commercial IDEs), i welcome it with open arms.

Re: Away from Exceptions: Errors as Values

#113
post #6

It's good to see so much focus on errors. They are essential when trying to build resilient systems. But our approaches are still very immature. First, to make it clear, this article appropriately points out that exceptions are still necessary and relevant. I disagree with some of the use-cases given, but it's important to recognize that exceptions should still exist in programming languages. Joe Duffy's article abou…

Author here. Thank you for the link to Midori's error model. It's on my reading list for this week.

> So we should keep the door open, and not pretend we have already solved errors.

Very much this. Even with errors as values, the approach languages like Go take makes composition difficult. I presented the Kleisli approach instead. That recovers compositionality. OCaml does something I find interesting. It makes exceptions performant by not capturing stack traces by default. But it's still too easy to forget handling the exception.

> btw, the article uses Rust, not Go, but anyway...

I actually used TypeScript. The Rust bit was meant to introduce the idea from Rust to TypeScript. It's not new in TypeScript, but it's not popular either. I have updated the article to clarify that.

Re: Away from Exceptions: Errors as Values

#114
post #100
post #96

I am writing some C++ code for a web application, and there I am handling errors via exception. There are two broad types of exceptions, one that is internal and one that needs to be reported to the user. Following is how I an handling the errors, please could you all suggest a better approach if my approach is sub-optimal designwise? // Base class HandleRequest(req, res) { try { try { post_processing(req, res) // im…

There's nothing wrong design-wise with your approach, IMO. I've seen several people (including very well-known C++ personalities) argue that exceptions should be used for X and error codes for Y, but this is just convention. C++-wise, you probably want to catch std::exception and "..." too. Finally, you said that there's two types of exceptions and only one of them is supposed to be reported to the user, but in your…

> C++-wise, you probably want to catch std::exception and "..." too.

Yeah, the "unknown_exception" in the above pseudocode represents that :)

> Finally, you said that there's two types of exceptions and only one of them is supposed to be reported to the user, but in your code you seem to report everything to the user. You should edit your message to clarify what you meant.

Yeah, only one will be reported because only one exception handler will be called. So the internal error will be reported to the user as "internal error" and some internal code that the user can report back to me if they want to. The other error is user error. So broadly there are only two categories of errors.

Re: Away from Exceptions: Errors as Values

#115
post #6

It's good to see so much focus on errors. They are essential when trying to build resilient systems. But our approaches are still very immature. First, to make it clear, this article appropriately points out that exceptions are still necessary and relevant. I disagree with some of the use-cases given, but it's important to recognize that exceptions should still exist in programming languages. Joe Duffy's article abou…

> errors are such an integral part of our programs, and have so much to do with flow control , that I don't believe thinking about errors just as values is enough Exactly. The control flow . Both errors and asynchronous programming share the quality that they don't go well with our call/return based programming model(s). You have to return something, but you either don't have anything (error) or don't have something…

Interesting. Can you give some pointers/examples?

Re: Away from Exceptions: Errors as Values

#116
post #17

Earlier quoted context omitted.

Tbh, to me the first one is easier to read. There's less jumping. But both are terrible. It should just be a bunch of if (...) { ... } else if (...) { ... } else { ...} etc. with no mutation of variables (what are all those v += 1 for?).

Those v += 1 implement the exact specification given above: 1. Parse an integer N from a string. 2. If N is NaN, fail with an error. Otherwise, increment N by 1. 3. If N is > 3, fail with an error. Otherwise, increment N by 1. 4. If steps 1-3 failed, set N to 3. 5. Increment N by 1. Those are quite strange requirements, and the resulting second code looks strange too, but... it faithfully and obviously correctly repr…

The example is strange and contrived. I couldn't torture the logic enough to demonstrate how readability breaks down with exceptions. Reading through the comments, I realise that even if the code is unreadable with exceptions, it can be rewritten to be readable. I updated the article to highlight not only readability, but also compositionality. I also tried to draw parallels with Promises (which are also monadic). I tried to target the article to intermediate programmers that may not already know most of the concerns raised in the comments, and I surely can't cover enough space on error handling without writing a book.

Thank you for the comments. I've learned more from reading the comments.

Re: Away from Exceptions: Errors as Values

#117

That second program must be the single worst example of exceptions ever written; a straw man if ever these was one. The key in understanding why this is the case lies in the realisation that ParseInt is a combined parser/validator, and a validation failure isn't actually an error ; it's a normal, expected, situation. In C++, you'd solve this by returning std::optional , and end up with code like this: std::optional r…

> There's just no error handling needed to begin with, except right at the end, if the number is not in any of the three supported formats.

I would argue that if (!result) is a form of error handling, as result being falsy indicates that the parsing failed.

Re: Away from Exceptions: Errors as Values

#118
post #105

Earlier quoted context omitted.

The main caveat is that oftentimes, checked exception handling doesn't compose well - see what kind of trouble Java gives you, for example. Recent articles I've read on effect modeling languages seems to give a more uniform construct for bringing checked exceptions in line with other control constructs.

> see what kind of trouble Java gives you, for example. I program a lot in Java, and the only trouble there is the lack of support for sum types and/or variadic type parameters in generics (i.e. to express functional interfaces that can throw an arbitrary number of checked exceptions, as a type parameter). That’s the only pain point for me and is something that could be fixed. In fact, the interplay with control stru…

[deleted]

Re: Away from Exceptions: Errors as Values

#119

> Programming with exceptions is difficult and inelegant. Learn how to handle errors better by representing them as values. Funny how exception were invented because handling errors as values was considered to be tedious. And now, more and more languages are going backward.

Yes, errors-as-values only works well with a type system which supports discriminated unions. And programming languages with such support have only recently become popular.

Re: Away from Exceptions: Errors as Values

#120
post #119

> Programming with exceptions is difficult and inelegant. Learn how to handle errors better by representing them as values. Funny how exception were invented because handling errors as values was considered to be tedious. And now, more and more languages are going backward.

Yes, errors-as-values only works well with a type system which supports discriminated unions. And programming languages with such support have only recently become popular.

OCaml is a somewhat old language with algebraic types (so including discriminated unions) yet exceptions were introduced precisely to avoid dealing with propagating errors as a values. I agree with your point, but would argue that even with sum types, propagating errors is tedious and there's a case for using exception.

I wonder if another reason why errors as value are making a come back is because of the asynchronous programming style which is becoming quite pervasive, and doesn't play well with exceptions.

Post reply on HN