关于clojure名称空间和宏的问题

Mic*_*are 6 macros clojure

假设我有一堆名称空间(苹果,香蕉,橙色).在这些命名空间中,我使用eat宏,它调用(而不是"生成",调用)peel函数.peel每个水果的功能都不同,但宏是相同的,而且相当大,所以我想创建一个fruit包含eat宏的命名空间.但是当我eatapple命名空间调用宏时,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)

那么,关于如何结合宏和多态的任何想法?

Stu*_*rra 7

你所描述的不是多态,而是所谓的本地捕获.你想要宏来"捕捉" 果皮的局部定义.

在大多数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)


z5h*_*z5h 1

编辑:抱歉。我已经发布了以下内容。但你说的是“调用,而不是生成”剥离函数。所以我写的可能不是你想要的,尽管看起来它会得到预期的结果。

简单地引用(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)