A long time ago, in Objective-C on the NeXT, one could often remove nil
checks, because all messages to nil
would immediately return nil
(or 0
depending on the caller’s method signature).
How many times have we seen this in Ruby?:
def foo bar && bar.baz && bar.baz.caz("x") end
Or even worse, avoiding redundant execution?:
def foo (temp = @bar) && (temp = temp.baz) && temp.caz("x") end
In Objective-C this could be written as:
- foo { return [[bar baz] caz: "x"]; }
So in Ruby:
class ::NilClass def method_missing(*args) nil end end @bar = nil def foo @bar.baz.caz("x") end foo # => nil
Assuming that most of the time bar
is not nil
, NilClass#method_missing => nil
makes for cleaner code that also runs faster than checking for nil
along the way.
An additional benefit is that nil
can also be used as an immutable empty collection sink by defining NilClass#size => 0
, NilClass#empty? => true
, etc.
Obviously, it breaks code that expects exceptions to be thrown for messages to nil
.
Introduce a method that explicitly checks for nil:
module ::Kernel def not_nil; self; end end class ::NilClass def not_nil; raise("not_nil failed"); end end @bar = nil def foo @bar.baz.caz("x").not_nil end foo # => RuntimeError: not_nil failed
Comments?