Having recently worked with a Ruby codebase where anything could be nil at anytime, I consider even references to nil to be a code smell. Developers are inherently prone to ignoring error handling, so they'll happily ignore the fact that Order#customer really means Order#customer_or_nil. And when they see errors in production, they'll slap an andand on it and call it fixed. The code becomes extremely difficult to reason about.<p>I prefer that functions throw an exception when unable to do what they promised, rather than return nil or a null object. The try-catch block serves as documentation that the function might fail. If someone forgets to catch the exception, it will shut everything down rather than leave the program in an unanticipated state that could lead to an error elsewhere.
I'm not sure I like it, but this works<p><pre><code> def nil.method_missing(*args, &block); end
</code></pre>
So now you can call nil.whatever.you.like and get nil. It's also still falsy, but now every nil value in your app silently works and doesn't throw an error.<p>It's both impressive and scary that Ruby lets you (or that new contractor you're not sure about) change the fundamentals of the language in one line of code.
I've said this in a comment at rosania.org, but I think it bears repeating here: this is why we need a #blank? or #null? protocol that user classes can participate in as part of core. #nil? and an inextensible FalseClass just aren't enough to do the sorts of thing that Avdi was trying to do in his original post. My tentative proposal is languishing here: <a href="http://redmine.ruby-lang.org/issues/5372" rel="nofollow">http://redmine.ruby-lang.org/issues/5372</a>
Conceptually, nil != false. You shouldn't use 'nil' to mean 'false'. You should always test explicitly for nil-ness using #nil?. If you write<p><pre><code> if finished?
do_something
end
</code></pre>
then finished? is not expected, and may not, return nil.<p>If you expect <i>some_value</i> to be able to be nil (which, for boolean values, is hardly ever), you should write<p><pre><code> if !some_value.nil? && some_value
do_something
end
</code></pre>
In the end, these 'convenient' coercions that allow you to use any value as a boolean only come back to bite you, because unexpected stuff happens when stuff is unexpectedly nil. If it makes my coworkers cry that an object is nil and true at the same time, then they are at fault, not me.<p>Edit: and more importantly (I forgot to point this out explicitly) a non-nil value != true. That any string or integer is 'true' can lead to very hard-to-find bugs.
Isn't this a flaw in Ruby, though? It also means that you can't create a delegate/decorator/proxy object for a false object and have it be false as well, which goes against the general "everything is determined by sending messages" vibe Ruby has going on.<p>I know the reasoning (it's much faster to do math on object IDs than it is to call a method), but there are workarounds for this (e.g. only allowing frozen objects to be boolean-false, and having the object's truth-ness/false-ness represented by the return value of its #false? method <i>at the time of freezing</i>—thus allowing the interpreter to locate it in a semantically-meaningful part of object-ID space that can later be masked for in a TEST instruction.)