gpt4 book ai didi

clojure - 为什么 dotrace 会在这里抛出 StackOverflowError?

转载 作者:行者123 更新时间:2023-12-04 11:31:22 25 4
gpt4 key购买 nike

(use '[clojure.contrib.trace])
(dotrace [str] (reduce str [\a \b]))

最佳答案

简而言之:

那是因为 trace-fn-call ,这就是 dotrace用于包装要跟踪的函数,使用 str生产漂亮的TRACE foo => val输出。

扩展解释:
dotrace宏通过为每个包含要跟踪的函数的 Var 安装线程绑定(bind)来发挥其魔力;在这种情况下,有一个这样的 Var,clojure.core/str .替换看起来大致如下:

(let [f @#'str]
(fn [& args]
(trace-fn-call 'str f args)))
trace-fn-call , 引用其文档字符串,“使用 args 跟踪对函数 f 的单个调用。”。在此过程中,它调用跟踪函数,记下返回值,打印出一个很好的信息性消息,格式为 TRACE foo => val。并返回从跟踪函数获得的值,以便可以继续常规执行。

如上所述,这个 TRACE foo => val使用 str 生成消息;然而,在手头的情况下,这实际上是被跟踪的函数,所以对它的调用会导致对 trace-fn-call 的另一个调用。 ,它自己尝试使用 str 生成跟踪输出字符串,这导致再次调用 trace-fn-call ...最终导致堆栈爆炸。

一种解决方法:
dotrace 的以下修改版本和 trace-fn-call即使在核心变量存在奇怪绑定(bind)的情况下也应该可以正常工作(请注意, future 可能不会及时安排;如果这是一个问题,请参见下文):
(defn my-trace-fn-call
"Traces a single call to a function f with args. 'name' is the
symbol name of the function."
[name f args]
(let [id (gensym "t")]
@(future (tracer id (str (trace-indent) (pr-str (cons name args)))))
(let [value (binding [*trace-depth* (inc *trace-depth*)]
(apply f args))]
@(future (tracer id (str (trace-indent) "=> " (pr-str value))))
value)))

(defmacro my-dotrace
"Given a sequence of function identifiers, evaluate the body
expressions in an environment in which the identifiers are bound to
the traced functions. Does not work on inlined functions,
such as clojure.core/+"
[fnames & exprs]
`(binding [~@(interleave fnames
(for [fname fnames]
`(let [f# @(var ~fname)]
(fn [& args#]
(my-trace-fn-call '~fname f# args#)))))]
~@exprs))

(在常规 trace-fn-call 周围重新绑定(bind) dotrace 显然不起作用;我的猜测是这是因为 clojure.* Var 调用仍然由编译器硬连线,但这是另一回事。无论如何,上面的方法都可以。 )

另一种方法是使用上述 my-dotrace宏和 my-trace-fn-call函数不使用 future ,但修改为调用 clojure.contrib.trace 的自定义替换使用以下代替 str 的函数:
(defn my-str [& args] (apply (.getRoot #'clojure.core/str) args))

替换是简单而乏味的,我从答案中省略了它们。

关于clojure - 为什么 dotrace 会在这里抛出 StackOverflowError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2977801/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com