Computing macros in clojure

I am trying to translate the following macro from lisp land to clojure:

(defmacro tag (name atts &body body)
  `(progn (print-tag ',name
                     (list ,@(mapcar (lambda (x)
                                       `(cons ',(car x) ,(cdr x)))
                                     (pairs atts)))
                     nil)
          ,@body
          (print-tag ',name nil t)))

But I continue to get stuck with atts, requiring another level of evaluation. For instance. To evaluate t # you need the following:

(defmacro tag [tname atts & body]
  `(do (print-tag '~tname '[~@(map (fn [[h# t#]] [h# t#]) (pair atts))] nil)
     ~@body
     (print-tag '~tname nil true)))

Because he creates things like:

(tag mytag [color 'blue size 'big])
<mytag color="(quote blue)" size="(quote big)"><\mytag>

Where I want the attribute to be evaluated. If I use "(eval t #)" in the above example, I encounter such problems:

(defn mytag [col] (tag mytag [colour col]))
java.lang.UnsupportedOperationException: Can't eval locals (NO_SOURCE_FILE:1)

Any suggestions?

Why does it seem that one less high level of assessment occurs in Clojure?

Definitions of helper functions:

;note doesn't handle nils because I'm dumb
(defn pair [init-lst]
      (loop [lst init-lst item nil pairs []]
    (if (empty? lst)
      pairs
      (if item
        (recur (rest lst) nil (conj pairs [item (first lst)]))
        (recur (rest lst) (first lst) pairs)))))

(defn print-tag [name alst closing]
      (print "<")
      (when closing
    (print "\\"))
      (print name)
      (doall
      (map (fn [[h t]]
           (printf " %s=\"%s\"" h t))
       alst))
      (print ">"))

(For some reason, I did not perform the pair function in the same way as the book, which means that it does not handle zero correctly)

+5
source share
3 answers

Clojure tag , lisp . - ' /, map, , , , .

, , Clojure: - , - print-tag, - ; .

(defmacro tag [name attrs & body]
  `(str "<" 
        (clojure.string/join " "
                             ['~name
                              ~@(for [[name val] (partition 2 attrs)]
                                  `(str '~name "=\"" ~val "\""))])
        ">"
        ~@body
        "</" '~name ">"))

user> (tag head [foo (+ 1 2)] "TEST" (tag sample []))
"<head foo=\"3\">TEST<sample></sample></head>"

, , . , (partition 2...), .

, , XML Clojure, . XML , Hiccup, prxml data.xml.

+4

- , , , , , , , , ,


(defmacro tag [tname atts & body]
  `(do (print-tag '~tname [~@(map (fn [[h# t#]] [h# t#]) (pair atts))] nil)
       ~@body
       (print-tag '~tname nil true)))

(tag mytag ['color 'blue 'size 'big])

<mytag color="blue" size="big"><\mytag>nil

clojure.

0
source

For completeness, what I wanted was:

(defmacro tag [tname atts & body]
  `(do (print-tag '~tname [~@(map (fn [[h# t#]] [`'~h# t#]) (pair atts))] nil)
     ~@body
     (print-tag '~tname nil true)))
0
source

All Articles