Lisp:宏与函数 [英] Lisp: Macros vs Functions

查看:337
本文介绍了Lisp:宏与函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了完全理解如此强大的lisp宏,我想到了一个问题.我知道关于宏的一条黄金法则是在函数完成工作时切勿使用宏". 但是,请阅读第9章-实用:构建单元测试框架-从《实用的通用Lisp我》一书中被介绍到下面的宏中,该宏的目的是消除测试用例表达式的重复,并伴有错误标记结果的风险.

In my quest to fully understand the so powerful lisp macros a question came to my mind. I know that a golden rule about macros is the one saying "Never use a macro when a function will do the work". However reading Chapter 9 - Practical: Building a Unit Test Framework - from the book Practical Common Lisp I was introduced to the below macro whose purpose was to get rid of the duplication of the test case expression, with its attendant risk of mislabeling of results.

;; Function defintion. 

(defun report-result (result form)
  (format t "~:[FAIL~;pass~] ... ~a~%" result form))

;; Macro Definition

(defmacro check (form)
  `(report-result ,form ',form))

好的,我了解它的用途,但是我可以使用函数而不是宏来完成它,例如:

OK, I understand its purpose but I could have done it using a function instead of a macro, for instance:

(setf unevaluated.form '(= 2 (+ 2 3)))

(defun my-func (unevaluated.form)
  (report-result (eval unevaluated.form) unevaluated.form))

  1. 这仅是因为给定的宏太简单了吗?
  2. 此外,由于代码本身(如控制结构,函数等)以LIST表示,因此Lisp Macro System相对于它的对手是否具有如此强大的功能?

推荐答案

但是,如果您使用的是宏,则可以这样做:

But if it were a macro you, could have done:

(check (= 2 (+ 2 3)))

要使用某个功能,您必须执行以下操作:

With a function, you have to do:

(check '(= 2 (+ 2 3)))

此外,使用宏(= 2 (+ 2 3))实际上是由编译器编译的,而使用函数时,它是由eval函数求值的,不一定是同一件事.

Also, with the macro the (= 2 (+ 2 3)) is actually compiled by the compiler, whereas with the function it's evaluated by the eval function, not necessarily the same thing.

附录:

是的,它只是在评估功能.现在,这取决于实现.有些人可以解释它,其他人可以编译和执行它.但是,简单的问题是您不了解系统之间的情况.

Yes, it's just evaluating the function. Now what that means is dependent upon the implementation. Some can interpret it, others can compile and execute it. But the simple matter is that you don't know from system to system.

其他人提到的null词汇环境也很重要.

The null lexical environment that others are mentioning is also a big deal.

考虑:

(defun add3f (form)
  (eval `(+ 3 ,form)))

(demacro add3m (form)
  `(+ 3 ,form))

然后观察:

[28]> (add3m (+ 2 3))
8
[29]> (add3f '(+ 2 3))
8
[30]> (let ((x 2)) (add3m (+ x 3)))
8
[31]> (let ((x 2)) (add3f '(+ x 3)))

*** - EVAL: variable X has no value
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead of X.
STORE-VALUE    :R2      Input a new value for X.
ABORT          :R3      Abort main loop
Break 1 [32]> :a

对于大多数用例而言,这确实是非常可恶的.由于eval没有词法环境,因此它无法从封闭的let中看到" x.

That's really quite damning for most use cases. Since the eval has no lexical environment, it can not "see" the x from the enclosing let.

这篇关于Lisp:宏与函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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