Learning from io 2
io is a small, prototype based, dynamic programming language that is inspired by Smalltalk, Self, NewtonScript, Act1, LISP, and Lua. Need I say more? It has a very useful feature that any programmer can appreciate: the "?"
It's very common to want to check the existence of an object before accessing it.
if offer != nil
offer.price
endor
offer && offer.priceIt gets even more tedious when you also need to traverse a couple objects deep.
offer && offer.price && offer.price.formatted_amountLittering the "check" around the code can quickly cloud up the intention of the code. In io, you can do the following:
offer ?price
offer ?price ?formatted_amountNo more checking! However, I want to do that in ruby. An obvious solution is to open up the nil class and re-implement the method_missing to return nil. This is a very bad idea, since it applies to ALL objects in the system. It can hide serious errors within the application and make debugging very difficult. A better solution is to the following:
class Object
def _?()
self
end
end
class NilClass
def _?()
SafeNil.new
end
end
class SafeNil
def method_missing(*args, &b)
nil.send(*args, &b) rescue nil
end
endThe above code is taken from this post The post didn't mention io, but I assumed it is inspired by it. In ruby you can't just use the "?" for your method name, therefore, _ is prepended before "?".Now you can do following without checking the parent object:
offer._?.price._?.formatted_amountif offer or price is nil, nil is returned.

So what you're saying is... you implemented the Maybe monad in Ruby.
In Common Lisp you could just add a method specialized on NIL (or write a macro that does this automatically).
An alternative would be using the MOP for this.