假设我有一堆名称空间(苹果,香蕉,橙色).在这些命名空间中,我使用eat宏,它调用(而不是"生成",调用)peel函数.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)
Run Code Online (Sandbox Code Playgroud)
要强调的是,这意味着只有在宏扩展时才应调用剥离函数,如本例所示.
(ns apple)
(defn peel [] (prn "peeled apple"))
(defmacro eat [] (peel))
(macroexpand-1 '(eat))
Run Code Online (Sandbox Code Playgroud)
那么,关于如何结合宏和多态的任何想法?
你所描述的不是多态,而是所谓的本地捕获.你想要吃宏来"捕捉" 果皮的局部定义.
在大多数Lisp中,这被认为是糟糕的风格,特别是Clojure,因为它可能导致细微和不可预测的错误.
更好的解决方案是在调用时将正确的果皮传递给eat宏:
(ns fruit)
(defmacro eat [peeler] `(~peeler))
(ns apple)
(defn peel [] (prn "Peeled an apple"))
(fruit/eat peel)
Run Code Online (Sandbox Code Playgroud)
如果你真的想进行本地捕获,可以在宏中强制使用〜'(unquote-quote):
(ns fruit)
(defmacro eat [] `(~'peel))
Run Code Online (Sandbox Code Playgroud)
编辑:抱歉。我已经发布了以下内容。但你说的是“调用,而不是生成”剥离函数。所以我写的可能不是你想要的,尽管看起来它会得到预期的结果。
简单地引用(peel)对我有用。
(ns fruit)
(defmacro eat [] '(peel))
(ns apple)
(defn peel [] (prn "peeled apple"))
(fruit/eat)
(ns banana)
(defn peel [] (prn "peeled banana"))
(fruit/eat)
Run Code Online (Sandbox Code Playgroud)