6 ms·
NULL is a convenient way to map singularities in your model of the problem. I have on a few occasions tried to write NULL-less code, and it adds a good bit of
by rusk 8y ago
NULL is a convenient way to map singularities in your model of the problem.
I have on a few occasions tried to write NULL-less code, and it adds a good bit of work.
- model all possible states for a value
- determine appropriate default actions for all types
- meaningful place-holder values
It's a good exercise, and I think more code should be written this way, but - as an Engineer I'm trying to model just enough of the problem to solve it. I'm not trying to simulate every possible outcome in that domain.
Certain corners of your problem simply don't need to be modeled, and what's more the effort needed to model them can just be too much.
NULL is a great way to just throw up your hands and go "I don't know and I don't care". Much as when modelling a physical system singularities typically represent phenomena that the model doesn't take account of, so it goes with NULL. It simply says "Don't Go There".
- knocte 8y agoHave you ever dealt with the Maybe(Haskell)/Option(F#) types? If not, then you don't understand what's wrong with NULL and how to easily avoid it without much work.
- jstimpfle 8y agoI 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.
- 8y ago
- 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.
- rusk 8y agoI see these as a more sophisticated way of dealing with NULL. It allows me to define alternative default behaviour beyond just throwing an undeclared exception. They are still NULLs however under the hood and I still need to do the work of defining what I want to happen when they occur. It's just neater.
- icebraining 8y agoYou can conceptualize the Maybe based on the NULL, but there's no point in the compilation or runtime in which they actually become NULLs, it's just a regular container value.
- rusk 8y agoWhich is the same as if I go and ensure a default "noop" value is assigned ... it's logically a NULL. I don't know anything about it except that it hasn't been assigned.
- icebraining 8y agoIt's not a NULL. A NULL is a value that is considered by the type system to be a valid instance of a given type, except it doesn't actually fulfill the type's contract. A Maybe is a completely different type, much like a list or a map or a tree.
- rusk 8y agoWell at this stage you're just being narrow minded. I think if you read back over this thread it should be clear what I mean. I proposed that NULL has a purpose. You proposed that Option obviates this. I stress that it's just a neater way to manage the conditions you don't need to model. You point out that in terms of implementation it's different, where I explain that still, logically it's the same thing. Of course NULL has a very specific meaning in the structure of the language, and when you start using things like Options it makes managing NULL easier, but it's a rose by another name, gift-wrapped, and bundled with some plant food. Logically however, at the point where you're modelling your problem it's the same.
- jcelerier 8y ago> I have on a few occasions tried to write NULL-less code, and it adds a good bit of work. Really depends on the language. On Java / C#, it's hard to avoid null-checking a lot of stuff. In C++ you will never encounter a null std::string outside of code written by indian students learning on Turbo C++ 3.5. So you don't need to check for anything: if it's a value, it exists.
- rusk 8y agoStrings are an easy case. Default initialisation to "" (empty string). You'll still encounter NULL when modelling other domains however.