4 ms·
It's possible that I'm missing the thrust of #0, but I don't see how an object-oriented language completely without the concept of a "null pointer" could be use
by RodgerTheGreat 16y ago
It's possible that I'm missing the thrust of #0, but I don't see how an object-oriented language completely without the concept of a "null pointer" could be used to construct elementary data structures like linked-lists and trees without resorting to special classes as terminators. It would be just as clumsy as using null pointers in the first place.
If "not-null" references were provided in addition to normal references, the effect would be pretty similar to the common usage of "final" fields in Java- compiler-enforced initialization.
- Groxx 16y agoI was wondering that too, so I looked up the linked "Cyclone" language. If I'm understanding what I read there, the entire #0 is pretty misleading. Basically, it boils down to adding a "qualifier" to the language, so you can mark pointers as nullable / never-null, so the system doesn't have to check.[1] You can also mark them as "thin" (no pointer arithmetic) and "fat" (safer pointer arithmetic), all of which is accomplished by putting a "@nullable" / "@notnull" / etc. qualifier on the pointer when you declare it (I think). @nullable does a check before each access, @notnull does not. So, it's C + super-static-types to make C somewhat safer. At the cost of making the language significantly more complex. But still not safe, as this is put there by the programmer - people make mistakes. And C programmers seem especially vulnerable to making things unsafe "for speed"... what's to stop an overzealous optimizer from marking more pointers as @notnull? [1]: http://cyclone.thelanguage.org/wiki/Pointers http://cyclone.thelanguage.org/wiki/Pointers
- ekiru 16y agoIf the compile can't statically prove that a pointer can't be null, any attempt to convert it to *@notnull inserts a runtime assertion that it isn't null, according to the website.
- Groxx 16y agoEnabling faster compiled code if it can prove it can't be null? Makes sense, and a useful trade-off for essentially polluting the language with yet more keywords. But that still means you can force it to read things as never being null, even when they could be, and I still don't trust developers (despite (because of?) being one). Unless I'm reading that wrong?
- silentbicycle 16y ago> It would be just as clumsy as using null pointers in the first place. When you combine this with type-inference, it's actually really convenient. Check out the Maybe monad in Haskell or the option type in OCaml - nullable types are boxed in a variant type of None | Some 'a, you're reminded to check for both possibilities in the few places where it actually matters, and you can quit wasting time and bloating your code writing null tests, forever. You can define special sentinel subclasses of things in OO languages, but there's usually quite a bit of boilerplate compared to just adding a variant type in ML (and the compiler still can't guarantee that nulls will never occur), so people don't usually bother.
- Chris_Newton 16y agoThere are alternatives to making references nullable by default. For example, functional programming languages often support algebraic data types and pattern matching. Creating the equivalent of a nullable value is one possible application of these features. Typically, the type system would make sure you can't get to the underlying value without first checking that your data is non-null via pattern matching, so the equivalent of derefencing a null pointer simply isn't possible without generating a compile-time error. Note that this idea is independent of the underlying type, so there's no particular reason you couldn't have a type system that could wrap an OO class type in an algebraic data type. Unfortunately, for now, these ideas seem to live in different worlds: I know of no mainstream OO language that has anything close to the power of algebraic data types and pattern matching that is commonly available in functional programming languages. But this is one way you could have an OO-friendly language with powerful data structures and without relying on the idea of a nullable reference.
- tel 16y agoThis was the first thing I thought of. Addition types with pattern matching (which enable Maybes) both provide safe options for these data types. An example Haskell type that keeps the surface idea of nulls (via Maybe having an object) might be something like: List a :: Cons a (Maybe (List a)) Tree a :: Branch (Maybe (Tree a)) (Maybe (Tree a)) The type system removes the concept of 'dereferencing nulls' while maintaining that if the pointer isn't null it still must be the (polymorphic) type a. Of course, the simpler implementation unfolds the addition type inside Maybe and is more like: List a :: Cons a (List a) | End Tree a :: Branch (Tree a) (Tree a) | Leaf a
- silentbicycle 16y agoPattern matching seems to mix really poorly with conventional OO subtyping / inheritance, though multi-methods seem like a good synthesis. (I haven't really used CLOS enough to decide, though.)
- Chris_Newton 16y agoI'm not sure OO fundamentally requires the kind of inheritance relationship that is familiar from languages like C++, Java and C#, though. For example, the Liskov Substitution Principle is phrased in terms of a subtype relationship between two types. This is a logical relationship rather than a physical one: it is about whether both types present the same interface in terms of (some aspect of) their state and behaviour, and therefore generalised code can be written that interacts analogously with instances of either type. This subtype relationship need not be realised via a subclass relationship, which is a physical relationship related to the mechanics of inheritance hierarchies and so on. I don't see any problem with mixing pattern matching and OO, if you allow a representation as an algebraic data type as one view of a class and provide a mechanism to convert between them in some suitable way. Indeed, I'm fairly sure I've seen papers investigating this approach, though I'm afraid I can't immediately remember what the authors called it so I could look them up; if anyone knows what I'm talking about, please post citations if you have them.
- InclinedPlane 16y agoWelcome to the idea of the "null object". It's an object which satisfies all of the use cases of the null value but doesn't cause you to litter nearly every line of your code with defensive null checks to avoid your program randomly barfing. When done right it's a far more elegant solution than "null".
- grogers 16y agoLinked lists are a particuarly poor example though. It is just as easy to make them without null pointers as with null pointers: struct list_node { list_node *next; }; struct list { list_node sentinel; }; IE. A circular linked list. In C++ speak, begin() is sentinel.next, end() is sentinel. In an empty list, sentinel.next points to &sentinel. It might seem more clumsy, but it isn't really any more work. When you actually do need the equivalent of a null pointer you can use an option type to specify that you either want nothing or a valid pointer.