4 ms·
Sorry, that's still not a reason to use bools instead of "errors" and An error should by default be considered non-recoverable, to be returned when somethi
by ReleaseCandidat 2y ago
Sorry, that's still not a reason to use bools instead of "errors" and
An error should by default be considered non-recoverable, to be returned when something goes very wrong. Semantically, a table not existing isn't really an error, it's something you expect to happen all the time.
remains a bad idea.
Seems like the reason for this article is the reaction to that one: https://www.dolthub.com/blog/2024-05-10-ok-considered-harmful/ https://www.dolthub.com/blog/2024-05-10-ok-considered-harmfu...
- LoganDark 2y agoThat quote conflates errors and exceptions. An error is an unsuccessful result. An exception, however, precludes any result at all. Sometimes they are the same, but in many cases they are different. Asking to retrieve a table that doesn't exist is an error, because the answer is that there is no table; the operation was unsuccessful. There failed to be retrieved any table, but as the table always could have either existed or not, this is not an exceptional case. Nothing went wrong: you simply asked to retrieve a table and no table was found, so you get that back as an error. However, trying to perform a table operation on that unsuccessful result generates an exception, because you violated a contract: you can't operate on something that doesn't exist. Sure, you can operate on the representation of nonexistence (that is, null), but you attempted to operate on a table and you don't have one. The computation stops prematurely with an exception because the operation expects the table to necessarily exist. There is no unsuccessful result to be returned because the operation didn't even make it to the point of failing; the performance itself of the operation failed. The operation is entirely invalid and returning any result would be incorrect. At least, that is my personal understanding of the terms. For example, most things in Rust are errors and not exceptions, because exceptions (panics) generally terminate the thread, or abort the process, depending on user preference or runtime environment. Anything that isn't fatally unrecoverable deserves to be an error - in other words, a `Result::Err` - which can be handled by the caller, as opposed to panics, which are not guaranteed to be catchable (unwinding is not a required part of the language, it is an optional convenience). Most failures in JavaScript are exceptions, because you are not made to check anything, and everything is dynamically typed, so if you make an assumption that isn't true, an exception has to be raised to stop you. Luckily, there is try/catch. It can also be difficult to represent errors without exceptions, you instead have things called "error states" which are basically certain non-errors being treated as errors by user code, when either that result is undesired even if perfectly normal, or that result is the only/easiest way for the error to be reported by the source. Anyway, my point is that the article probably means to use the term exception and say that a boolean is better than an exception when the error isn't an exceptional case. And in that case I would agree. In Rust, I don't want my program to crash when I ask for a nonexistent table - I only want that to happen later if I decide that the table's nonexistence is a fatal error in the context of the whole thread.
- randomdata 2y ago> Sometimes they are the same Your understanding otherwise seems on point, but I'm not sure they can ever be the same. An exception is the representation of programmer fault. An error, on the other hand, is the representation of faults outside of the programmer's control. Like you point out, operating on a missing table is a mistake made by the programmer. This fault could have been avoided when the code was written. The table not being there is not within the control of the developer (with some assumptions of what table is meant to mean here) and no amount of perfect coding could have avoided the situation. > Most failures in JavaScript are exceptions Idiomatic Javascript suggests handling errors using its exception handling mechanism, but the payload is still error in nature. In fact, the base object the idioms suggest you use to hold error data, passed using the exception handler, is literally called Error. Javascript may be confused by having no official "Exception" type. Although arguably it does not need one as you can simply throw a string, which is all you need for an exception. The exception handler will tack on the rest of the information you need to know automatically. Java takes a different opinion, though, having two different, albeit poorly named, built-in classes for errors (Exception) and exceptions (RuntimeException).
- tsimionescu 2y agoYou are explaining the diferrence between error results and panics in Rust, and maybe this also applies to Go. But this is very much not how exceptions (a word these languages don't even use) are understood in languages which have them. In Java, C#, C++, for example, exceptions are meant for any situation where the operation you asked for can't be completed successfully, for whatever reason. The most common example is IOException: if you asked to read 200 bytes from a socket, but the connection got interrupted after 100 bytes, that's an IOException. This would not be appropriate as a panic in Go or Rust, for a comparison of the difference in philosophy.
- spockz 2y agoI like your example. Although I do remember that there are also read operations where you ask for 200 bytes and you can get 100 back. And it is up to the caller to check for this. Otoh, if the socket is closed you indeed get a socket closed exception. But that is because the docker was closed while reading. What is the rust behaviour in this case?
- zachmu 2y agoAgree to disagree here. And yes, this article is a follow-up to the linked one. The last section of the blog has a discussion of aesthetic and philosophical concerns around using errors for control flow. I'm against it, for the reasons I provide. YMMV.
- sethammons 2y agoYour take away in the "ok is harmful" article is incorrect. There is nothing wrong with "ok" - your problem is with shadowing variables. The better organized code couldn't use shadowing. Your example of moving the ok-checks to the end makes as much sense as moving all your err checks to the bottom. If you overwrite a shadow variable before using the value, of course that's bad. The real takeaway should be that one must always be careful with shadow variables and generally use them as immediately as possible.
- zachmu 2y agoMy whole point is that following the convention basically guarantees shadowing in many contexts. That's bad.
- sethammons 2y agoDo you also do err, err2, someOtherErr? Shadowing is the exact same situation. Errors are just values
- zachmu 2y agoYes, it is the same situation. No, we don't tend to use unique names for errors. The idiom is just too strong. This is somewhat mitigated by consistent consecutive error handling, meaning you always immediately dispatch an error on the line after assigning it. Every time we have had bugs because of this, it's because someone tried to be clever and delay handling an error until slightly later (like at the end of an if else chain where each branch might have had an error).
- kiitos 2y ago
- aaomidi 2y agoI agree with you. The go standard library uses sentinel errors. ErrNotFound is actually good to use, because otherwise, a `Get` call can end up returning `nil, nil` (*Value, error). Which is just bad.
- trustno2 2y agoGo returns bool for map access, not errors...