我最近开始阅读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
三个提示可能会让您的生活更轻松:
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
.有两个匿名函数可供选择.
如果将源代码保存在文件中并将其作为脚本执行,它将为您提供包含文件中行号的完整堆栈跟踪.
at net.projecteuler.problem31$apply_if__9.invoke(problem31.clj:7)
Run Code Online (Sandbox Code Playgroud)
注意,您还可以通过检查*e来检查REPL中的最后一个异常和堆栈跟踪:例如:(.stackTrace*e)堆栈跟踪起初非常令人生畏,因为它会抛出所有Java内部.您需要学会忽略它们,只需查找引用代码的行.在你的情况下,这很容易,因为它们都是从一开始net.projecteuler
您可以命名匿名函数以帮助更快地识别它们:
(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)).当我apply
用map
程序替换似乎工作.
最后,如果你想检查你可能想要查看clojure-contrib.logging
哪些值有一些帮助这种效果的值.有一个间谍宏允许你包装一个表达式,它将返回完全相同的表达式,因此它不会影响你的函数的结果,但会打印出来EXPR = VALUE
,这可能很方便.同样在该组织中,各种人都发布了完整的跟踪解决方案.并且始终是值得信赖的println
.但这里的关键技能是能够确切地确定爆炸的是什么.一旦你知道通常清楚为什么,但是当你无法分辨输入是什么时,有时需要打印输出.
归档时间: |
|
查看次数: |
660 次 |
最近记录: |