3 ms·
Bad 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 silen
by layoutIfNeeded 8y ago
Bad 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.
- munk-a 8y agoIf you have something that might be nil earlier, then some stuff happens and you know it definitely isn't nil anymore then why is it still in an option, isn't the logical path split that diverted those "might be nil" cases where a case handling the nil would peel off leaving you not with a maybe but with a real value? I think that sort of pattern is a bad code smell, you are propagating doubt where there is none leading to misleading code that has assumptions that differ from what's on the page - obviously I don't have a real example in front of me so there may be good allowances for understanding but I don't find your core premise to be sound and I feel like any counter example would have a lot of work to do to appear convincing.
- whateveracct 8y ago> 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. Nope that's bad programming. If you know the Maybe is always there, PROVE IT! Step 1 to proving anything: Make a proposition. In other words, swap out `Maybe a` for `a`. Then prove it upstream. Maybe at some point you want to crash, but you definitely want to do it at the boundary and not within your function. Writing a function that takes a Maybe but assumes it's there just seems like asking to break things. > a toy example would be that A and B can both be nil, but it also holds that (A == nil) == (B == nil). Isn't this just `Maybe (A, B)`? If you have both sums and products in your type system, these sorts of situations go away. A more complicated example: You have A and B and A, B, or both are non-null. But both are never null at the same time. The way to lift this invariant into your type system (i.e. make a proposition about your program) is: data IOr a b = ILeft a | IRight b | IBoth a b
- layoutIfNeeded 8y agoLet’s say Math.sqrt returns Optional because we haven’t invented complex numbers yet. You’re given an integer between 1 and 10, you square it, and then take the square root. The result is an Optional, but it’s provably non-nil. On the other hand, you can’t prove this within the type system. (unless we’re talking about Idris or coq or whatever exotic crap that noone’s using outside of academia) >If you have both sums and products in your type system, these sorts of situations go away. Like I said, it’s a toy example. If you need a different example, here’s one: A, B, C and D are Optionals, but at most two of them are nil.
- Dylan16807 8y agoIf you depend on the square root existing, why not have a (very short) positive_sqrt function? > A, B, C and D are Optionals, but at most two of them are nil. That sounds like something that's quite fragile and should either be wrapped up in its own type or not depended on.
- whateveracct 8y ago