|
22 | 22 | Local macros are most useful in the definition of the expansion
|
23 | 23 | of another macro, they may be used anywhere. Global symbol
|
24 | 24 | macros can be used only inside a with-symbol-macros form."}
|
25 |
| - clojure.tools.macro) |
| 25 | + clojure.tools.macro |
| 26 | + [:require clojure.string]) |
26 | 27 |
|
27 | 28 | ; A set of all special forms. Special forms are not macro-expanded, making
|
28 | 29 | ; it impossible to shadow them by macro definitions. For most special
|
|
197 | 198 | (map? exp) (into {} (map expand-all (seq exp)))
|
198 | 199 | :else exp)))
|
199 | 200 |
|
| 201 | +(defn- check-not-qualified |
| 202 | + "Verify that none of the supplied symbols are namespace-qualified" |
| 203 | + [symbols] |
| 204 | + (when (not-every? nil? (map namespace symbols)) |
| 205 | + (throw (Exception. |
| 206 | + (str "Can't macrolet qualified symbol(s): " |
| 207 | + (clojure.string/join ", " |
| 208 | + (map str (filter namespace symbols))))))) |
| 209 | + symbols) |
| 210 | + |
200 | 211 | (defmacro macrolet
|
201 | 212 | "Define local macros that are used in the expansion of exprs. The
|
202 | 213 | syntax is the same as for letfn forms."
|
203 | 214 | [fn-bindings & exprs]
|
204 |
| - (let [names (map first fn-bindings) |
| 215 | + (let [names (check-not-qualified (map first fn-bindings)) |
205 | 216 | name-map (into {} (map (fn [n] [(list 'quote n) n]) names))
|
206 | 217 | macro-map (eval `(letfn ~fn-bindings ~name-map))]
|
207 | 218 | (binding [macro-fns (merge macro-fns macro-map)
|
|
213 | 224 | The syntax is the same as for let forms."
|
214 | 225 | [symbol-bindings & exprs]
|
215 | 226 | (let [symbol-map (into {} (map vec (partition 2 symbol-bindings)))
|
216 |
| - names (keys symbol-map)] |
| 227 | + names (check-not-qualified (keys symbol-map))] |
217 | 228 | (binding [macro-fns (apply dissoc macro-fns names)
|
218 | 229 | macro-symbols (merge macro-symbols symbol-map)]
|
219 | 230 | `(do ~@(doall (map expand-all exprs))))))
|
|
0 commit comments