This is especially a problem in dynamic languages that sling nils around....like any major modern scripting language. Checking if a value is nil before proceeding is aping what a language like Haskell does when it pattern matches against Maybe (Just a, Nothing) albeit in a post-facto bad way. Granted, you can't really make any assertions about reflecting a maybe value in the type of a language that doesn't care about types before runtime.
Making types non-Nullable by default is nice, though. Even in a dynamic language you can have a syntactic distinction to make interfaces more explicit.
I'm sort of a fan of Haskell already, to tell you the truth.
Not sure that's so far from Haskell, really... :-P
> and a type system that can handle external hardware poking around in its memory
Can it be in isolated places? That's doable...
Maybe it's my lack of experience talking. Haskell feels heavier in a lot of places. I think the focus on compilation in the backend is almost a downside here, too.
Can it be in isolated places? That's doable...
Depends on the application. There's a lot of hardware out there that does really weird stuff. There's some interesting work in Haskell-space (eg Atom) but I don't know how comprehensively mature it is.
In some scenarios, this is a serious issue all by itself. My day-to-day work is mostly on Android, and eliminating nullable references altogether would eliminate some crashes, which are highly visible to the user.
if (argumentX == null)
return null;
at the top of function signatures. It was just defensive programming. Maybe argumentX couldn't be null, but it would take time to figure that out (sometimes I did that, though). More code means harder to read and maintain, thus costing dollars.This would also be contagious: If a piece of code checks if X is null, you'll assume that X can be null, whether or not that's true.
I'd certainly prefer to be able to reason about the code with the safe assumption that certain things cannot be null.
You can do this, but if you want it to be maintainable, you'll also want to detail in the function comments this technical debt. If you don't, someone else will come along and see your sweet method (looking only at the comments) and use it where the input can be null.
Ex:
/**
* This does some stuff.
* @param entry Does something with this
* DEBT: Assumes the input entry is not null.
*/
void doSomething(SomeObject entry) { }Depending on your user-base (i.e. if you distribute headers to other developers with precompiled code), the documentation may be necessary on its own... but it's much weaker than an assert.
For anyone who needs to look it up like me: http://en.wikipedia.org/wiki/Reference_(C%2B%2B)
If people want to pass lazy NullPointerExceptions, it's their fault.
You should verify arguments at a top level, then let the code underneath blow up with a NullPointerException if something unexpected happened. Your stack trace will point at where the problem lies.
I find for some reason that a lot of people want to use null instead of empty lists where you'll end up with this ugliness:
if (list != null) {
for (Thing t: list) {
processThing(t);
}
}
Instead of just passing in a Collections.emptyList() instead.They had to "fix" it by blocking userspace memory mappings at the 0th page.
While pointers which point into the wrong place for various reasons (off end of array, previously freed memory) cause horrible issues to this day, I can't personally remember ever having a serious issue with a null pointer (they tend to crash quickly and loudly, because in all modern OSes dereferencing NULL segfaults)