我在源文件中定义的命名空间中有动态var,如下所示:
(ns mystuff.log ...)
(def ^:dynamic *logging* #{})
我希望能够从REPL中set!
这个var,以便同一源文件中的代码可以查看它。在此示例中,mystuff.log/log
宏查看*logging*
以决定是否打印给定表达式。在REPL中,(set! *logging* #{:whatever})
会很方便,在会话期间多次更改其值。
如何让Leiningen的REPL允许这样做?默认情况下,set!
这样的var会产生IllegalStateException,因为set!
无法更改var的根绑定。 var必须是线程局部的,可由set!
更改。
有没有办法告诉Leiningen将REPL包装成这样的东西,为var创建一个线程局部绑定?
(binding [mystuff.log/*logging* mystuff.log/*logging*]
(the-leiningen-repl ...))
:init
的{{1}}选项,简要解释here,似乎提供了接近的内容。但显然,REPL会调用:repl-options
,这会为在REPL中输入的表达式建立线程局部绑定而为时已晚。
答案 0 :(得分:2)
您可能需要alter-var-root
,而不是set!
。由于没有对REPL进行特殊设置或修改,您可以执行以下操作:
user> (def logging #{})
#'user/logging
user> (alter-var-root #'logging conj :my-new-logger)
#{:my-new-logger}
user> (alter-var-root #'logging conj :another-new-logger)
#{:my-new-logger :another-new-logger}
user> logging
#{:my-new-logger :another-new-logger}
#{:my-new-logger :another-new-logger}
set!
仅修改var的当前线程绑定。 alter-var-root
修改var的根绑定:在所有线程中共享的值,它不被每个线程绑定覆盖。*
*顺便说一下,这就是alter-var-root
没有感叹号的原因。它遵循与修改根绑定的其他形式相同的约定,如def
。