5 ms·
Better than nothing, but worse than having a type system than disallows the exception it in the first place.
by yxhuvud 8y ago
Better than nothing, but worse than having a type system than disallows the exception it in the first place.
- tantalor 8y agoMaybe or optional types don't really help because your "get value" functions also throw exceptions, or have undefined behavior, if the value doesn't exist. Examples: https://en.cppreference.com/w/cpp/utility/optional/value https://en.cppreference.com/w/cpp/utility/optional/value https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html#get-- https://docs.oracle.com/javase/8/docs/api/java/util/Optional...
- lmm 8y agoNonsense. Obviously if you make every single value in your program with an option then you have the same problem as if your language had null. But the difference is that in a language that has optional types, it becomes practical to have values that aren't optional. And for values that really are meant to be optional, you don't use the "get value" functions (which really shouldn't exist at all), you use functions that handle both cases.
- the_af 8y agoYou are not supposed to do a get on an Option type; it's an antipattern. You're supposed to map over them, and when you really need the value, to pattern match the Some and Nothing cases, which cannot blow up in your face.
- layoutIfNeeded 8y agoBad advice. If you're given an Optional that's guaranteed to have a value, it's better to call get and blow up if someone violates this invariant than to silently ignore the invalid input via pattern matching or optional chaining. Crashing is better than silently ignoring logic errors. Of course, one could ask what's the point of an Optional that's guaranteed to be non-nil. Well, it often happens that there's some relationship between a set of values that's hard/awkward to express via the type system. E.g. a toy example would be that A and B can both be nil, but it also holds that (A == nil) == (B == nil).
- the_af 8y agoI don't know what to tell you. It's how they are meant to be used [0], it's not some advice I made up. It's the whole point of using optionals, otherwise you're left with a verbose way of saying "this may be null". There are unsafe methods to extract the value in those rare occasions when you absolutely know it's there, but you seldom need them. You're supposed to map and pattern match. Neither is silent, so I don't understand what you meant. > Crashing is better than silently ignoring logic errors. Map and pattern matching are not silent. ---- [0] https://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html https://www.oracle.com/technetwork/articles/java/java8-optio... (search for "this is not the recommended way of using Optional", and bear in mind this was for Java 8, which doesn't have pattern matching like Scala or an ML language)
- layoutIfNeeded 8y ago>Map and pattern matching are not silent. I'm writing a complicated algorithm and am at a point where I know for certain that a given value must be non-nil. Sometimes it can be nil, but at this point it's provably non-nil (E.g. at the end of Dijkstra's algorithm every entry in the distance vector must be non-nil - assuming the graph is connected). The type system can't prove this, but I know that it's non-nil at this point. So, when I access it, I want the program to fail loud and clear, because it means that I've messed up somewhere. Handling it via map or pattern matching makes no sense here. What would you write in the nil case of the pattern matching anyway? return -1? That's absurd. abort()? That's exactly what get() does.
- the_af 8y agoThere are unsafe escape hatches for the rare cases where you do need them, but they aren't recommended. It's not the idiomatic usage, which is why the original post in this thread saying "it'll blow up when I do Optional.get" is mistaken. If it's provably non-nil, use get. But you must provide the proof, and your first reaction must always be "I'm not sure I can assume this". > What would you write in the nil case of the pattern matching anyway? return -1? That's absurd. Yes, it's absurd. You don't return this type of sentinel values in statically typed languages with optional types. If you don't need to discriminate the error, sometimes returning Nothing will suffice. If you need the error, you can use an Either type (where traditionally Left is used for the error). Again, this isn't something I made up. It's how Optionals are used. I suggest you read the link I posted above.
- fwip 8y agoThe distinction here is that those implementations aren't a type system, they are types in the existing c++/java type system. In many languages that support Optional types as first-class citizens, it is a compile-time error to ignore the fact that it may be null/none. Your code must deal with this, and you won't have any surprise exceptions, even if you are lazy.
- Rebelgecko 8y agoWhich languages? In the languages that I'm somewhat familiar that support Optionals (Kotlin and Swift) you can still get NPEs, there's just some nice syntax that makes it harder to do accidentally (e.g. by using !! or ! on a null/nil optional)
- UK-Al05 8y agoMost ML(Ocaml) languages I use will tell you if you haven't handled all the cases.
- jayshua 8y agoElm is an example of a language that literally can not produce NPEs. I use Rust on a daily basis and while it "technically" can produce one, I've never seen one.
- ajanuary 8y agoThe idiomatic way to use optional types is pattern matching (e.g. when in kotlin, switch in Swift). These pattern matching constructs tend to have a requirement that your cases are exhaustive. This makes it impossible to miss the None case. However, they also tend to provide escape hatches for getting at the type directly, which defeats that and will still let you NPE.
- timw4mail 8y agoRust does not allow null values without resorting to unsafe code.
- cesarb 8y ago
- whateveracct 8y ago> Maybe or optional types don't really help because your "get value" functions also throw exceptions, or have undefined behavior, if the value doesn't exist. That's a big leap. That's like saying Haskell isn't pure because of unsafePerformIO. You still get nice static checks with Maybes. If people cheat with fromJust, it's at least obvious they are cheating. Both big and obvious improvements over null :)