将 clojure `defn` 重构为 `fn` 导致 ClassCastException

Refactoring clojure `defn` to `fn` causes ClassCastException

我正在研究 4clojure 的素数 型。我有完美的解决方案 (如果效率低下)在我的本地机器上,但它依赖于 defn 这是 4clojure 禁止。

(defn factors [n]
  (->> n
       range
       (map inc)
       (filter #(zero? (mod n %)))))

(defn prime? [n]
  (->> (factors n)
       (count)
       (= 2)))

(defn n-primes [n]
  (->> (range)
       (filter prime?)
       (take n)))

我试图重构它以仅使用匿名函数,但它爆炸了。

(fn x-primes [count]
  (let [x-factors (fn factors [n] (->> n range (map inc) (filter #(zero? (mod n %)))))
         x-prime? (fn [n] (->> (x-factors n) (count) (= 2)))]
        (->> (range)
             (filter x-prime?)
             (take count))))

抛出以下错误(当 运行 在本地和使用 4clojure 的编辑器时)

ClassCastException java.lang.Long cannot be cast to clojure.lang.IFn

我重构代码做错了什么?

顺便说一句,为什么 4clojure 会禁止 defdefn

您正在使用您的参数名称隐藏 count 函数。 (count some-num) 抛出错误,因为在此范围内,count 是一个数字,而不是函数。

将您的参数名称从 count 更改为其他名称。


此外,在 4Clojure 的帮助页面中,有以下行:

Some operations are prohibited for security reasons. For instance, you will not be able to use "def" or switch namespaces.

因为 defn 只是一个 def 包装宏,所以它也被禁止是有道理的。尽管我无法理解这将如何导致安全问题。