5

dsというものを作りたいので

(let [a 2]
  (ds a))

->

 "a->2"

(let [a 1 b 2 c 3]
    (ds a b c)) 

->

 "a->1, b->2, c->3"

そしてこれまでのところ、私は次のようになっています:

(defmacro ds3 [a b c] 
     `(clojure.string/join ", " 
          [(str '~a "->" ~a) 
           (str '~b "->" ~b) 
           (str '~c "->" ~c)]))

うまくいくようです:

 (let [ a 1 b 2 c 3]
     (ds3 a b c)) ; "1->1, 2->2, 3->3"

明らかに、ds1 ds2 ds3 などを定義できますが、可変長にする方法を知りたいですか?

4

3 に答える 3

10

どうぞ:

(defmacro ds [& symbols]                                                                                                                             
  `(clojure.string/join ", "                                                                                                                         
                        ~(into [] 
                           (map (fn [s] `(str ~(name s) "->" ~s))  symbols))))                                                                
于 2013-02-04T13:47:57.663 に答える
8

Ankur の答えはおそらく最も実用的ですが、マクロ展開時に実行できる多くの作業を実行時に延期しています。これは便利な演習であり、コンパイル時に実行できる作業の量を確認するために、強力なマクロがもたらす優れたデモンストレーションです。

(defmacro ds [& args]
  `(str ~(str (name (first args)) "->")
        ~(first args)
        ~@(for [arg (rest args)
                clause [(str ", " (name arg) "->") arg]]
            clause)))

(macroexpand-1 '(ds a b c))
=> (clojure.core/str "a->" a ", b->" b ", c->" c)

これにより、実行時に一時オブジェクトを構築することが回避され、絶対最小数の文字列連結が行われます。

于 2013-02-04T20:38:47.867 に答える