<< 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.





[TMACRO-1] Preserve metadata for (at least) unexpanded forms Created: 02/Apr/12  Updated: 02/Apr/12

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

Type: Enhancement Priority: Minor
Reporter: Stephen Compall Assignee: Konrad Hinsen
Resolution: Unresolved Votes: 0
Labels: None
Environment:

Clojure 1.3.0, tools.macro 0.1.1, algo.monads 0.1.0



 Description   

In algo.monads:

(with-monad blah some-code...)

causes all of some-code to report as being on the line of the with-monad form. Could, perhaps, expand-all copy over metadata from the original form, at least in the common case that the form-at-point was not itself expanded?






Generated at Wed Apr 23 05:28:50 CDT 2014 using JIRA 4.4#649-r158309.