Clojure 计算宏时出现NullPointerException
我正在编写一个宏来实现Clojure 计算宏时出现NullPointerException,clojure,Clojure,我正在编写一个宏来实现当内置宏时,代码如下: (defmacro when-valid "Macro that does a series of actions if the condition is true" [condition & actions] `(if ~condition (~cons 'do ~actions) nil)) 但当我这样评价它时: (when-valid (< 1 2) (println "hello") (println "d
当
内置宏时,代码如下:
(defmacro when-valid
"Macro that does a series of actions if the condition
is true"
[condition & actions]
`(if ~condition (~cons 'do ~actions) nil))
但当我这样评价它时:
(when-valid (< 1 2) (println "hello") (println "dear"))
我应该得到nil
而不是NullPointerException
。
有人知道我做错了什么吗
谢谢。让我们看看宏观扩张阶段会发生什么:
(macroexpand '(when-valid (< 1 2) (println "hello") (println "dear")))
当Clojure计算此代码时,它将看到(println“hello”)
是一个列表,因此它将对其进行计算,假设返回的结果是一个函数,并尝试调用该函数。当然,(println“hello”)
返回nil,
因此您得到一个NullPointerException
为什么会这样?让我们仔细看看你的宏观经济正在做什么:
(defmacro when-valid
"Macro that does a series of actions if the condition is true"
[condition & actions]
`(if ~condition
(~cons 'do ~actions)
nil))
这将返回一个列表,其前两项是if
符号和条件
表达式,最后一项是nil
。到目前为止,一切顺利。但是在“then”子句中,不是得到一个由do
符号和actions
表达式组成的列表,而是得到一个包含以下三项的列表:
cons
函数(不是符号,因为您使用~
解析cons
'do
,扩展为(引号do)
操作
表达式包装在一个列表中,因为您使用了unquote(~
)而不是unquote-splice(~@
)(defmacro when-valid
"Macro that does a series of actions if the condition is true"
[condition & actions]
`(if ~condition
(do ~@actions)))
自从“那时”表达式仍在语法引号内,
do
符号将被正确引用。通过使用~@
,您可以将操作
序列展开为一个列表,在开始时使用do
,而不是将其包装为一个序列,这将导致上述问题。我还省略了最后的if
表达式中。让我们看看在宏扩展阶段会发生什么:
(macroexpand '(when-valid (< 1 2) (println "hello") (println "dear")))
当Clojure计算此代码时,它将看到(println“hello”)
是一个列表,因此它将对其进行计算,假设返回的结果是一个函数,并尝试调用该函数。当然,(println“hello”)
返回nil,
因此您会得到一个NullPointerException
为什么会这样呢?让我们仔细看看你的宏观经济正在做什么:
(defmacro when-valid
"Macro that does a series of actions if the condition is true"
[condition & actions]
`(if ~condition
(~cons 'do ~actions)
nil))
这将返回一个列表,其前两项是if
符号和条件
表达式,最后一项是nil
。到目前为止,一切正常。但在“then”中子句,而不是得到一个由do
符号和actions
表达式组成的列表,而是得到一个包含以下三项的列表:
cons
函数(不是符号,因为您使用~
解析cons
'do
,扩展为(引号do)
操作
表达式包装在一个列表中,因为您使用了unquote(~
)而不是unquote-splice(~@
)(defmacro when-valid
"Macro that does a series of actions if the condition is true"
[condition & actions]
`(if ~condition
(do ~@actions)))
自从“那时”表达式仍在语法引号内,do
符号将被正确引用。通过使用~@
,您可以将操作
序列展开为一个列表,在开始时使用do
,而不是将其包装为一个序列,这将导致上述问题。我还省略了最后的if
表达式中