耳当てつきのvarはダイナミックスコープを持つと自動的にみなされない

これはClojure 1.3.0のchanges.txtの1.1の日本語訳と解説です。



日本語訳

(def *fred*)
=> Warning: *fred* not declared dynamic and thus is not dynamically rebindable,
but its name suggests otherwise. Please either indicate ^:dynamic *fred* or change the name.
(警告:*fred*は動的と宣言されていないので、動的に再束縛することができませんが、名前がそうでないことをほのめかしています。
^:dynamic *fred*と明示するか、名前を変えてください。)

解説

1.2系のコードを移行する時によく見かける警告です。

Lispから受け継いだ慣習に「ダイナミックスコープを持つ変数は名前の前後をアスタリスクで囲んで宣言する*1」というものがあります。

1.2.xまではすべてのvarがダイナミックスコープを持つ変数だったので、(恐ろしいことに)こんなこともできました。

(defn answer
  []
  (* 2 3 7))
(answer) ;=> 42

;; *が動的に+へと再束縛される
(binding [* +]
  (answer)) ;=> 12

(answer) ;=> 42

1.3から:dynamicメタデータの値がtrueな値のみがダイナミックスコープを持つので、ダイナミックスコープをほのめかしている名前のvarがダイナミックスコープを持たない場合に警告を表示するようになりました。

ダイナミックスコープを持つ変数として使っている場合は:dynamicメタデータを付け加え、慣習を知らずに強調のためにアスタリスクで囲んでいる場合は紛らわしいのでアスタリスクを外しましょう。

(def ^:dynamic *fred*)
;; または
(def fred)

:dynamicメタデータを付け加える際に使った^:dynamicという書き方については、後で別に解説します。

メタデータのこれまでとこれから - OGINO Masanori@はてなで解説しました

*1:この「アスタリスクで囲んだ名前」のことを「耳当てつきの名前」と呼び、前後のアスタリスクを「耳当て」と呼びます。(*´ω`*)ミミアテ