[CLJ-859] Built in dynamic vars don't have :dynamic metadata Created: 19/Oct/11 Updated: 24/Feb/12
|Affects Version/s:||Release 1.3|
I'm sure 'built in' is probably not the right term here, but I'm not sure what these are called.
I ran into this issue earlier today while fixing a bug in clojail. Built in vars, particularly ones listed here without a source link: http://clojure.github.com/clojure/clojure.core-api.html, do not have :dynamic metadata despite being dynamic. This includes *in*, *out*, and *err* among others. Here are some examples:
|Comment by Ben Smith-Mannschott [ 19/Oct/11 12:03 PM ]|
This recent discussion on the users list seems relevant: Should intern obey :dynamic?.
It seems to boil down to this the information that a Var is dynamic (or not) is duplicated. Once as metadata with the key :dynamic, and once as a boolean field on the Var class which implements Clojure's variables. This boolean can be obtained by calling the method isDynamic() on the Var.
The confusion arises because apparently :dynamic and .isDynamic can get out of sync with each other. .isDynamic is the source of truth in this case.
|Comment by Ben Smith-Mannschott [ 19/Oct/11 12:18 PM ]|
Compiler$Parser.parse(...) finds the :dynamic entry left in the metadata of the symbol by LispReader and passes this on when creating a new DefExpr, which in turn, generates the code that will call setDynamic(...) on the var when it is created at runtime.
As far as I can tell, the :dynamic entry is irrelevant once that has occurred. It seems to be implemented only as a way to communicate (by way of the reader) with the compiler. Once the compiler's gotten the message, it isn't needed anymore. Keeping it around seems to just cause confusion.
Dynamic vars created by the Java layer of Clojure core don't use the :dynamic mechanism, they just setDynamic() directly. That's why they don't have :dynamic in their meta-data map.
Or, perhaps one might consider, for 1.4, replacing :dynamic altogether and just enforcing the established naming convention: *earmuffs* are dynamic, everything-else isn't. (The compile warns about violations of this convention in 1.3.)
|Comment by Andy Fingerhut [ 24/Feb/12 11:39 AM ]|
I recently noticed several lines like this one in core.clj. Depending upon how many symbols are like this, perhaps this method could be used to add :dynamic metadata to symbols in core, along with a unit test to verify that all symbols in core have :dynamic if and only if .isDynamic returns true?
|Comment by Andy Fingerhut [ 24/Feb/12 12:41 PM ]|
Ugh. In my previous comment, by "several lines like this one" I meant to paste the following as an example:
(alter-meta! #'agent assoc :added "1.0")