argius note

プログラミング関連

lambdaで関数型っぽく

lambdaは関数型言語ではあたりまえの存在なわけですが、なぜなら、関数型言語では関数の定義がすべてラムダ式だからです。
以下はLispのサンプル*1

(defun multiply(x y) (* x y))
(defun multiply5(x) (multiply x 5))
(message "%d" (multiply 3 5)) ; "15"
(message "%d" (multiply5 3))  ; "15"

これをRubyで普通の関数形式で書くと、こうなります。

def multiply(x, y) x * y end
def multiply5(x) multiply x, 5 end
puts multiply(3, 5) #=> 15
puts multiply5(3)   #=> 15

で、lambdaを使って書くと、こう。

multiply = lambda do |x, y| x * y end
multiply5 = lambda do |x| multiply[x, 5] end
puts multiply[3, 5] #=> 15
puts multiply5[3]   #=> 15

しかし、これだけじゃありがたみが分からないと思うので、ありがたみが分かるコードを。

class String
  def to_lambda() eval "lambda do " + self + " end" end
end

["|f, x, y| f[x] + f[y]",
 "|f, x, y| f[x] * f[y]"].each do |sf1|
  ["|x| x + x", 
   "|x| x * x"].each do |sf2|
    sf3 = "f1[f2, 3, 5]"
    f1 = sf1.to_lambda
    f2 = sf2.to_lambda
    printf "f1=%s, f2=%s, %s=", sf1, sf2, sf3
    puts eval(sf3)
  end
end

結果。

f1=|f, x, y| f[x] + f[y], f2=|x| x + x, f1[f2, 3, 5]=16
f1=|f, x, y| f[x] + f[y], f2=|x| x * x, f1[f2, 3, 5]=34
f1=|f, x, y| f[x] * f[y], f2=|x| x + x, f1[f2, 3, 5]=60
f1=|f, x, y| f[x] * f[y], f2=|x| x * x, f1[f2, 3, 5]=225

*1:実行環境はMeadowEmacs Lispです。