That reminds me of this article, Null References: The Billion Dollar Mistake:
Tony Hoare introduced Null references in ALGOL W back in 1965 “simply because it was so easy to implement”, says Mr. Hoare. He talks about that decision considering it “my billion-dollar mistake”.Compounding this problem is Ruby's current lack of real keyword arguments (although, I know they're coming). Hence, if you pass a keyword argument like f(:foo => 1), and then try to use the keyword argument in the function like options[:foooo], the misspelling will result in a nil as if the argument hadn't been passed. This masks a real problem. All of these have resulted in real bugs in my code and lots of frustration.
It doesn't have to be this way. In Python, if you try to look up something in a dict that doesn't exist, you get a KeyError exception. If you try to use an attribute that doesn't exist, you get an AttributeError exception. If you misspell a keyword argument, you get a TypeError exception. Exceptions are nice because they catch the problem right away instead of allowing it to fester. In Ruby, if I get a nil that I'm not expecting, I might not find out that there's a problem until much, much later in a different part of the code when I try to call a method on the nil thinking it's a real object.
Since I'm on the subject of hashes, I think I should mention that Haskell and Scala take a different approach. If you look up something in Scala that may not exist, it returns an Option instance. An Option instance may or may not contain a real value. (Similarly, Haskell uses the Maybe monad.) You have to do work to get the value out of the Option instance, and the type system will catch you if you just blindly assume that there's always something in the Option instance. This is one case where the ML type system can help you avoid a whole class of bugs.