Clojure 轻松地向LISP方言添加跟踪语句(例如,不使用do)

Clojure 轻松地向LISP方言添加跟踪语句(例如,不使用do),clojure,lisp,Clojure,Lisp,当使用命令式编程语言(如Java)编程时,可以方便地添加跟踪语句。例如: for (int i=0; i<10; i++) { // do something // do something System.out.println("Some trace statement"); // do something } 注: 该方法应该相对简单,只需添加一行 例如,如果我要使用do块——我必须重新格式化,确保适当地关闭括号 使用do块: (def fact (fn [n] (

当使用命令式编程语言(如Java)编程时,可以方便地添加跟踪语句。例如:

for (int i=0; i<10; i++) {
  // do something
  // do something
  System.out.println("Some trace statement");
  // do something 
}
注:

  • 该方法应该相对简单,只需添加一行
  • 例如,如果我要使用do块——我必须重新格式化,确保适当地关闭括号

  • 使用
    do
    块:

    (def fact
    (fn [n]
    (loop [cnt n acc 1]
       (if (zero? cnt)
            acc
          (do
            (println "**")
            (recur (dec cnt) (* acc cnt)))))))
    
    user=> (fact 4)
    **
    **
    **
    **
    24
    
    在你的回复中:

    (doc do)
    
    做 (不表达*)
    特殊表格
    按顺序计算表达式并返回 最后。如果未提供表达式,则返回nil。 请看

    无创追踪 Lisp环境通常提供交互式调试环境和跟踪机制。 例如,在SBCL中,您可以使用: 您甚至不需要像在Java示例中那样修改代码

    对于Clojure,请查看,或以下答案:

    自定义函数和宏 另请参见此问题的许多答案: 大多数方法都涉及将要调试/跟踪的表达式嵌套在另一个表达式中,就像Chiron建议的那样

    我不认为“我必须重新格式化并适当关闭括号”是一个好论点;每次编辑程序时,都必须处理语法,否则就永远不会修改代码

    帕雷迪特 我个人不使用我现在是一个快乐的用户。您的编辑器在编写代码时跟踪括号和括号,这非常方便

    读取器宏 如果你真的不想把你的表达式嵌套在另一个表达式中,我想你可以编写一个reader宏,这样你就可以用一个debug语句注释一个表达式,但是这太过分了,imho(edit:显然,这就是它的作用;参见尼尔斯克的答案).

    该库提供了一个简单的选项,用于输入跟踪打印,而无需更改原始语法,这正是您(和许多其他人)喜欢的方式

    还有包括跟踪消息的方法

    spyscope.repl=> #spy/d ^{:marker "triple-add"} (+ 1 2 3)
    spyscope.repl$eval3935.invoke(NO_SOURCE_FILE:1) triple-add (+ 1 2 3) => 6
    6
    
    甚至(部分)堆栈跟踪

    spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3} (+ 1 2 3)))
    ----------------------------------------
    clojure.lang.Compiler.eval(Compiler.java:6477)
    clojure.lang.Compiler.eval(Compiler.java:6511)
    spyscope.repl$eval675.invoke(REPL:13) (+ 1 2 3) => 6
    (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)
    

    我有几个宏允许这样的操作(因为它不需要多次抛出程序):

    (我的痕迹(“你好妈妈”1 2 3)再次出现(十二月碳纳米管)(*acc碳纳米管))

    我的跟踪仅扩展为:

    (项目 (强制跟踪“嗨妈妈”1 2 3) (再次发生(十二月碳纳米管)(*acc碳纳米管)))

    一个更简单的变体是:

    (回音hi mom复发(12月cnt)(*acc cnt))

    它捕获已包装表单的结果,并打印带有hi mom标记的表单

    一个很好的方法是,我可以插入/删除nil作为未计算的第一个参数来关闭/打开跟踪。在一些调试输出时,我只是将跟踪留在原位,但在下次需要时才将其禁用


    -香港

    谢谢你的回答,不过我想找一个比添加do块更方便的表格——我会为可能的观众更新我的问题。最初的问题没有提到OP不想使用
    do
    块。它后来更新了。所以您不想因为重新格式化而使用
    do
    ?你用的是什么编辑器?@Chiron,我的意思是我知道如何用do解决这个问题——不过我总觉得这比我想要的麻烦多——我年轻时用过很多LISP,但我从来没有找到一种方便的方法来向代码中添加跟踪语句。@NielsK这不是一个有效的参数。关于:“我不想在Java代码中添加
    if
    条件,因为我不想重新格式化代码”?@C.WarrenDale我编辑了我的答案,这样Paredit就显得有点突出了more@coredump谢谢直到我发表评论后我才注意到,我忘了编辑它,因为我是一个差劲的网民;)跟踪是一个宏,不是一个函数。那是什么语言
    progn
    看起来像公共Lisp<代码>重复看起来像Clojure。
    spyscope.repl=> #spy/d ^{:marker "triple-add"} (+ 1 2 3)
    spyscope.repl$eval3935.invoke(NO_SOURCE_FILE:1) triple-add (+ 1 2 3) => 6
    6
    
    spyscope.repl=> (take 20 (repeat #spy/d ^{:fs 3} (+ 1 2 3)))
    ----------------------------------------
    clojure.lang.Compiler.eval(Compiler.java:6477)
    clojure.lang.Compiler.eval(Compiler.java:6511)
    spyscope.repl$eval675.invoke(REPL:13) (+ 1 2 3) => 6
    (6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6)