Example:
I have a person object that might have a spouse object, and I want their first_name. So, if all is good, I'd call person.spouse.first_name. Of course, if we have no spouse there would be a crash of no method first_name on nil, so I use Maybe:
first_name = Maybe(person).spouse.first_name.fetch(nil)
In this case, as per idiomatic Ruby, I want nil as the default first_name if there is none. However, the value of first_name
is not nil, but rather Monadic::Nothing
, which is true valued in if satements! In other words
# Fails to work correctly because first name is Monadic::Nothing, not nil as expected!
do_something(first_name) if first_name
The bug is at https://github.com/pzol/monadic/blob/master/lib/monadic/maybe.rb#L78, where you use a magic value for the argument to decide if you have one, and that magic value happens to be a common default for idiomatic Ruby.
My recommended fix would be to capture the args as follows, which gives exactly the same behavior as the current version, but honors any default value:
def fetch(*args)
case args.length
when 0
self
when 1
args.first
else
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..1)", caller
end
end