Clojure 如何使该宏按预期工作?

Clojure 如何使该宏按预期工作?,clojure,Clojure,为了学习宏,我想模拟switch case,在这里我将给出一个字典,其中case作为键,代码作为值执行 我希望(+1)被计算为2,然后被用作键,让codde用do执行 然而,扩展的宏给我们的代码不能解析选项和选项 我试着取消了一个又一个的选择,但不起作用。 我在这里遗漏了什么?取消报价确实有效,但您需要从常规报价切换到语法报价(反勾选)进行报价: (defmacro switch [choices choice] '(do (choices choice))) (macroexpand-1

为了学习宏,我想模拟switch case,在这里我将给出一个字典,其中case作为键,代码作为值执行

我希望(+1)被计算为2,然后被用作键,让codde用do执行

然而,扩展的宏给我们的代码不能解析选项和选项

我试着取消了一个又一个的选择,但不起作用。
我在这里遗漏了什么?

取消报价确实有效,但您需要从常规报价切换到语法报价(反勾选)进行报价:

 (defmacro switch [choices choice] '(do (choices choice)))
 (macroexpand-1 '(switch {1 (print 1) 2 (print 2)} (+ 1 1)))

 gives: (do (choices choice))
请注意,此处的
do
是不必要的

请注意,使用此版本的
switch
,将对示例中的两个
print
调用进行求值,因为它们将在switch的输出中以值表达式的形式出现。要有条件地打印,您必须使用一些条件构造(
if
case
或扩展到其中一个的东西)。我还将指出,
choices
参数必须是一个文字映射,否则宏将无法获取键和值(在任何情况下,值都将由外部上下文计算)

以下是一个考虑到上述内容的版本:

(defmacro switch [choices choice]
  `(do (~choices ~choice)))
REPL中的示例:

(defmacro switch [choices choice]
  `(case ~choice ~@(apply concat choices)))

2
print
调用打印,
nil
是返回值。)

语法引用与引用有何不同?主要区别在于取消引用,使用语法引用可以如上所述取消引用。另一个经常出现的区别是自动生成符号,以防止无意中捕获符号。基本上,使用语法quote可以执行的任何操作都可以使用quote和一组足够奇特的cons和concat调用。它还将非命名空间限定符号解析为变量,并将其替换为输出中命名这些变量的命名空间限定符号。(在不方便的时候,可以通过将取消报价与常规报价相结合来避免这种情况;大多数情况下,这是一个很好的功能。)
user=> (switch {1 (print 1) 2 (print 2)} (+ 1 1))
2nil