私はClojureを学んでいて、動的スコープで遊んでいます。私はいくつかのことを発見しました:
- 既存の Var にメタデータを追加
{:dynamic true}
しても、実際には Var は動的になりません。なぜそうなってほしいのかはなんとなくわかりますが、誤解を招く可能性があります。 - Var が実際に動的かどうかを確認するには、
(.isDynamic #'whatever)
- Var が動的であるかどうかを変更することはできます (しかし、おそらくそうすべきではありませんか?)
(.setDynamic #'whatever)
要するに、Var の動的な性質は clojure.lang.Var クラス自体の内部に格納されているように見え、定義時に^:dynamic
メタデータを設定すると、その内部状態にのみ影響します。後でメタデータを変更しても、影響はないようです。いいよ。
名前空間 clojure.core の動的変数を調べていたときに、これを発見しました。:dynamic
その名前空間のどの変数にメタデータが設定されているかを確認しました。
user=> (def metadyn (map key (filter #(-> % key resolve meta :dynamic) (ns-publics 'clojure.core))))
#'user/metadyn
user=> metadyn
(*3 *2 *print-level* *data-readers* *e *print-length* *1 *verbose-defrecords*
*clojure-version* *default-data-reader-fn* pr)
思ったよりも少なく、*out*
やのようなものがありません*in*
でした。
Varsが実際に動的であることを確認しました:
user=> (def realdyn (map key (filter #(-> % key resolve .isDynamic) (ns-publics 'clojure.core))))
#'user/realdyn
user=> 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*)
さらに多く。
したがって、次の Var は動的ですが、メタデータにあると主張していません。
user=> (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*}
私の質問は単純です: これには何か意味がありますか? それとも、Clojure の実装で簿記がずさんなだけなのでしょうか?
これは実用的ではありません。理解しようとしているだけです。