Hacker Newsnew | past | comments | ask | show | jobs | submit | xerokimo's commentslogin

> Hiding heap allocations seems like it make it harder to avoid resource leaks!

Because types come in constructor / destructor pairs. When creating variables, you're forced to invoke a constructor, and when an the object's lifetime ends, the compiler will insert a destructor call for you. If you allocate on construction and de-allocate on destruction, it'll be very hard for the leak to happen because you can't forget to call the destructor


RAISI is always wrong because the whole advantage of the try block is to write a unit of code as if it can't fail so that what said unit is intended to do if no errors occur is very local.

If you really want to handle an error coming from a single operation, you can create a new function, or immediately invoke a lambda. This would remove the need break RAII and making your class more brittle to use.

You can be exhaustive with try/catch if you're willing to lose some information, whether that's catching a base exception, or use the catch all block.

If you know what all the base classes your program throws, you can centralize your catch all and recover some information using a Lippincott function.

I've done my own exploring in the past with the thought experiment of, what would a codebase which only uses exceptions for error handling look like, and can you reason with it? And I concluded you can, there's just a different mentality of how you look at your code.


An error to me can be as simple as any time I need to write a range check so I don't index out of bounds, that very act of range checking is an error check. In other words, any time you require a runtime check to prevent an operation that would otherwise be erroneous is an error

Philosophically, I don't differentiate how you represent errors, they are all errors in the end. You can use unchecked exceptions, results, checked exceptions, error codes, whatever. I will abide by rules set in the code base's guidelines, and I do have my preferences (unchecked exceptions), and I'll also accept using one or the other for practical reasons (performance, or binary overhead), but I will never argue that it is absolutely best that one error handling scheme is reserved for uses ABC, and the other best for EFG.

A bug is one of two things, writing code that is erroneous despite having knowledge at compile time that it can't happen such as, indexing into an array of known bounds with inputs that are known to never be out of bounds. Typically where asserts are used. You can promote these types of bugs to errors if it doesn't harm your system stability, and they often are in order to avoid crashing. The other definition of a bug is just your program entering in an unforseen state.

I dislike using the words expected, unexpected, and such for error handling unless you're talking about c++'s std::expected, because no one can agree what they mean, hence to me are useless definitions when talking about error handling. While the same can be said about definitions of errors and bugs, the practical uses tend to converge to an agreement on whether something is an error, or a bug.

From years of observing error handling:

- Most times I see people talk about it, from what I interpret from what people say, seems to have an emphasis on what operations can error out, rather than emphasizing what the state of your program should be when a unit of code errors out, which I believe should be more emphasized.

I typically define a unit of code as a function because that's how most things already work and is easier to reason about. In other words, stop focusing on individual failures of the callers, rather treat the entirety of the callee as a failure. This reduces your function to usually only have 2 states, what should your program state be when everything succeeds, and what should it be when it fails.

That's how you can interpret a lot of value based error handling functions already no matter how many operations can fail. With exceptions it means that, either your whole function must be in a try/catch block, or it doesn't have one at all.

- Value based error handling seems to re-invent some forms of unchecked exception features, with very good reasons, leading me to believe that they are on the same sides of the coin where given enough language and tooling support, they converge to the exact same thing.

- I do think it's better to encode preconditions in some way visible to callers that's not just through documentation. If you're using types, which is my preferred way, known as dependent types. I'm not too familiar with them, but apparently requires a proof solver for it to work entirely at compile time. I wouldn't mind them turning into runtime checks, and if you have overloading enabled, allows runtime checks to mostly occur once, at construction time.


That's being idiomatic to a language, not being semantically correct.

Result, Either, Expected, all have different names, but their semantics are all the same.

Panic and Recover may not be idiomatically used the same way Exceptions are used in other languages, but they share the exact same semantics of implicitly bailing out potentially multiple functions, going up the call stack until we Catch, or well Recover.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: