5 ms·
I find Maybe a bad idea. It forces me to write denormalized code when I know that something is not NULL. It's not possible to specify this knowledge as a data s
by jstimpfle 8y ago
I find Maybe a bad idea. It forces me to write denormalized code when I know that something is not NULL. It's not possible to specify this knowledge as a data structure since data structures are static but context is dynamic. I much prefer the simple NULL sentinel that blows up like an assertion when I made a mistake. That said, there's not very often a need for NULL at all if you structure the code correctly.
- funciton 8y ago> I much prefer the simple NULL sentinel that blows up like an assertion when I made a mistake. Haskell, for instance, has the 'fromJust :: Maybe A -> A' function that allows you to do just that. It unpacks the Maybe typed value and throws a runtime error if it fails.
- jstimpfle 8y agoYes. Most Haskellers will sneer at it, while personally I think it's the right thing to do because it conveys the programmer's ideas about invariants. But syntactically an explicit unwrapping function is still a lot of noise. Simple null pointers as we have in C, with an unmapped segment at address zero so that it throws a segmentation fault, are much better.
- cultus 8y agoI haven't drank all my coffee yet this morning, but are you saying that throwing a segfault can be a good thing? Either you unwrap the Option, or you have to remember to do an manual null check. The second option is more verbose.
- jstimpfle 8y ago> but are you saying that throwing a segfault can be a good thing? Sure, what's bad about it? A logic bug was detected, so the program should be terminated. Or how do you intend to continue? Segfault is not so different from what happens if you do "fromJust Nothing" in Haskell or get a NullPointerException in Java. You can even write a handler for the segfault, but I guess that's rarely a good idea.
- lmm 8y ago> Sure, what's bad about it? A logic bug was detected, so the program should be terminated. Or how do you intend to continue? I intend to not have the logic bug in the first place, by encoding my invariants in the type system. If you "know" that the value is present rather than absent, you must have a reason for knowing it, so explain that reason to the compiler. E.g. maybe you took the first element of a list value that you know is non-empty - so maybe you need to change the type of that value to a non-empty list type. That way the compiler can check your reasoning for you, and will catch the cases where you thought you "knew" but were actually wrong.
- jstimpfle 8y ago> by encoding my invariants in the type system the way I program that is nothing but a pipe dream. > If you "know" that the value is present rather than absent, you must have a reason for knowing it, so explain that reason to the compiler. I might know that it exists for example because it is computed in a post-processing step after a first stage but before a second stage. So it exists in the second stage but not in the first. Relying on global data (which I won't give up) makes it practically impossible to encode that the data is not there in the first stage. And that's not a problem at all. I simply don't access that data table in the first stage... Trying to explain my processing strategy to a compiler would amount to headaches and no benefits.
- lmm 8y ago> I might know that it exists for example because it is computed in a post-processing step after a first stage but before a second stage. So it exists in the second stage but not in the first. So the first stage could create a handle to it, or even just a phantom "witness" that you treat as proof that the value is present. > And that's not a problem at all. I simply don't access that data table in the first stage... Trying to explain my processing strategy to a compiler would amount to headaches and no benefits. Shrug. I found that errors would make it into production, because human vigilance is always fallible. And the level of testing that I needed to adopt to catch errors was a lot more effort than using a type system.
- cultus 8y agoReplying to your lower comment (the coffee has kicked in): The situation you describe is one where a null really is an unrecoverable error, and the program should terminate. That is the one case where it makes sense to just let a NPE happen. However, the vast majority of time, a null is just an absence of value, and does not signify an unrecoverable error. Those are the kind of situations that an Option/Maybe helps with, since it doesn't let you forget to handle the null case. Even if a null value returned from a function is abnormal, and the program shouldn't continue, an Option is still going to be better most of the time. After all, you probably have connections and stuff you want to cleanly terminate before shutting the program down.
- cultus 8y agoIf you know something can't be null, then don't use an option. Simple as that. For example, a SQL library can return a non-nullable column of String as just a String, not an Option[String]. Thus, you actually get a solid distinction that you don't get with null pointers. There's no reason to include sentinels that will randomly blow up your program.
- jstimpfle 8y agoNo. The point is that the data structure can't know if there's a NULL since the data structure is static. Context is dynamic. Code is dynamic as well, and it can know that some things must exist based on other dynamic conditions. So this "solid" distinction often is just noise and actually blurs the intention of the programmer: An explicit unwrap is required syntactically while it should not be required semantically because really the option data is not an option but a requirement in certain contexts.
- cultus 8y agoIf it is a requirement for something not to be null, unwrap the option before you send to it to the part of the program that can't accept nulls, and deal with the case of None in a sane way and in a predetermined place. Then you don't have to worry about unwrapping in the rest of the code. You can escape from Option. It's not like IO. You just have to check for None if you want to get something out, as you should. In this fashion, you have type safety everywhere, and you deal with the case of a missing value in a predictible way, in a single spot.
- knocte 8y ago> I much prefer the simple NULL sentinel that blows up like an assertion when I made a mistake Are you nuts? I prefer the compiler gives me an error instead of blowing up in production.