Clojure Church数词的阶乘函数
我正试图实现书中描述的阶乘lambda表达式 这里的描述方式是:Clojure Church数词的阶乘函数,clojure,lambda,functional-programming,factorial,y-combinator,Clojure,Lambda,Functional Programming,Factorial,Y Combinator,我正试图实现书中描述的阶乘lambda表达式 这里的描述方式是: fact = (Y)λf.λn.(((is-zero)n)one)((multiply)n)(f)(predecessor)n Y = λy.(λx.(y)(x)x)λx.(y)(x)x 在哪里 而为零,一,乘法和前置是为标准的教堂数字定义的。实际定义 我把它翻译成以下内容 (defn Y-mine [y] ; (defn Y-rosetta [y] ((fn [x] (y (x
fact = (Y)λf.λn.(((is-zero)n)one)((multiply)n)(f)(predecessor)n
Y = λy.(λx.(y)(x)x)λx.(y)(x)x
在哪里
而为零
,一
,乘法
和前置
是为标准的教堂数字定义的。实际定义
我把它翻译成以下内容
(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))))))
及
注释掉的版本是来自的等效fac和Y函数
问题1:
我从别处的阅读中了解到,Y-rosetta
β-降低为Y-mine
。在这种情况下,为什么使用这一个优于另一个
问题2:
即使我使用Y-rosetta
。当我尝试时,我得到了一个堆栈溢出错误
((Y-rosetta fac-mine) two)
当
很好
无防护递归发生在哪里
我怀疑这与if
表单在clojure中的工作方式有关,它并不完全等同于我的is zero
实现。但我自己还没能找到错误
谢谢
更新:
考虑到@amalloy的回答,我稍微改变了fac-mine
以接受懒惰的论点。我对clojure不是很熟悉,所以,这可能不是正确的方法。但是,基本上,我让为零
接受匿名零参数函数并计算它返回的任何值
(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))))))
我现在得到一个错误,说:
=> ((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)
考虑到
懒惰的下一个术语
总是用n
和f
调用,这看起来真的很奇怪fac mine的主体
看起来是错误的:它调用(是零n一)
以获得副作用,然后无条件调用(乘以n(f(前置n))
。大概您希望在这里有一个条件选择(尽管我不明白为什么这不会引发算术异常,因为您对的定义是零)。我很抱歉。我复制代码时出错了。我现在已经改正了。但我认为无条件调用multiply
的观点仍然成立。有没有办法让你变得懒惰?
((Y-rosetta fac-rosetta) 2)
(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))))))
=> ((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)