macros - 构建评估的评估是否等于宏观?

标签 macros lisp common-lisp evaluation

我想知道 nth 的这两个定义是否相等:

我。定义为宏:

(defmacro -nth (n lst)
  (defun f (n1 lst1)
    (cond ((eql n1 0) lst1)
      (t `(cdr ,(f (- n1 1) lst1)))))
  `(car ,(f n lst)))

二。被定义为一堆函数:

(defun f (n lst)
  (cond ((eql n 0) lst)
        (t `(cdr ,(f (- n 1) lst)))))
(defun f1 (n lst)
  `(car ,(f n `',lst)))
(defun --nth (n lst)
  (eval (f1 n lst)))

我的想法正确吗?宏定义是表达式的求值,在其主体中构造?

最佳答案

好的,让我们从头开始。

宏用于创建通常依赖于宏输入的新表单。在编译或评估代码之前,必须展开宏。宏的扩展是在评估使用它的形式之前发生的过程。这种扩展的结果通常是 lisp 形式。

所以在一个宏里面有几个层次的代码。

  • 未引用的代码将在宏扩展期间进行评估(不是在运行时!),在您的示例中,您在扩展宏时定义函数 f(为了什么?) ;
  • 接下来是引用(使用通常的引号或反引号甚至嵌套反引号)代码,它将成为宏扩展结果的一部分(以其文字形式);您可以控制在宏扩展期间将评估代码的哪一部分以及将保持完整(引用,部分或全部)的代码。这允许人们在执行之前构建任何东西。

宏的另一个特点是它在扩展前不评估其参数,而函数会。为了让您了解什么是宏,请看这个(首先想到的是):

(defmacro aif (test then &optional else)
  `(let ((it ,test))
     (if it ,then ,else)))

你可以这样使用它:

CL-USER> (defparameter *x* '((a . 1) (b . 2) (c . 3) (d . 4)))
*X*
CL-USER> (aif (find 'c *x* :key #'car) (1+ (cdr it)) 0)
4

这个宏创建有用的词法绑定(bind),捕获变量 it。检查条件后,您不必重新计算结果,它可以以“then”和“else”的形式访问。仅仅一个函数是不可能做到的,它在语言中引入了新的控件构造。但宏观不仅仅是创造词汇环境。

宏是一个强大的工具。不可能完全描述您可以用它做什么,因为您可以做任何事情。但是 nth 不是你需要宏的东西。要构造 nth 的克隆,您可以尝试编写一个递归函数。

重要的是要注意 LISP 宏是编程世界中最强大的东西,而 LISP 是唯一具有这种能力的语言;-)

为了启发您,我推荐这篇文章:http://www.paulgraham.com/avg.html

要掌握宏,从这样的事情开始:

http://www.gigamonkeys.com/book/macros-defining-your-own.html

然后可能是 Paul Graham 的“On Lisp”,然后是“Let Over Lambda”。

关于macros - 构建评估的评估是否等于宏观?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24041571/

相关文章:

lisp - 嵌入式方案解释器

recursion - 在 Lisp 中合并列表

lisp - 从 CCL 检索(加载)ed 源代码?

macros - Lisp:在宏中扩展属性名称

c - 使用类函数宏检查变量是否已定义

c++ - C/C++ 有哪些图灵完备的宏语言

lisp - 一个简单的 lisp 函数

closures - Pandoric Macro 中的符号如何编译出来?

c++ - strings.h 并用宏检查包装这个宏是否

c++ - 可变参数宏