我已经提出了下面的函数,它按预期工作,但它使用了非常糟糕的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)))))
但这显然不起作用。
答案 0 :(得分:4)
不需要宏或eval,操作只是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重复返回一个序列,如果你想要所有z / right第一个和最后一个项应该是z / down然后你应该使用{ {1}}
答案 1 :(得分:1)
Ankur是正确的,这是一个减少的情况,并且宏或eval都不合适,尽管它可能仍然值得解释写这样一个宏的机制,因为它本身就是这样:
您的宏示例非常接近,您只需要拼接 - 取消引用功能即可使其工作:
(defmacro path [d p]
`(-> ~d
~@(flatten
(map #(conj (repeat (dec %) z/right) z/down)
(path-to-vector ~p)))))
这会在宏扩展时评估调用以展平,然后将其连接到生成的s-expression /列表中。