这个Clojure计划有什么问题?

Ben*_*nno 5 clojure

我最近开始阅读Paul Grahams的'On Lisp',并学习学习clojure,所以这里可能有一些非常明显的错误,但是我看不到它:(显然是一个项目的euler问题)

(ns net.projecteuler.problem31)

(def paths (ref #{}))

; apply fun to all elements of coll for which pred-fun returns true
(defn apply-if [pred-fun fun coll]
  (apply fun (filter pred-fun coll)))

(defn make-combination-counter [coin-values]
  (fn recurse
    ([sum] (recurse sum 0 '()))
    ([max-sum current-sum coin-path]
      (if (= max-sum current-sum)
          ; if we've recursed to the bottom, add current path to paths
          (dosync (ref-set paths (conj @paths (sort coin-path))))
          ; else go on recursing
          (apply-if (fn [x] (<= (+ current-sum x) max-sum))
              (fn [x] (recurse max-sum (+ x current-sum) (cons x coin-path)))
              coin-values)))))

(def count-currency-combinations (make-combination-counter '(1 2 5 10 20 50 100 200)))
(count-currency-combinations 200)
Run Code Online (Sandbox Code Playgroud)

当我在REPL中运行最后一行时,我收到错误:

<#CompilerException java.lang.IllegalArgumentException: Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)>
Run Code Online (Sandbox Code Playgroud)

除了错误的问题之外,更有趣的问题是:如何调试这个?错误消息不是很有帮助,我还没有找到一个很好的方法来单步执行clojure代码,每次遇到问题时我都无法真正询问堆栈溢出.

Tim*_*ley 13

三个提示可能会让您的生活更轻松:

  1. Wrong number of args passed to: problem31$eval--25$make-combination-counter--27$recurse--29$fn (NO_SOURCE_FILE:0)> 告诉你大概发生错误的地方:$fn最后那里意味着匿名函数,它告诉你它是在recurse里面声明的,它是在里面声明的make-combination-counter.有两个匿名函数可供选择.

  2. 如果将源代码保存在文件中并将其作为脚本执行,它将为您提供包含文件中行号的完整堆栈跟踪.

    at net.projecteuler.problem31$apply_if__9.invoke(problem31.clj:7)
    
    Run Code Online (Sandbox Code Playgroud)

    注意,您还可以通过检查*e来检查REPL中的最后一个异常和堆栈跟踪:例如:(.stackTrace*e)堆栈跟踪起初非常令人生畏,因为它会抛出所有Java内部.您需要学会忽略它们,只需查找引用代码的行.在你的情况下,这很容易,因为它们都是从一开始net.projecteuler

  3. 您可以命名匿名函数以帮助更快地识别它们:

    (fn check-max [x] (<= (+ current-sum x) max-sum))
    
    Run Code Online (Sandbox Code Playgroud)

在您使用所有这些信息的情况下,您可以看到apply-if正在传递单个参数函数作为乐趣.应用这样做(f [1 2 3]) - >(f 1 2 3).从你的评论你想要的是地图.(地图f [1 2 3]) - >(列表(f 1)(f 2)(f 3)).当我applymap程序替换似乎工作.

最后,如果你想检查你可能想要查看clojure-contrib.logging哪些值有一些帮助这种效果的值.有一个间谍宏允许你包装一个表达式,它将返回完全相同的表达式,因此它不会影响你的函数的结果,但会打印出来EXPR = VALUE,这可能很方便.同样在该组织中,各种人都发布了完整的跟踪解决方案.并且始终是值得信赖的println.但这里的关键技能是能够确切地确定爆炸的是什么.一旦你知道通常清楚为什么,但是当你无法分辨输入是什么时,有时需要打印输出.