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?