【问题标题】:Problem with Clojure functionClojure 函数的问题
【发布时间】:2011-02-22 20:49:03
【问题描述】:

大家,我昨天开始在 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]

我认为这意味着在某个地方我正在尝试将 Integer 作为函数进行评估。但是我找不到这个地方,更让我困惑的是,如果我像这样简单地评估它,一切正常:

(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)))))))

【问题讨论】:

  • 我认为问题在于is-palindrom? 函数,因为当我实现缺少的is-palindrom? 时,您的find-max-palindrom-in-range 对我有用
  • 我添加了我的 is-palindrom 代码?问题。
  • 在 Clojure 中 is-palindom? 的更好名称是:palindrome?
  • (filter #(is-palindrome? %) ...) 等价于(filter is-palindrome? ...)

标签: clojure


【解决方案1】:

该代码适用于我的 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. 1234563 Euler 4 的上下文,但最好记住它)。如果确实需要将向量向右扩展,请首选into
  4. 为了进一步简化事情,您可以考虑将它们分解成一个函数来过滤给定的序列,以便只保留回文,以及一个单独的函数来返回两个三位数的所有乘积。后者可以通过例如来完成

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

【讨论】:

  • +1 来自于伟大的建议。我对 Clojure 和函数式编程还很陌生,所以我知道我的风格远非很好。听到有用的提示来改进您的代码总是很高兴。也就是说,我已经在 REPL 中多次尝试过代码,但它根本行不通。而且我无法从我得到的堆栈跟踪中做出正面和反面,因为我的代码中基本上没有任何内容......
  • 这真的很奇怪。 :-( 我会说用新的 REPL 再试一次。如果它不起作用——你能把你正在使用的代码的 entirety 和堆栈跟踪粘贴到某处吗?在此处发布链接?
  • 杀死我的劣质 lisp 进程并再次启动它解决了这个问题。我仍然不知道最初的问题是什么,但我感谢您的帮助。
猜你喜欢
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多