Note that there are some explanatory texts on larger screens.

plurals
  1. PODisconnect between :dynamic metadata and actually-dynamic Vars in Clojure
    primarykey
    data
    text
    <p>I'm learning Clojure and am playing around with dynamic scope. I've discovered a few things:</p> <ul> <li>Adding <code>{:dynamic true}</code> metadata to an existing Var doesn't actually make the Var dynamic. I can kind of see why you'd want this to be the case, but it can be misleading.</li> <li>You can see if a Var is actually dynamic with <code>(.isDynamic #'whatever)</code></li> <li>You can (but probably shouldn't?) change whether a Var is dynamic with <code>(.setDynamic #'whatever)</code></li> </ul> <p>In short, it looks like the dynamic nature of a Var is stored in the guts of the clojure.lang.Var class itself, and setting <code>^:dynamic</code> metadata <em>at def time only</em> will affect that internal state. Changing metadata afterward doesn't appear to affect it. OK, fine.</p> <p>I discovered this when I was looking at the dynamic variables in namespace clojure.core. I checked to see what Vars in that namespace have <code>:dynamic</code> metadata set:</p> <pre><code>user=&gt; (def metadyn (map key (filter #(-&gt; % key resolve meta :dynamic) (ns-publics 'clojure.core)))) #'user/metadyn user=&gt; metadyn (*3 *2 *print-level* *data-readers* *e *print-length* *1 *verbose-defrecords* *clojure-version* *default-data-reader-fn* pr) </code></pre> <p>Rather fewer than I expected, missing things like <code>*out*</code> and <code>*in*</code>.</p> <p>I checked to see what Vars actually <em>are</em> dynamic:</p> <pre><code>user=&gt; (def realdyn (map key (filter #(-&gt; % key resolve .isDynamic) (ns-publics 'clojure.core)))) #'user/realdyn user=&gt; realdyn (*compile-path* *3 *2 *ns* *print-level* *allow-unresolved-vars* *data-readers* *unchecked-math* *math-context* *read-eval* *compile-files* *command-line-args* *warn-on-reflection* *e *flush-on-newline* *out* *print-length* *1 *file* *verbose-defrecords* *clojure-version* *use-context-classloader* *err* *default-data-reader-fn* *agent* pr *print-dup* *print-readably* *fn-loader* *print-meta* *in* *source-path* *compiler-options* *assert*) </code></pre> <p>Lots more.</p> <p>So, the following Vars are dynamic but don't claim to be in their metadata:</p> <pre><code>user=&gt; (clojure.set/difference (set realdyn) (set metadyn)) #{*compile-path* *ns* *allow-unresolved-vars* *unchecked-math* *math-context* *read-eval* *compile-files* *command-line-args* *warn-on-reflection* *flush-on-newline* *out* *file* *use-context-classloader* *err* *agent* *print-dup* *print-readably* *fn-loader* *print-meta* *in* *source-path* *compiler-options* *assert*} </code></pre> <p>My question is simply: is there any significance to this, something I'm missing? Or, is it just a case of sloppy bookkeeping in the Clojure implementation?</p> <p>No practical use for this; just trying to Understand.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload