You need to monkey-patch Nilclass
to coerce nil
to an integer. Here is the code:
class NilClass
def coerce(n)
return [0, n] if n.is_a? Numeric
super
end
end
1 + nil
#=> 1
Have a look at this thread - In Ruby, how does coerce() actually work? - to understand the concept of coerce
.
However, there is an issue with above code:
nil + 1
#=> undefined method `+' for nil:NilClass (NoMethodError)
To fix this problem, you will have to define +
method on NilClass
class NilClass
def +(param)
param + self
end
end
nil + 1
#=> 1
If we try to get adventurous and try:
nil * 10
#=> undefined method `*' for nil:NilClass (NoMethodError)
By being adventurous, lets handle all such undefined method
s by implementing our own method_missing
handler.
class NilClass
def method_missing m, *args, &block
args.first.send(m, self, &block) if args.size == 1
end
end
p nil * 1
#=> 0
Next, lets try:
nil + "hello"
# '+': can't convert NilClass to String (NilClass#to_str gives NilClass) (TypeError)
Lets fix this as well
class NilClass
def to_str
""
end
end
nil + "hello"
#=> "hello"
Next, lets try this:
nil + [1,2,3]
#=> '+': can't convert NilClass to Array (NilClass#to_ary gives NilClass) (TypeError)
Lets fix it:
class NilClass
def to_ary
[]
end
end
nil + [1,2,3]
#=> [1, 2, 3]
We now have this version of NilClass
:
class NilClass
def coerce(n)
return [0, n] if n.is_a? Numeric
super
end
def method_missing m, *args, &block
args.first.send(m, self, &block) if args.size == 1
end
def to_str
""
end
def to_ary
[]
end
end
Caution:: Above code shows that what you want to do can be done. However, this should be used only for experimental and learning purpose. It is really not feasible to make nil
behave like other operand in all operations and you will end up monkey-patching NilClass
to no end.
Hence, its better to stay off from this kind of monkey patching to avoid scary surprises to future Rubyists who will be maintaining your code.