<< Back to previous view

[TMACRO-3] Handling of namespaced symbols Created: 04/Sep/13  Updated: 10/Sep/13

Status: Open
Project: tools.macro
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Minor
Reporter: Dmitry Groshev Assignee: Konrad Hinsen
Resolution: Unresolved Votes: 0
Labels: None


 Description   

Here is a snippet:

(def spec-map
  {:int {:type 'ints}})

(defmacro specialize [type body]
  `(symbol-macrolet [type$ ~(-> spec-map type :type)]
     ~(w/postwalk
       (fn [form]
         (if-let [tag (-> form meta :tag)]
           (if (= tag 'type$)
             (with-meta form {:tag (-> spec-map type :type)})
             form)
           form))
       (mexpand-all body))))

(defmacro caster [x]
  `(type$ ~x))

(specialize :int
 (defn test-getter [x]
   (let [^type$ x x]
     (prn "my type" type$)
     (caster x)
     (aget x 0))))

It's broken, the error is "Unable to resolve symbol: type$ in this context". Why is it so? Let's macroexpand it:

(clojure.tools.macro/symbol-macrolet 
    [clojure.core.matrix.impl.ndarray-magic/type$ ints] 
    (def test-getter 
      (fn* ([x] (let* [x x] (prn "my type" type$) (clojure.core.matrix.impl.ndarray-magic/type$ x) (aget x 0))))))

Now, the reason is obvious: symbol-macrolet expects namespaced symbol, and in expanded form "type$" is once namespaced and once not. I think that symbol-macrolet can (should?) ignore namespacing here.



 Comments   
Comment by Konrad Hinsen [ 10/Sep/13 4:09 AM ]

After a bit of thought, I think the right solution is to treat symbol macros like ordinary symbols in evaluation. This means that global definitions (defsymbolmacro) use namespaced symbols, whereas local symbol definitions (symbol-macrolet) accept only plain symbols and raise an exception for qualified symbols, just like let does.

With those rules, the way tools.macro handles namespaces in correct code is correct, but it doesn't do the required error handling because it lets you symbol-macrolet qualified symbols.

Note also that according to those rules, your example code is not correct. You have to write

(symbol-macrolet [~'type$ ...] ...)

and

(defmacro caster [x]
  `(~'type$ ~x))

although you might then prefer to write the latter as

(defmacro caster [x]
   (list 'type$ x))

but that's a matter of taste.

Generated at Thu Oct 02 02:00:59 CDT 2014 using JIRA 4.4#649-r158309.