如果您运行以下内容,则仅打印“foo”:
[
{ "keys": ["f5"], "command": "build" }
]
但是,如果将宏作为参数传递给if,它似乎会立即评估这两个宏。
(if true (println "foo") (println "bar"))
;foo
如何避免同时运行这两个宏并仅根据真实条件对其进行评估?
编辑:
我混淆的主要原因是这可以在普通的lisp中使用。我不知道lisp多么常见地处理编译宏的方式不同,但我猜测它与JVM上的更多自由度有关。
澄清实际代码是创建某种类型的表单而不引用它们作为参数。代码正在迭代并且将变得更复杂,但在当前状态下是:
(defmacro foo
[]
(println "foo"))
(defmacro bar
[]
(println "bar"))
(if true (foo) (bar))
;foo
;bar
我希望在评估if之前不要扩展两个宏,因为将除列表之外的内容传递给bar会导致异常。我现在明白这是不可能的,因为扩展发生在编译时。我已经转而使用多方法 - 这种方法更冗长,但我认为它更具多态性。
答案 0 :(得分:2)
Alan拥有它的权利(就需要立即修复而言),但要说明理由:
宏在编译时评估,而不是运行时。对于仅在运行时已知的内容来说,控制所编译的内容显然是不可能的,因为所有编译都必须在运行时启动之前完成。
答案 1 :(得分:1)
您忘记了"语法引用"。代码应如下所示:
(defmacro foo
[]
`(println "foo"))
(defmacro bar
[]
`(println "bar"))
(if true
(foo)
(bar))
=> FOO
答案 2 :(得分:0)
宏是语法上的抽象。当您看到经常编写的模式时使用它,但由于参数评估,您无法使用函数。宏评估代码并且不应该有副作用,因为你无法控制何时扩展(运行)。
foo
和bar
应该是函数。然后它会像你想象的那样工作。
(defn foo
[]
(println "foo"))
(defn bar
[]
(println "bar"))
(if true
(foo)
(bar)) ; prints "foo"
在不需要宏时使用宏被认为是不好的做法。