Why does Clojure 1.3 say that variables are not declared dynamic if I declared them dynamic?

I am porting the working Clojure code (to the Leiningen project) from 1.2 to 1.3 and having problems. In addition to the fact that the code itself no longer works, I get dozens of warning messages like this:

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. 

This happens, although I have already done what looks like the correct changes to the vars that I use to maintain state. For the above error, for example, the code already includes the following:

 (def ^:dyanamic *tooltip-width* (* 1.8 *slip-width*)) 

I get these errors in two places: first, from the command line, as a result of lein swank ; and secondly from Emacs REPL after compiling my core.clj file with Cc Cw .

To be absolutely complete, here is my project.clj file:

 (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"}) 

In addition to getting my code, I would like to understand why I get these errors and why I get them in both places. Thank you for your help.

+7
source share
2 answers

This is a simple typo.

 (def ^:dyanamic ... 

it should be:

 (def ^:dynamic ... 

Happens for all of us!

+15
source

You might want to consider using links or atoms instead of vars to maintain state.

To list the Clojure documentation:

Vars provides a mechanism for referencing a mutable storage location that can be dynamically restored (to a new storage) for each thread.

(Emphasize mine.)

Vars can be set to a new value (for the current thread) using the binding macro. Before Clojure 1.2, any var can be bounced like this, but since Clojure 1.3 vars must be explicitly declared as ^:dynamic in order to allow this. (As far as I know, the reason is a sharp acceleration of the search for variables in the usual case without overwriting).

This is a common convention (but nothing more) to give vars that are designed to bounce names like this: *foobar* . Because of this convention, the compiler issues a warning when it sees a variable with a name like this that is not declared dynamic.

Summarizing:

  • If you just want to declare a value that does not change at run time, use the var variable and leave * around the name.
  • If you want to change the value for each thread, declare the var variable.
  • If you want to maintain global state (not for a stream), use one of the other reference types: atom , ref (if you need transactions) or agent (for asynchronous changes).
+11
source

All Articles