如何让这个宏按预期工作?

时间:2013-07-09 18:54:27

标签: clojure

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

 gives: (do (choices choice))

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

我希望(+ 1 1)被评估为2然后被用作密钥以使用do执行codde。

然而,扩展的宏为我们提供了无法解决选择和选择的代码。

我尝试了无选择和选择,不起作用。 我在这里缺少什么?

1 个答案:

答案 0 :(得分:3)

Unquoting确实有效,但您需要从常规报价切换到语法报价(反引号)以供引用:

(defmacro switch [choices choice]
  `(do (~choices ~choice)))

请注意,这里不需要do

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

这是一个用以上内容编写的版本:

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

REPL的例子:

user=> (switch {1 (print 1) 2 (print 2)} (+ 1 1))
2nil

2打印printnil是返回值。)