Clojure功能有问题

时间:2010-05-23 06:30:15

标签: clojure

大家,我昨天开始在Clojure的Euler项目上工作,我的解决方案有一个我无法弄清楚的问题。

我有这个功能:

(defn find-max-palindrom-in-range [beg end]
  (reduce max
          (loop [n beg result []]
            (if (>= n end)
              result
              (recur (inc n)
                     (concat result
                             (filter #(is-palindrom? %)
                                     (map #(* n %) (range beg end)))))))))

我尝试像这样运行:

(find-max-palindrom-in-range 100 1000)

我得到了这个例外:

java.lang.Integer cannot be cast to clojure.lang.IFn
  [Thrown class java.lang.ClassCastException]

我认为这意味着在某个地方我试图将整数作为一个函数进行评估。然而,我无法找到这个地方,更让我感到困惑的是,如果我只是像这样评估它,一切都有效:

(reduce max
          (loop [n 100 result []]
            (if (>= n 1000)
              result
              (recur (inc n)
                     (concat result
                             (filter #(is-palindrom? %)
                                     (map #(* n %) (range 100 1000))))))))

(我刚刚删除了函数定义并用常量替换了参数)

先谢谢你的帮助,对不起,我可能会因为我的愚蠢错误而烦你。顺便说一下,我正在使用Clojure 1.1和ELPA最新的SLIME。

修改:以下是 is-palindrom?的代码。我已经将它实现为数字的文本属性,而不是数字属性。

(defn is-palindrom? [n]
  (loop [num (String/valueOf n)]
    (cond (not (= (first num) (last num))) false
          (<= (.length num) 1) true
          :else (recur (.substring num 1 (dec (.length num)))))))

1 个答案:

答案 0 :(得分:6)

代码适用于我的REPL(1.1)。我建议你把它贴在你的身上然后再试一次 - 也许你只是错误的输入了什么?

话虽如此,您可以将此作为一个使代码更简单,更明显正确的机会。一些低调的果实(如果你认为它可能会剥夺你的Project Euler乐趣,请不要阅读,尽管你的逻辑已经记录下来,我认为它不应该):

  1. 您无需在匿名函数中包装is-palindrome?即可将其传递给filter。只需写下(filter is-palindrome? ...)

  2. loop中的is-palindrome?非常复杂。此外,它不是特别有效(firstlast首先从字符串中生成seq,然后last需要遍历所有字符串。 (require '[clojure.contrib.str-utils2 :as str])并使用(= num (str/reverse num))

  3. 会更简单,更快捷
  4. 由于我提到了效率,以这种方式使用concat有点危险 - 它会产生一个懒惰的seq,如果你堆积两个级别的懒惰可能会爆炸(这无关紧要在欧拉4的背景下,但记住它是好的)。如果您确实需要向右扩展向量,请选择into

  5. 为了进一步简化,您可以考虑将它们拆分为一个函数来过滤给定的序列,以便只保留回文并且单独的函数返回两个三位数字的所有产品。后者可以用例如

    完成
    (for [f (range 100 1000)
          s (range 100 1000)
          :when (<= f s)] ; avoid duplication of effort
      (* f s))