Forum: Ruby on Rails One Liner Problem / MaybeMonad

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
417e50c1bb8f3958b58e9b1f593a9e0b?d=identicon&s=25 shawn_garbett (Guest)
on 2005-12-09 19:44
(Received via mailing list)
Stump the list challenge for a Friday. The following
code has a reoccuring pattern. The chain of calls
can't continue if a nil is returned. So what would be
a one-liner is now broken into three. This occurs in
several places in the Ruby code. What would be good is
if this could be turned into a _clean_ one-liner. No
fancy gobbly-gook strung out over 80 characters....

def self.locate( path )
  d = TupleDomain.locate( path )
  return nil unless d
  d.tuple
end

Things like the following are not desired, because
they make ugly looking chains.
def self.locate( path )
  (d = self.locate( path ) ? nil : d.tuple)
end

HINT: What would be better would be something like
this:

class self.locate( path )
  TupleDomain.locate_domain( path
).return_on_nil.tuple
end

Hmmmm..... How to do that? Add a method to Object
maybe?

----------------------------------------------------------------------
SPOILERS BELOW
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

At first I thought just add a routine to Object
return_on_nil, and for the nil object just have it
define a method_missing that just returns nil. So that
all nils pass through unharmed.

Bzzzzt. That didn't work. nil is a singleton. I mean a
real solid singleton, defined in the core of the
language. No easy reflection is going to change that,
and gosh how much it would probably screw up.

So then I decided to create a mirror of nil, that does
the chaining. This is what I came up with:

class ChainableNil
  NilClass.methods.reject {|m| m =~
/(send|eval|__id__)/}.each do |m|
    a=NilClass.method(m.to_sym).arity
    case
      when a == 0
        eval "def #{m}() nil.send(:#{m}); end"
      when a > 0
        eval "def #{m}(*args) nil.send(:#{m}, args);
end"
      else
        eval "def #{m}(*args,&block) nil.send(:#{m},
args, block); end"
    end
  end
  def method_missing(symbol, *args) self end
end

class Object
  def return_on_nil() (self.nil? ?  ChainableNil.new :
self) end
end

# Test code, should print an even mixture of false and
trues.
def foo() (rand(10) > 4 ? nil : 'test') end
20.times {puts foo.return_on_nil.length.nil?}

Now it would be even better that if once invoke in a
chain _any_ routine that fails nils the chain-- like a
true MaybeMonad.
http://moonbase.rydia.net/mental/writings/programm...

The true monad solution however invokes a lot of code
and turns this into a non one-liner stringable chain
of routines.

So anyone up for the second challenge? I have doubts
it can be done.

Shawn

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
This topic is locked and can not be replied to.