假设我有一堆命名空间(苹果,香蕉,橙色)。在这些 namespace 中,我使用eat
宏,该宏调用peel
函数(而不是“generates”,调用)。每种水果的peel
函数都不同,但是宏是相同的,并且相当大,因此我想创建一个包含fruit
宏的eat
命名空间。但是,当我从eat
命名空间调用apple
宏时,eat
宏应调用apple/peel
函数。
为了说明(但这不起作用):
(ns fruit)
(defmacro eat [] (peel))
(ns apple)
(defn peel [] (prn "peeled apple"))
(fruit/eat)
(ns banana)
(defn peel [] (prn "peeled banana"))
(fruit/eat)
要强调的是,这意味着在宏扩展时(仅在此示例中),才应调用pere函数。
(ns apple)
(defn peel [] (prn "peeled apple"))
(defmacro eat [] (peel))
(macroexpand-1 '(eat))
那么,关于如何组合宏和多态性的任何想法?
最佳答案
您所描述的不是多态,而是所谓的本地捕获。您希望eat宏“捕获”果皮的局部定义。
在大多数Lisps中,尤其是Clojure,这被认为是不良样式,因为它可能导致细微且不可预测的错误。
更好的解决方案是在调用它时将正确的果皮传递给eat宏:
(ns fruit)
(defmacro eat [peeler] `(~peeler))
(ns apple)
(defn peel [] (prn "Peeled an apple"))
(fruit/eat peel)
如果您确实要进行本地捕获,则可以在宏中使用〜'(unquote-quote)将其强制:
(ns fruit)
(defmacro eat [] `(~'peel))