【发布时间】:2012-12-28 14:16:36
【问题描述】:
假设我有一个用 clojure 编写的应用程序,它在运行时会生成代码。如何调试该代码 - 我没有源代码?
编辑:我问这个问题是因为我正在和我的同事谈论 clojure,他说由于上述原因,clojure 程序很难(或不可能)测试。我认为这是一种评估者悲观的方法。如果它无法测试,没有人会使用它。
【问题讨论】:
假设我有一个用 clojure 编写的应用程序,它在运行时会生成代码。如何调试该代码 - 我没有源代码?
编辑:我问这个问题是因为我正在和我的同事谈论 clojure,他说由于上述原因,clojure 程序很难(或不可能)测试。我认为这是一种评估者悲观的方法。如果它无法测试,没有人会使用它。
【问题讨论】:
Clojure 为您提供了如此强大的功能,因此您不需要 debug 开发风格,这在其他不太强大的语言(如 java、c++ 等)中很常见。
如果您保持这种编程风格,您将减少真正需要调试的机会。 在您的情况下,您可以通过 REPL 完成所有工作。您可以通过 logging 获取生成“调试”动态代码的函数的输入参数。之后,您将以相同的方式获取此动态代码的输入参数。最后,您将同时拥有生成的“调试”代码和输入参数。因此,您可以轻松重现情况并进行测试。
更新。关于问题的编辑部分,仅仅因为您的程序动态生成代码而说“clojure 程序很难(或不可能)测试”是不正确的。请记住,生成的代码仍然是可以像通常的数据集合一样操作的数据。您无需在断点处构建、运行和冻结整个应用程序即可查看那里发生了什么。我已经描述了测试动态代码的方式。
【讨论】:
您可以尝试使用clojure/tools.trace 中的方法使生成的代码包含某种跟踪。
例如如果您要定义函数,则可以使用 deftrace 而不是 defn,后者会跟踪调用。
来自旧文档(它曾经在 clojure-contrib 中,但从 1.3 开始,它在 clojure/tools.trace 中——此文档来自 contrib 页面编辑: link):
deftrace
用法:(deftrace 名称和定义)
代替defn;跟踪此 fn 的每次调用/返回,包括 论据。对 deftrace 函数的嵌套调用将打印一个 树状结构。
lib 中还有其他方法可能也很方便。
Other debugging suggestions, including where I got the info on the trace lib.
【讨论】:
这有点麻烦,但是如果您将生成的代码写入临时文件并随后加载和评估其内容,那么您将在堆栈跟踪中按行号获取调试信息。
【讨论】:
与所有其他代码一样 - 将调试语句(如日志)添加到代码中。无论如何,F10-F10-F10 样式的调试器对于任何更复杂的代码都是无用的,不应该使用。
【讨论】: