defn和defmacro之间有什么区别? [英] What is the difference between defn and defmacro?

查看:295
本文介绍了defn和defmacro之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

defn和defmacro有什么区别?

What is the difference between defn and defmacro? What is the difference between a function and a macro?

推荐答案

defn 定义一个函数, defmacro 定义一个宏。

defn defines a function, defmacro defines a macro.

函数和宏之间的区别是函数调用函数的参数被求值,然后函数的主体使用参数求值。

The difference between functions and macros is that on a function call first the arguments of the function are evaluated then the body of the function is evaluated using the arguments.

另一方面,宏描述了从一段代码到另一段代码的转换。任何评估发生在转换之后。

Macros on the other hand describe a transformation from one piece of code to another. Any evaluation takes place after the transformation.

这意味着参数可以被多次计算或根本不被计算。例如是一个宏。如果的第一个参数为false,则永远不会计算第二个参数。如果是一个函数,这是不可能的,因为参数将始终在函数运行之前进行求值。

This means that arguments may be evaluated multiple times or not at all. As an example or is a macro. If the first argument of or is false, the second argument will never be evaluated. If or were a function, this would not be possible, because the arguments would always be evaluated before the function runs.

这样做的另一个后果是,在展开宏之前,宏的参数不必是有效的表达式。例如,您可以定义一个宏 mymacro ,使(mymacro(12 23 +))扩展为(+ 23 12),所以这将工作,即使(12 23 +)本身也是废话。你不能使用函数,因为(12 23 +)将被计算,并导致一个错误,在函数运行之前。

Another consequence of this is that the arguments of a macro need not be a valid expression before the macro is expanded. For example you could define a macro mymacro such that (mymacro (12 23 +)) expands to (+ 23 12), so this will work even though (12 23 +) on its own would be nonsense. You couldn't do that with a function because (12 23 +) would be evaluated, and cause an error, before the function runs.

一个小例子来说明区别:

A small example to illustrate the difference:

(defmacro twice [e] `(do ~e ~e))
(twice (println "foo"))

c $ c>两次获取列表(printlnfoo)作为参数。然后将它转换为列表(do(printlnfoo)(printlnfoo))。这个新代码是执行的代码。

The macro twice gets the list (println "foo") as an argument. It then transforms it into the list (do (println "foo") (println "foo")). This new code is what gets executed.

(defn twice [e] `(do ~e ~e))
(twice (println "foo"))

这里 printlnfoo 立即被评估。由于 println 返回 nil ,用 nil 其论点。 两次现在生成列表(do nil nil)并返回结果。注意,这里(do nil nil)不会被计算为代码,它只是作为一个列表处理。

Here println "foo" is evaluted right away. Since println returns nil, twice is called with nil as its argument. twice now produces the list (do nil nil) and returns that as its result. Note that here (do nil nil) is not evaluated as code, it's just treated as a list.

这篇关于defn和defmacro之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆