打印“评估前完全展开的形式”的 Clojure 函数?

A Clojure function that prints the “fully expanded form before evaluation”?

是否有 Clojure 函数可以为任何函数执行 macroexpand-all 为宏执行的操作?

在 SICP 中,Abelson & Sussman 对此进行了演示,他们称之为“linear recursive process”。

换句话说,如果我们给出:

(factorial 6)

该函数将打印(而不计算):

(* 6 (* 5 (* 4 (* 3 (* 2 (1))))))

本质上,我试图“看到”数据结构任何函数在评估之前“建立”。


我认为这对于初学者(就是我 :) 来说是一种有趣的方式,可以在 Reader(?) 将内容传递给 Evaluator 之前查看它正在构建的内容。 (我不确定我在这里使用的术语是否正确。)

这不存在,因为这不是评估的工作方式。 (* 6 (* 5 (* 4 (* 3 (* 2 1))))) 形式在计算 (factorial 6) 时从不存在,因此运行时不能只是“顺便”给你。

无需编程即可实现功能跟踪。例如,它在 Emacs 的 Cider 扩展中可用。 https://docs.cider.mx/cider/debugging/tracing.html

我已将我的阶乘程序加载到 Emacs 中,并将光标放在 factorial 函数上。

 (ns factorial.core
    (:gen-class))

 (defn factorial [n]
    (if (zero? n)
     1
     (* n (factorial (dec n)))))

 (defn -main
    "A factorial program."
    [& args]

    (let [n 6] 
       (println "The factorial of " n "is" (factorial n))))

             M-x cider-jack-in

 REPL:  (in-ns 'factorial.core)

             C-c M-t v, select factorial when prompted

        (factorial 3)

你的问题实际上归结为函数是如何实现的。 例如,如果阶乘看起来像这样,(也可以用宏来完成)

(defn factorial
  [n]
  (if (<= n 1) 1 (concat `(~'* ~n) (list (factorial (dec n))))))

调用函数后,

(map #(-> % factorial) (range 10)) =>
(1
 1
 (* 2 1)
 (* 3 (* 2 1))
 (* 4 (* 3 (* 2 1)))
 (* 5 (* 4 (* 3 (* 2 1))))
 (* 6 (* 5 (* 4 (* 3 (* 2 1)))))
 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 1))))))
 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 1)))))))
 (* 9 (* 8 (* 7 (* 6 (* 5 (* 4 (* 3 (* 2 1)))))))))

这会被调用。 您可以将宏视为转换函数的函数。只有当函数 factorial 将表达式转换为看起来像上面的嵌套乘法时,宏展开才会给出您要查找的内容。

(map #(-> % factorial eval) (range 10)) ; will give the evaluated values