3 ms·
It's clear that null has semantic and syntactic meaning. If one cares to make the analysis, one could say that it's messy encoding of the None of the maybe mon
by jpz 8y ago
It's clear that null has semantic and syntactic meaning.
If one cares to make the analysis, one could say that it's messy encoding of the None of the maybe monad, e.g. at the call site you need to do some reasoning, but it effectively encodes Some / None.
It simply does not communicate anything to me to hear someone say "logically-speaking, there is no such thing as null" - such a statement really does appear to be word games. It has no explanatory power, and it cannot ever be categorically true.
- wellpast 8y ago> It simply does not communicate anything to me to hear someone say "logically-speaking, there is no such thing as null" I've seen tons of complex and unwieldy code in my day. Often the complexity comes from illogic and incorrect modeling of how things are. So when someone points out a logical unnecessity, for a programmer to dismiss it as meaningless is to miss out. (In some logics,) there is no such thing as null and therefore you don't need it's representation to write effective programs. That's actually a valuable thing to say. Because from there you can start asking questions like why does it exist here or there? And then you can proceed to write more reasonable, less complex programs. I've had to fight ill-devised null semantics too many times to count in my programming life. To get concrete, there are things we know and things we don't. Most often null is used as a placeholder to say "I don't know." This leads to complexity because I'll then have to write code to branch on this one other value case (or at minimum defend, like the article points out). But if it's not logical per se, then what else can we do. What other way can I program that more reflects logic and our reasoning processes? That's a path to writing better, more maintainable programs. One revelation I got when having to model data in NoSQL after years of SQL is that while SQL makes you decide and write down NULL values for entity properties, NoSQL did not. If you don't know it, you don't write it down. It's that simple. And that is much more in line with the way that I contend with the things I don't know in my life. I don't go around re-iterating my lack of knowledge by referring to some logically non-existent value. I generally simple don't say things I don't know. Following this reasoning to a degree, and then I am writing programs that are much more ergonomic to the way people actually think.
- 3pt14159 8y agoAnd yet when I data science with my dirty SQL, knowing that I've summed a collection that has a null value is super helpful because it shows that the query that I've made is fundamentally unknowable. Of course there are alternative ways of doing it: https://i.imgur.com/ENtJs.png https://i.imgur.com/ENtJs.png
- jpz 8y agoWhen one writes code which is close to the processor, for instance, one has a reason to write in C, one can represent an unallocated memory structure with a null pointer, or one can use a boolean value. A null value means something in that context. I don't see how it means nothing. If I have a tail-recursive function, I probably do not need null. But if I have a loop which may run 0 or more times, and need to catch the absence of runs, I need to model a None result. In that instance, the null has semantic meaning. I can use an algebraic type of course, but for the task I am doing, that may not be practical. Saying that null logically doesn't exist is not true if my context is the Linux kernel. The unqualified statement of such seems to be overly categorical, to me. I do like your analogy with NoSQL, I think it's an excellent point. Nullability in a JSON document for instance is better modelled with absence - however, with a language which is compile-time type-checked, those absent values may need to be present in materialised classes as nullable values (options if you like) - unless you're dictionaries all the way down like Python.
- enord 8y agoThe nullephant in the room is that procedural programming with mutable state (registers, class fields, whatever) is not trivially amenable to logical analysis, and any constraints introduced to rectify this issue become the topic of a never-ending river of tutorials and navel-gazing rants on the demerits of said tutorials. (See borrow-checkers, linear/affine types, monads etc.) People want to Get Stuff Done, and preferably without getting all math-y about it. Compile now plz. Add the null-reference to your spec and Presto! the problem is now confined to userspace. it can be done, but it's Not Fun, and definetly mathy, e.g. Predicate Transformers or ß-reductions
- DalekBaldwin 8y agoBut it doesn't encode Maybe/Option in a composable way. Say you have a Map<T,Option<U>> and you look up a key. If the key is present but maps to None, you get Some None, but if the key is not present, you get None. A plain untyped null/nil results in a lossy encoding of the two distinct cases. Lispy maps tend to paper this over by returning multiple values or returning a tuple (e.g. using Clojure's `find` instead of `get`), but I almost never see a codebase maintained with enough discipline to handle these situations consistently. If you have multiple developers working on different parts of a record-munging pipeline, you will typically have to deal with endless bug regressions involving the silent disappearance of key-value pairs that come and go depending on the order in which you compose the transformations.
- 3pt14159 8y agoI think it fundamentally boils down to how you see the data. People that think in RDMS terms see the existence of the record as an implicit existence of the mapping key, since every record of a table has every attribute. If the record is not there, then it truly is None as in non-existence (no key present) but that operates at a different layer in our applications because the missing object doesn't have the methods or attributes of the class. It's a different class entirely! So in that sense the conflation issue with key => null vs no key at all is itself a mishandling, since it's operating on different classes of objects. This is what you call "paper overing" but I don't think it is fundamentally wrong, I think it's just a different way of reasoning about the data. It's also why I think the functional programming community prizes maybe monads more than the object orientated community. Functional programming is fundamentally about managing streams of data with functions that match up types, so the distinction between none and null matters because the data doesn't drag along it's methods from place to place.