为什么Clojure 1.3说变量在我声明它们是动态的时候没有被声明为动态的?

Gre*_*ams 7 compatibility version clojure dynamic leiningen

我正在将工作Clojure代码(在Leiningen项目中)从1.2移植到1.3并且存在问题.除了代码本身不再有效之外,我收到了许多类似这样的警告消息:

Warning: *tooltip-width* not declared dynamic and thus is not dynamically rebindable, 
but its name suggests otherwise. Please either indicate ^:dynamic *tooltip-width* 
or change the name.
Run Code Online (Sandbox Code Playgroud)

这种情况正在发生,即使我已经做了正如我正在用来保持状态的vars的正确修改.例如,对于上面的错误,代码已包含以下内容:

(def ^:dyanamic *tooltip-width*   (* 1.8 *slip-width*))
Run Code Online (Sandbox Code Playgroud)

我在两个地方得到这些错误:首先,从命令行,执行的结果lein swank; 第二,来自Emacs REPL,在core.clj使用后编译我的文件C-c C-w.

要绝对完整,这是我的project.clj文件:

(defproject infwb "1.0.0-SNAPSHOT"
  :description "an evolving, experimental workspace for manipulating infocards"
  :main infwb.core

  :dependencies [[org.clojure/clojure "1.3"]
             [seesaw "1.2.1"]
         [org.clojars.gw666/sxqj "beta2"]
         [org.clojars.gw666/piccolo2dcore "1.3"]
         [org.clojars.gw666/piccolo2dextras "1.3"]
         [com.miglayout/miglayout "3.7.4"]
         ]
  :dev-dependencies [[swank-clojure "1.3.2"]
             [org.clojars.weavejester/autodoc "0.9.0"]]
  :autodoc {:name "Infocard Workbench (InfWb)",
        :web-src-dir "https://github.com/gw666/infwb/blob"})
Run Code Online (Sandbox Code Playgroud)

除了让我的代码正常工作之外,我想了解为什么我会收到这些错误以及为什么我会在两个地方收到这些错误.谢谢你的帮助.

Sco*_*ott 16

这是一个简单的错字.

(def ^:dyanamic ...
Run Code Online (Sandbox Code Playgroud)

应该:

(def ^:dynamic ...
Run Code Online (Sandbox Code Playgroud)

发生在我们所有人身上!


Chr*_*erg 12

您可能需要考虑使用refs或atoms而不是vars来维护状态.

引用Clojure文档:

Vars提供了一种机制来引用可变存储位置,该位置可以基于每个线程动态地反弹(到新的存储位置).

(强调我的.)

可以使用binding宏将Vars设置为新值(对于当前线程).直到Clojure 1.2,任何var都可以像这样反弹,但是因为需要明确声明Clojure 1.3 vars ^:dynamic允许这样做.(据我所知,原因是对于没有重新绑定的常见情况,var的查找速度急剧加快.)

这是一个常见的惯例(但仅此而已),以提供像这样的反弹名称的变量:*foobar*.由于这种约定,编译器在看到名为this的未声明为动态的var时会给出警告.

总结一下:

  • 如果您只想声明一个在运行时没有更改的值,请使用var并删除名称周围的*.
  • 如果要基于每个线程更改值,请声明var dynamic.
  • 如果你想保持全球(而不是每个线程)状态,使用其他参照类型之一:atom,ref(如果你需要交易)或agent(异步变化).