gpt4 book ai didi

clojure - 在另一个 Clojure 命名空间中执行代码,为什么需要 eval?

转载 作者:行者123 更新时间:2023-12-04 14:45:42 24 4
gpt4 key购买 nike

我正在查看旧 contrib 宏 with-ns 的实现:

(defmacro with-ns
"Evaluates body in another namespace. ns is either a namespace
object or a symbol. This makes it possible to define functions in
namespaces other than the current one."
[ns & body]
`(binding [*ns* (the-ns ~ns)]
~@(map (fn [form] `(eval '~form)) body)))

我不明白的是需要评估 body 。换句话说,为什么在我想在没有 eval 的情况下访问主体内目标命名空间中的元素的情况下这不起作用(下面的示例)。
user=> (defmacro wns [ns & body] `(binding [*ns* (the-ns ~ns)] ~@body))
#'user/wns
user=> (create-ns 'boofar)
#<Namespace boofar>
user=> (in-ns 'boofar)
#<Namespace boofar>
boofar=> (clojure.core/refer-clojure)
nil
boofar=> (defn xx [a b] (str a b))
#'boofar/xx
boofar=> (xx 5 6)
"56"
boofar=> (in-ns 'user)
#<Namespace user>
user=> (with-ns 'boofar (println *ns*) (xx 5 6))
#<Namespace boofar>
"56"
user=> (wns 'boofar (println *ns*) (xx 5 6))

CompilerException java.lang.RuntimeException:
Unable to resolve symbol: xx in this context,
compiling:(blardy/blardy/form-init3758076021118964250.clj:1:29)
user=> (wns 'boofar (println *ns*))
#<Namespace boofar>
nil

我没问题。我真的不介意,但我想了解这里发生了什么。 xx 显然存在于 boofar 命名空间中,推送 ns 绑定(bind)应该让我在那里,但我不能直接调用它,但是我可以在 clojure.core 中调用一些东西已被提及。如果您想知道,我尝试重新编写宏以使用 in-ns使用相应的try/finally,结果是一样的。

谢谢!

编辑

添加了使用 in-ns 的宏示例.结果与没有相同。
user=> (defmacro wins [ns & body] 
`(let [orig-ns# (ns-name *ns*)]
(try
(in-ns ~ns)
~@body
(finally (in-ns orig-ns#)))))

扩展宏...
user=> (pprint (macroexpand-all '(wins 'boofar2 (xx 7 8))))
(let*
[orig-ns__4137__auto__ (clojure.core/ns-name clojure.core/*ns*)]
(try
(clojure.core/in-ns 'boofar2)
(xx 7 8)
(finally (clojure.core/in-ns orig-ns__4137__auto__))))

使用它...
user=> (defn xx [a b] (str "user/xx [" a " " b "]"))
user=> (in-ns 'boofar2)
boofar2=> (defn xx [a b] (str "boofar2/xx [" a " " b "]"))
boofar2=> (in-ns 'user)
user=> (wins 'boofar2 (xx 7 8))
"user/xx [7 8]"

最佳答案

用 bind 设置 ns 并不能很好地工作,这就是为什么命名空间的文档包含这个 warning :

"The current namespace, *ns* can and should be set only with a call to in-ns or the ns macro, both of which create the namespace if it doesn't exist."

在您的示例中,符号 xx 正在命名空间用户中解析,而不是 *ns* 绑定(bind)到的命名空间:
user> (defn xx [a b] "I'm the xx from ns user")
#'user/xx
user> (wns 'boofar (println *ns*) (xx 5 6))
#<Namespace boofar>
"I'm the xx from ns user"

关于clojure - 在另一个 Clojure 命名空间中执行代码,为什么需要 eval?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20751565/

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