---
title: Clojureのdefmacroで強制的にシンボル捕捉させる
tags: []
categories: ["Programming", "Lisp", "Clojure"]
date: 2010-02-25T18:22:45Z
updated: 2010-03-19T18:09:05Z
---

<p>
Clojureはマクロ定義内のシンボルを名前空間で修飾する。シンボル束縛を回避するためであり、バグを防いでくれるが、次のような書き方をしたいときはNG。
</p>
<pre class="prettyprint lang-cl">
(defmacro foo [x]
  `(defn ~x [x]
     x))
</pre>
<pre class="prettyprint lang-cl">
user> (macroexpand-1 '(foo aaa))
(clojure.core/defn aaa [user/x] user/x)                                                                                              
user> (foo aaa)

Can't use qualified name as parameter: user/x
  [Thrown class java.lang.Exception]

</pre>
<p>
シンボル束縛を強制的に行うためには~'をつける。
</p>
<pre class="prettyprint lang-cl">
(defmacro foo [x]
  `(defn ~x [~'x]
     ~'x))
</pre>
<pre class="prettyprint lang-cl">
user> (macroexpand-1 '(foo aaa))
(clojure.core/defn aaa [x] x)                                                                                                        
user> (foo aaa)
#'user/aaa                                                                                                                           
user> (aaa 100)
100
</pre>
<p>
使うときは要注意。<br/>
尤も、このケースでは<strong>(gensym)を使うべき</strong>なのだが。。。
</p>
<p>
→ （<strong>追記：2010/03/03</strong>）Clojureはマクロ内で使うシンボルの末尾に「#」をつければ勝手にgensymしてくれます。
</p>
<pre class="prettyprint lang-cl">
user> (defmacro foo [x] `(defn ~x [x#] x#))
#'user/foo
user> (macroexpand-1 '(foo aaa))
(clojure.core/defn aaa [x__4956__auto__] x__4956__auto__)
</pre>
