5 ms·
Option type was my favourite solution to this until i was introduced to nil punning. I still haven’t found a more pragmatic approach. Some languages allow you
by CraigJPerry 4y ago
Option type was my favourite solution to this until i was introduced to nil punning. I still haven’t found a more pragmatic approach.
Some languages allow you to say “this can never be null”, and in general, i find that really helpful and ergonomic but there’s cases where it’s not practical and you have to permit null and at that point, you’ve sunk the boat.
Strict non-nullable with Option types has been moved to 2nd place solution since i experienced nil punning.
Treat nil as a value, like in this article’s example of the array being terminated by nil. Don’t make it an exception to compare against nil. But don’t ascribe any other meaning to the value - that means no matter the context, nil can semantically fit your use case.
It’s better than option primarily because it means a lot less code. You delete all “is this value present?” type code from your codebase because encountering nil in your happy path is rendered harmless.
Very nice.
- HNHatesUsers 4y ago
- feanaro 4y agoThis sounds like an invitation for logic bugs and corruption. > It’s better than option primarily because it means a lot less code. Option doesn't need any extra code for checking the presence of a value when it's done right. In Rust, you just place a ? sigil at the end of the option expression. In Haskell, you just use the do syntax where val <- optional will assign the value to `val` if `optional` is some value rather that none, and it will exit the do block otherwise.
- CraigJPerry 4y ago>> Option doesn't need any extra code Ahh, those are both logic errors in your code. You do need the extra code to fix your errors here: >> In Rust, you just place a ? sigil at the end That changes the behaviour to bubble up that there was no value, the caller has been delegated responsibility and further processing has stopped at this point. Instead to accurately implement the required behaviour and replicate the nil punning logic, you’d need ? to behave in such a way that it inserts a suitable “empty” value for whatever type the option is guarding. So if this was an optional collection for example, the ? would need to figure out what type of collection then how to get an empty one to provide here (and you’d probably want that to be a singleton immutable collection, otherwise you’d be risking introducing logic bugs). In practice, you’d instead write code to provide that empty collection at the call site. At this point you’ve rendered the Option wrapper pointless though. It’s the exact same story for your Haskell example. You’ve given a different behaviour which is of course, a logic bug.
- feanaro 4y ago> to behave in such a way that it inserts a suitable “empty” value for whatever type the option is guarding. Some types have no suitable "empty" value. It is dangerous to assume you can always find such a value. In essence, when you're expecting that such a value exists, you're implicitly relying on your type being a suitable monoid. That's fine when you're expecting this and when it is actually a monoid, but not all types are. > In practice, you’d instead write code to provide that empty collection at the call site. Not all types can be modelled as collections. This is the same problem as above. What I'd actually do is either: 1. Fail the parent operation by again using `?`, or 2. Provide a suitable default/"empty" type, if it is possible to continue. It's very important that such a decision is explicit on a case-by-case basis, and this is what `?` allows you to easily do without much fluff or noise. > At this point you’ve rendered the Option wrapper pointless though. How was it useless? It allowed us to safely write a procedure as if the value existed and otherwise cheaply signal failure to the caller. The caller can then repeat the same process. What's important is that the procedure stands on its own and is safe out of the box. It clearly says that it can fail (by returning an option) and we know exactly when it has failed and when it has not. > You’ve given a different behaviour which is of course, a logic bug. I don't see where the bug is?
- CraigJPerry 4y ago>> I don't see where the bug is? That appears to be a willful decision on your part i think :-) A'dieu and all the best
- divingdragon 4y agoI would rather have my program hard crash on unexpected null than to have it silently ignore potential logic errors. I have never used a language with nil punning, but to me Option<T> still feels to be the best approach.
- CraigJPerry 4y agoIt’s a small example and won’t claim it’s life changing but if you get a spare hour some time, i’d definitely vote for broadening experience horizons and playing with an example. Specifically to your point about the hard crash, I’m interpreting this as meaning “i want the programmer to be told they’re mistaken”, if I’ve got that right, you’ll be pleasantly surprised.
- happytoexplain 4y ago>encountering nil in your happy path is rendered harmless. Only if by "harmless", you mean "creates a bug later rather than a crash now", as compared to traditional null handling. But Optional has neither problem. >It’s better than option primarily because it means a lot less code. You delete all “is this value present?” type code from your codebase "It's better because it's less code" is a pretty big red flag if that's the only advantage. Especially when "less code" means `foo.bar` instead of `foo?.bar`, or `if foo.bar` instead of `if foo?.bar == true` (and even in the second example, if you're touching `foo` multiple times, you can unwrap it one time with `if let` instead).
- happytoexplain 4y ago>Don’t make it an exception to compare against nil. But don’t ascribe any other meaning to the value If comparing against nil does not fail, you are ascribing the value of "false" to it. If it works in every use case, you are ascribing an arbitrary value to it in every use case.
- rocqua 4y agoMost 'optional' types have a 'map' function that allows you to apply a function to it, if it isn't None. That seems like a decent middle ground, though maybe less useful when writing a few short functions.
- LAC-Tech 4y agoBig fan of options, but I am curious to see some examples of how it's cleaner, even in pseudo code.
- jhatemyjob 4y agoGlad to read an opinion from someone who can think for themselves. Rust/Swift propaganda can be quite effective. These languages solve fake problems.