为Clojure宏定义同义词

16

继承自Clojure宏创建函数同义词,我发现def不能用于定义一个宏的同义词。以下是我尝试过但Clojure不允许的示例。

;(def def-function defn)
;(def case cond)
;(def function fn)

在Clojure中是否可以定义宏的同义词/别名?需要使用defmacro吗?

3个回答

34

听起来可能有点嘈杂,但是

(def ^:macro case #'cond)

有效!


这在 cljs 中也适用吗?我尝试时遇到了一些错误,但可能是我做错了其他事情。 - Jeff Evans

8
您可以使用宏:
user=> (defmacro def-function [& args] `(defn ~@args))
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2

或者您可以使用 clojure.contrib.def/defalias

user=> (use 'clojure.contrib.def)
nil
user=> (defalias def-function defn)
#'user/def-function
user=> (def-function g [] 2)
#'user/g
user=> (g)
2

3
现在已经没有类似于clojure.contrib.def的东西了。 - micrub

2
基本上,要做到这一点,您需要将宏完全重写为原始内容,只需替换不同的名称(当然,您会使用defmacro来完成此操作)。这是唯一可能的方式,因为宏不返回值,而只是编写代码,随后对其进行评估。 def需要将名称绑定到一个值,而不是代码块。

(def symbol init?)

创建并将具有符号名称和当前命名空间(ns)值的全局变量映射或定位。如果提供了init,则对其进行评估,并将var的根绑定设置为生成的值。如果未提供init,则var的根绑定不受影响。def总是应用于根绑定,即使在调用def时,var在线程中绑定。 def生成var本身(而不是其值)。如果symbol已经存在于命名空间中并且未映射到interned var,则引发异常。

来自Clojure: Special Forms 宏不评估它们的形式:

宏是操纵形式的函数,允许语法抽象。如果调用的运算符是命名全局变量的符号,该全局变量是宏函数,则调用该宏函数并传递未评估的操作数形式[斜体为我的]。然后在其位置上评估宏的返回值。

来自Clojure: Evaluation 总之,宏的要点是延迟评估,因此它不能为def提供绑定到符号的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接