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