ブロックやラムダ式を使った再帰表現のお勉強をしてみました。
なお、以下の例はどれもinjectでやった方が早い例です。
Hashie::Extensions#deep_find_allの場合
module Hashie module Extensions module DeepFind def deep_find_all(key) matches = _deep_find_all(key) matches.empty? ? nil : matches end #... private #... def _deep_find_all(key, object = self, matches = []) if object.respond_to?(:key?) matches << object[key] if object.key?(key) object.values.each { |v| _deep_find_all(key, v, matches) } elsif object.is_a?(Enumerable) object.each { |v| _deep_find_all(key, v, matches) } end matches end end end end
この方式に則ると、injectでもかけそうな文字列連結は次のように書き下せます。
def test (ary, sum = "") (ary.is_a?(Enumerable)) ? ary.each{|i| test(i,sum)} : sum.concat(ary[0]) sum end
ラムダ式の場合
factorial = lambda do |n| n <= 1 ? 1 : (n * factorial.call(n - 1)) end
これを呼び出すと…
factorial.call(3) #=> 6 factorial.call(5) #=> 120
この場合、先程の例は
test = lambda{|i,j| (i.is_a?(Enumerable)) ? i.each{|x| test.call(x,j)} : j.concat(i[0]); j} test.call(%w(a b c),"") #=> "abc"
となります。