2

私は意図したとおりに動作する以下の関数を思いつきましたが、それは恐ろしいevalを使用しており、私が使用しようとしているClojureScriptには存在しません。

(defn path [d p]
  (eval 
    (concat '[-> d] 
      (flatten (map 
                 #(conj (repeat (dec %) 'z/right) 'z/down) 
                 (path-to-vector p))))))

マクロに変換するにはどうすればよいですか?私の試みは次のようになります。

(defmacro path [d p]
  `(concat (-> ~d)
      (flatten
       (map #(conj (repeat (dec %) z/right) z/down)
             (path-to-vector ~p)))))

しかし、それは明らかに機能しません。

4

2 に答える 2

4

マクロや評価は必要ありません。操作は次のreduceとおりです。

(defn path [d p]
  (reduce (fn [s v]
            (reduce #(%2 %1) s (conj (repeat (dec v) z/right) z/down)))
          d (path-to-vector p)))

また、(conj (repeat (dec %) z/right) z/down)z/down を意味し、すべての z/right coz 繰り返しがシーケンスを返すことに注意してください。(conj (vec (repeat (dec %)) z/right) z/down)

于 2013-05-08T16:31:44.500 に答える
1

これは reduce のケースであり、マクロも eval も適切ではないという Ankur の意見は正しいですが、このようなマクロを作成するメカニズムについては、それ自体のために説明する価値があるかもしれません。

あなたのマクロの例は非常に似ています。必要なのは splicing-unquote 関数だけです。

(defmacro path [d p]
  `(-> ~d 
      ~@(flatten
         (map #(conj (repeat (dec %) z/right) z/down)
               (path-to-vector ~p)))))

これは、マクロ展開時に flatten の呼び出しを評価し、それを結果の s-expression/list に連結します。

于 2013-05-08T18:11:10.117 に答える