Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Can't we all just agree that Maybe/Optional types are actually a great idea that generalizes all of this at minimal cost?


No. In the same way that my directions to the mall don't include "maybe take this turn" at all turns.

That is, in many (all?) imperative lists of steps for how to accomplish something, I often do not want to acknowledge that every step could fail. Rather, I would like for a failure to be something I can touch and reason with. Possibly restart from.

Why did I not take that turn? Because I need gas. Or the kids need to use the bathroom. Doesn't matter, too much. I'm the user. Give me my options at this point. (And as a real user of maps, also give me the option of "piss off for 10 minutes.")

(Yes, I like the condition/restart system of common lisp...)


> No. In the same way that my directions to the mall don't include "maybe take this turn" at all turns.

I think that's a really poor and simplistic comparison. You're content not considering every possible outcome of trying to go shopping because in the face of changes to your circumstances, you can easily come up with a new strategy and adjust your goals on the fly.

> I often do not want* to acknowledge that every step could fail.*

That's what you want, but I have often found that the demands of quality software are different. I've seen too much software end up in strange and unconsidered failure modes because it threw up at the wrong time.


I should say that my want there is local to the directions. For the trip, I definitely want them handled.

So, for the function, I want to be able to say the happy path. I would also like to be able to say what could go wrong, with advice to the user on how to proceed.


You either crash or acknowledge errors. Silently swallowing exceptions is acknowledging, the same as using something like Result.withDefault(...).


I don't think options really serve the same purpose as exceptions. If you have are just passing up None or whatever up the call stack over and over again, you probably should just be using an exception. If not, then options are fine. I use options for normal behavior (a missing file, for example) that perhaps can be corrected or handled in a different way. I throw an exception if I want to just crash the program. I rarely ever try catching exceptions, except in maybe some top level driver function. Oh and to all the programmers out there who wrote the code I'm currently dealing with: please don't use exceptions for flow control, it's a terrible terrible idea.


> please don't use exceptions for flow control

That's kind of the problem though. Exceptions are flow control.


> Exceptions are flow control.

...for exceptional events.

That means those events that are very far from the happy path and need to be recovered by unwinding down multiple function calls until a safe point to recover gracefully is reached. These are events such as failing to allocate memory.


I think those are awful to deal with errors. You have one part of the code that handles one concept and could error something. However the result of that code is then handled to some other part of the code which might deal with a local error but now you really don’t know if the error was local or occurred in the other part of the code. The second part of the code is now dealing with an error situation which it shouldn’t and you’d need to write weird code to stop it from doing that. Also you introduce behavior caused by two different context but merged due to the language “features” which, I think is much worse, because it’s not obvious that it just happened. Using exceptions otoh fixes this and parts of the code can still be completely oblivious that errors can occour.


Which is why Result and Error types exist. With those you get both the context of the error as well as making it clear that the code you are entering needs error handling to be safe. Much less of an issue than calling code that unexpectedly raises exceptions.


And they do have their uses but they are not good enough by their own. Having both exceptions, result types and maybes is a lot better to have and to use appropriately than only have one or the other.


Maybe/Option only eliminates the dreaded NullPointerException.

Result<T, ErrorT> is used in place of exceptions, much nicer IMHO.


A Result type is often more appropriate, but in general sure.


I heard related issues called boolean blindness. You drop every bit of useful error information and leave only result/no result or true/false. Want to load a file and it fails? Access rights? Parsing Error? File doesn't exist? User interrupt? Can all be summed up as an empty Optional, completely useless for any kind of automated or manual recovery or even to decide if recovery is necessary (user interrupt).


that is why in most languages with that approach you have a symmetric error type (Either for Haskell, Result for Rust etc.)


and in those langs its trivial and very common to make even more elaborate return/result types containing a very precise representation of all possible result categories.


The cost is significant: introducing one more level of indirection (for tagging) is not cheap.

However, Maybe can be implemented without tagging, see[0] for example.

[0] https://hackage.haskell.org/package/unpacked-maybe


Do you have a benchmark that measures this cost?

I'm pretty sure the cost of checking this in a static language where the tag enums range is known at compile-time is:

- 100x cheaper than cache-miss on a memory access

- and 10000x cheaper than IO which is often where those errors/results/maybe/exceptions issues arise.

I.e. irrelevant in most cases.


Sum types in general are really cool


Maybe I agree with every word you said.


So the result of division would be an Option? Option types are great, but cannot reasonably be used for all types of error conditions.




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

Search: