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?