Trying code blocks in Ruby (aka Prototype’s Try.these)

Prototype’s Try.these is a really useful bit of code (though I doubt it sees much application outside of JavaScript libraries). I have this evil bit of code somewhere, for example:

var results = Try.these(
  function() { return response.responseText.evalJSON(true); },
  function() { return eval('(' + response.responseText + ')'); }
);

Evilness personified in its evaled glory, but that’s besides the point here.

Just for fun, I tried to do this in Ruby, just to see how easy it was, and came up with this try method:

module Kernel
  def try(*these)
    raise ArgumentError, 'try requires at least 2 arguments' if these.size <= 1
    fallback = these.pop unless these.last.respond_to?(:call)
    these.each { |candidate| begin return candidate.call rescue next end }
    fallback || raise(RuntimeError, 'None of the given procs succeeded')
  end
end

Which you can (ab)use like this:

try(
  Proc.new { open('http://finance.yahoo.com/foo/') },
  lambda { open('http://finance.google.com/bar/') },
  proc { open('http://finantiq.com/flomp/') },
  :fallback
)

Real world applications would be, like the example above, retrieving content from several unreliable websites to retrieve currency rates.

You can find the specs for Kernel#try here: http://pastie.org/144339.

So the question now is, is there a better way to implement this, or a more idiomatic Ruby way?

2 Comments & TrackBacks (Add yours)

The paper doll icon that precedes each comment is an idea conceived by Vanessa Tan.

Paper doll icon
Jan De Poorter's Gravatar

What’s wrong with ruby’s native begin/rescue

?

Posted by: Jan De Poorter on January 29, 2008 4am

Paper doll icon
Chu Yeow's Gravatar

Well, nothing wrong really - this is largely just a convenient wrapper around being/rescue that allows you to pass arbitrary procs around and an easy way to specify a fallback value.

Posted by: Chu Yeow on January 29, 2008 9am

You can subscribe to the RSS feed for comments on this post.

Post a comment

(required)

(required, but never displayed)


You can format your comments using XHTML. Your email address will not be displayed or used for nefarious purposes.

Only following tags are allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>