【发布时间】:2020-05-02 19:01:19
【问题描述】:
我最喜欢的一种测试我正在学习的语言能力的方法是尝试并实现各种定点组合器。因为我正在学习 Clojure(虽然我对 lisps 并不陌生),所以我也学习了。
首先,一些“可测试”的代码,阶乘:
(def !'
"un-fixed factorial function"
(fn [f]
(fn [n]
(if (zero? n)
1
(* n (f (dec n)))))))
(defn !
"factorial"
[n]
(if (zero? n)
1
(apply * (map inc (range n)))))
对于我实现的任何组合器c,我想验证((c !') n) 是否等于(! n)。
我们从传统的 Y 开始:
(defn Y
"pure lazy Y combinator => stack overflow"
[f]
(let [A (fn [x] (f (x x)))]
(A A)))
当然,Clojure 并没有那么懒惰,所以我们转向 Z:
(defn Z
"strict fixed-point combinator"
[f]
(let [A (fn [x] (f (fn [v] ((x x) v))))]
(A A)))
事实上,它认为(= ((Z !') n) (! n))。
现在是我的问题:我无法让 U 或 Turing 组合器 (theta-v) 正常工作。我怀疑 U 是语言限制,而 theta-v 我更倾向于认为这是对 Wikipedia's notation 的误读:
(defn U
"the U combinator => broken???"
[f]
(f f))
(defn theta-v
"Turing fixed-point combinator by-value"
[f]
(let [A (fn [x] (fn [y] (y (fn [z] ((x x) y) z))))]
(A A)))
REPL 体验示例:
((U !') 5)
;=> Execution error (ClassCastException) at fix/!'$fn (fix.clj:55).
;=> fix$_BANG__SINGLEQUOTE_$fn__180 cannot be cast to java.lang.Number
((theta-v !') 5)
;=> Execution error (ClassCastException) at fix/theta-v$A$fn (fix.clj:36).
;=> java.lang.Long cannot be cast to clojure.lang.IFn
谁能解释一下
- 为什么 U 和 theta-v 的这些实现不起作用;和
- 如何解决?
【问题讨论】:
-
请附上您要翻译的代码的链接。
-
呃,@amalloy 我翻译的是数学而不是代码,但如果有帮助,当然
-
FWIW 很多数学和代码都是一样的。当然 lambda 演算两者兼而有之。
-
小点:因为
(*)是1,你不需要1作为函数!的特例。(defn ! [n] (apply * (map inc (range n))))有效,(defn ! [n] (reduce * (range 1 (inc n))))也有效,我更喜欢。
标签: clojure fixpoint-combinators