Macros 建构性评价是否等同于宏观评价?
我想知道这两个n的定义是否相等: I.定义为宏:Macros 建构性评价是否等同于宏观评价?,macros,lisp,common-lisp,evaluation,Macros,Lisp,Common Lisp,Evaluation,我想知道这两个n的定义是否相等: I.定义为宏: (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))))) (d
(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
- 接下来是引用的代码(使用通常的引号或反引号,甚至嵌套的反引号),它将成为宏扩展结果的一部分(以文本形式);您可以控制在宏扩展期间对代码的哪些部分求值,以及哪些部分保持不变(引用、部分或完全)。这允许在执行之前构造任何内容
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
此宏创建有用的词法绑定,捕获变量it
。检查条件后,您不必重新计算结果,它可以通过“then”和“else”形式访问。仅仅使用一个函数是不可能的,它在语言中引入了新的控件结构。但宏不仅仅是创建词汇环境
宏是一个强大的工具。不可能完全描述你能用它做什么,因为你什么都能做。但是n
并不是需要宏来实现的。要构造第n个的克隆,可以尝试编写递归函数
需要注意的是,LISP宏是编程世界中最强大的东西,LISP是唯一具有这种能力的语言;-)
为了启发您,我推荐这篇文章:
要掌握宏,请从以下内容开始:
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
然后可能是保罗·格雷厄姆的《口齿不清》,然后是《放过拉姆达》。好的,让我们从头开始 宏用于创建通常依赖于宏输入的新表单。在编译或计算代码之前,必须展开宏。宏的展开是在对使用宏的窗体求值之前进行的过程。这种扩展的结果通常是lisp格式 因此,在宏中有几个级别的代码
- 未引用的代码将在宏扩展期间(不是在运行时!)进行计算,在您的示例中,您定义了函数
,当宏被扩展时(为了什么?)李>f
- 接下来是引用的代码(使用通常的引号或反引号,甚至嵌套的反引号),它将成为宏扩展结果的一部分(以文本形式);您可以控制在宏扩展期间对代码的哪些部分求值,以及哪些部分保持不变(引用、部分或完全)。这允许在执行之前构造任何内容
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
此宏创建有用的词法绑定,捕获变量it
。检查条件后,您不必重新计算结果,它可以通过“then”和“else”形式访问。仅仅使用一个函数是不可能的,它在语言中引入了新的控件结构。但宏不仅仅是创建词汇环境
宏是一个强大的工具。不可能完全描述你能用它做什么,因为你什么都能做。但是n
并不是需要宏来实现的。要构造第n个的克隆,可以尝试编写递归函数
需要注意的是,LISP宏是编程世界中最强大的东西,LISP是唯一具有这种能力的语言;-)
为了启发您,我推荐这篇文章:
要掌握宏,请从以下内容开始:
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
然后可能是Paul Graham的“On Lisp”,然后是“Let Over Lambda”。不需要宏或
eval来抽象列表的第n个元素。除非索引是文字数字,否则宏-nth
甚至不起作用。试试这个:
(defparameter test-list '(9 8 7 6 5 4 3 2 1 0))
(defparameter index 3)
(nth index test-list) ; ==> 6 (this is the LISP provided nth)
(-nth index test-list) ; ==> ERROR: index is not a number
n的典型递归解决方案:
(defun nth2 (index list)
(if (<= index 0)
(car list)
(nth2 (1- index) (cdr list))))
(nth2 index test-list) ; ==> 6
通常,当您看到自己的代码重复太多,无法用函数进一步抽象代码时,可以使用宏。您可以制作一个宏来节省编写样板代码的时间。当然,不是标准代码有一个折衷,所以通常在编写样板文件几次之后再编写宏
eval
不应使用,除非您真的必须使用。通常,您可以使用funcall
和apply
进行操作eval
仅在全局范围内工作,因此可以释放闭包变量。不需要宏或eval
进行抽象以获取列表的第n个元素。除非索引是文字数字,否则宏-nth
甚至不起作用。试试这个:
(defparameter test-list '(9 8 7 6 5 4 3 2 1 0))
(defparameter index 3)
(nth index test-list) ; ==> 6 (this is the LISP provided nth)
(-nth index test-list) ; ==> ERROR: index is not a number
n的典型递归解决方案:
(defun nth2 (index list)
(if (<= index 0)
(car list)
(nth2 (1- index) (cdr list))))
(nth2 index test-list) ; ==> 6
通常,当您看到自己的代码重复太多,无法用函数进一步抽象代码时,可以使用宏。您可以制作一个宏来节省编写样板代码的时间。当然,不是标准代码会有一个折衷,所以你通常