if (o!=nil and o.first_call!=nil and o.first_call.second_call!=nil)
I quickly created a class which would help me get around this problem, and I think (I haven't checked further, honnestly) this goes in the direction of monads, which are well known in Haskell.
The solution is to have a class of which an instance is returned in place of nil. This instance responds to all methods by returning an instance of the same class, in turn responding to all methods. However such an instance responds to the method #nil? with true.
class SimpleMonad
def initialize(h={:is_nil => true})
@is_nil = h[:is_nil]
end
def method_missing(m, *args)
return SimpleMonad.new
end
def nil?
@is_nil
end
end
And I'm using this class as return value in a class derived from Hash. method_missing returns either the value in the hash for which the key is the method name just called, or an instance of the class above:
class ServicesKeys < Hash
def method_missing(m, *args)
if keys.include?(m)
return self[m]
else
return SimpleMonad.new
end
end
end
That way, we can chain calls as we want:
#define the object we will work on
h = ServicesKeys[ :uploadforme => ServicesKeys[:login => 'rb', :username => 'rb']]
#we can easily access the values in there:
h.uploadforme.login
=> "rb"
#if we try to access values for an undefined service, we don't get in trouble:
h.myowndb.login.nil?
=> true
You have to be cautious in naming your keys to avoid clashes, but in my case this is an acceptable trade-off.
There might also be better and more advanced solutions out there. Don't hesitate to mention them in the comments.
No comments:
Post a Comment