Yコンビネータ(2)

Y Combinatorをほぼそのままrubyに書き換えただけです.

ちなみに,ポール・グレアム関連でYコンビネータについて聞いたことがあるだけで,λ計算を勉強したことは無い.λ計算関連のページを検索してみるか.



素朴な階乗:

fact = lambda{|n| (n==0)? 1: n * fact[n - 1] }
p fact[5]


ラムダ式の中からfactを消す.代わりに呼び出し元が二重になった.

fact = lambda{|f| lambda{|n| (n==0)? 1: n * f[f][n - 1] }}
p fact[fact][5]

いまのfactは元々のfactを作り出すラムダ式


f[f][n-1]をf[n-1]に変形するための準備その1
f[f]をラムダ式にしてしまう.これでlambda{...}[x]はf[x]に変形できる.

fact = lambda{|f| lambda{|n|
  (n==0)? 1: n * lambda{|x| f[f][x]} [n-1] }}
p fact[fact][5]


lambda{|x|f[f][x]}をfの代わりに引数として渡すように変形する.

fact = lambda{|g|
  lambda{|f|
    lambda{|n| (n==0)? 1: n * f[n-1] }
  } [lambda{|x|g[g][x]}]
}
p fact[fact][5]


外側のlambdaを分離する.

fact = lambda{|f| lambda{|n| (n==0)? 1: n * f[n-1] }}
factX = lambda{|f| fact[lambda{|x| f[f][x]}]}
p factX[factX][5]

factXの中にfactが入ってしまったが,そのうち消える予定.


呼び出しもとの factX[factX]を整理

fact = lambda{|f| lambda{|n| (n==0)? 1: n * f[n-1] }}
factX = lambda{|f| fact[lambda{|x| f[f][x]}]}
pseud_y = lambda{|x| x[x]}
p pseud_y[factX][5]


pseud_yのx[x]はfactX[factX]だから展開して,

fact = lambda{|f| lambda{|n| (n==0)? 1: n * f[n-1] }}
pseud_y = 
  lambda{|f| fact[lambda{|x| f[f][x]}]}[
  lambda{|f| fact[lambda{|x| f[f][x]}]}]
p pseud_y[5]


pseud_yからfactを外に出して,

fact = lambda{|f| lambda{|n| (n==0)? 1: n * f[n-1] }}
pseud_y = lambda{|g|
  lambda{|f| g[ lambda{|x| f[f][x]}]}[
  lambda{|f| g[ lambda{|x| f[f][x]}]}]
}
p pseud_y[fact][5]