【问题标题】:Refactoring clojure `defn` to `fn` causes ClassCastException将 clojure `defn` 重构为 `fn` 会导致 ClassCastException
【发布时间】:2017-05-02 13:57:39
【问题描述】:

我正在处理4clojure's Prime Numbers kata。我有完美的解决方案 (如果效率低下)在我的本地机器上,但它依赖于 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 无法转换为 clojure.lang.IFn

我在重构代码时做错了什么?

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

【问题讨论】:

  • 具体在哪里?
  • 你是如何运行它的?
  • 本地运行时的苹果酒。我正在从我的编辑器中评估 s-exp(尽管将 fn 更改为 defn),然后通过以下方式调用它:(x-primes 5) in cider。
  • 我应该注意,在执行 4Clojure 时将代码包装在 fns 中可能是不必要的。你还不如直接输入代码 sn-ps 运行。
  • 顺便说一句:您可以使用 letfnlet 函数 - 我使用 letfn 重构了您的代码 here

标签: clojure refactoring anonymous-function


【解决方案1】:

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

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


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

出于安全原因,禁止某些操作。例如,您将无法使用“def”或切换命名空间。

由于defn 只是一个def 包装宏,因此它也被禁止是有道理的。但是,这将如何导致安全问题超出了我的范围。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多