2

我有一个关于如何定义函数/宏的问题,这些函数/宏调用其他宏或特殊形式,但传入的符号之一需要是动态的。

这个问题的最简单版本如下所述:

我们可以使用定义变量def

(def x 0)

但是,如果我们希望x以编程方式确定名称以便我们可以做类似的事情怎么办?

(let [a 'b]
  (our-def a 3)) => user/b

我们可以尝试定义一个函数

(defn defn2 [sym val]
  (def sym val))

然而它并没有做我们想要的

(def2 'y 1)   => #'user/sym

起初它似乎是一个宏工作(即使它似乎是不必要的)

(defmacro def3 [sym val]
  `(def ~sym ~val))

(def3 z 2) => user/z

但这只是肤浅的,因为我们真的回到了我们从常规 def 开始的地方。

(let [a 'b]
  (def3 a 3)) => user/a

如果我使用eval,我可以做到,但似乎没有eval必要

(defn def4 [sym val]
  (eval `(def ~sym ~val)))

(let [a 'b]
  (def4 a 4)) => user/b

如果有其他内置命令可以实现这个特定的示例,那么它们并不是我真正想要的,因为def它只是为了展示一个特定的示例。有些宏比def我可能想要调用的更复杂,而且不必担心它们是如何在内部实现的。

4

1 回答 1

1

第一:正确的做法是使用以 开头的宏,def...因为这是人们一直在做 defs 的方式,对用户来说并不奇怪。

回答你的问题:使用实习生

(def foo 'bar)
(intern *ns* foo :hi)
(pr bar) ;; => :hi
(intern *ns* foo :hi2)
(pr bar) ;; => :hi2

如果要使用宏,请执行以下操作:

(def z 'aa)
(defmacro def3 [sym val]
  `(def ~(eval sym) ~val))
(def3 z 2)
(pr aa) ;; => 2
于 2015-08-16T00:22:11.457 回答