Memoize

BasicWerk   EC Support   Technique   Facebook  

20140902181358_Ruby_if

Ruby_if

 

 

Ruby では if が値を返すので、こんな書き方が出来る。

 
x = 0
if x
    calc = lambda {|n| n + x}
else
    calc = lambda {|n| n}
end
# => #<Proc:0x007fd35a06c338@(pry):3 (lambda)>
# lambda ブロックが返され、更に calc にバインドされた状態で参照できる
 
(-3..10).map(&calc)
# => [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 
x = 8
(-3..10).map(&calc)
# => [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
 
x = nil
(-3..10).map(&calc)
# => [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 

 

だから calc はこう書いたのと同等だ。

 
x = nil
# ここで calc を宣言(してもしなくてもよいということ)
calc = nil
if x
    calc = lambda {|n| n + x}
else
    calc = lambda {|n| n}
end
# => #<Proc:0x007fd35a4aa3a0@(pry):38 (lambda)>
 
(-3..10).map(&calc)
# => [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
 

 

分岐によって lambda の中身が複雑になったり、多大なオーバーヘッドが発生するようなら、

最初から lambda オブジェクトを「作り分ける」というやり方は good だと思う。

 

でも個人的にはなるべくこう書くのが好きだ。

(この例なら、if で分岐させる為の計算量が無視できる程度のオーバーヘッドなら、という前提だが。)

 
x = 99
calc = lambda do |n|
    if x then n + x else n end
end
# => #<Proc:0x007fd35c09a560@(pry):43 (lambda)>
 
(-3..10).map(&calc)
# => [96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109]
 

 


© Shin Nakamura/BasicWerk 2014