factorial function for Church numerals
我正在尝试实现Lambda微积分,组合器和函数式编程
一书中所述的阶乘lambda表达式。
描述方式为:
1 2 | fact = (Y)λf.λn.(((is-zero)n)one)((multiply)n)(f)(predecessor)n Y = λy.(λx.(y)(x)x)λx.(y)(x)x |
其中
1 2 3 | (x)y is equivalent to (x y) and (x)(y)z is equivalent to (x (y x)) and λx.x is equivalent to (fn [x] x) |
为标准教堂数字定义了
和
我将其翻译为以下
1 2 3 4 5 | (defn Y-mine [y] ; (defn Y-rosetta [y] ((fn [x] (y (x x))) ; ((fn [f] (f f)) (fn [x] ; (fn [f] (y ; (y (fn [& args] (x x))))) ; (apply (f f) args)))))) |
和
1 2 3 4 5 6 | (def fac-mine ; (def fac-rosetta (fn [f] ; (fn [f] (fn [n] ; (fn [n] (is-zero n ; (if (zero? n) one ; 1 (multiply n (f (predecessor n))))))) ; (* n (f (dec n))))))) |
注释掉的版本是Rosetta代码中的等效fac和Y函数。
问题1:
我从其他地方的阅读中了解到,
问题2:
即使我使用
时收到StackOverflowError
1 | ((Y-rosetta fac-mine) two) |
while
1 | ((Y-rosetta fac-rosetta) 2) |
工作正常。
无保护的递归在哪里发生?
我怀疑
谢谢。
更新:
考虑到@amalloy的回答,我略微更改了
1 2 3 4 5 6 7 8 9 10 11 | (def lazy-one (fn [] one)) (defn lazy-next-term [n f] (fn [] (multiply n (f (predecessor n))))) (def fac-mine (fn [f] (fn [n] ((is-zero n lazy-one (lazy-next-term n f)))))) |
我现在收到一条错误消息:
1 2 | => ((Y-rosetta fac-mine) two) ArityException Wrong number of args (1) passed to: core$lazy-next-term$fn clojure.lang.AFn.throwArity (AFn.java:437) |
考虑到
调用,这似乎真的很奇怪