lisp钟macro到底是什么?
再c中的定义是
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
就是一个简单的替换
在编译器之外就可以实现
但在lisp中
(defmacro when (condition &rest body)
`(if ,condition (progn ,@body)))
在里面用到了语言语法成分,比如说,红色的部分,如果这样的话,macro的实现就是语言的一部分了,因为编译器要理解他,并执行它(when (> x 10) (print 'big))而不是简单的替换,产生代码(if (> x 10) (progn (print 'big)))
这是不是书上说的“Perhaps the biggest barrier to a proper understanding of macros is, ironically, that they're so well integrated into the language. ”
但是我还是理解不了,便一起是怎么执行这个宏,产生程序代码的
写得有一些乱,请大虾务必看看,谢谢
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
CL-USER> (defmacro echo (binds &body body)
`((lambda ,(mapcar #'(lambda (var) (if (consp var) (car var) var))
binds)
,@body)
,@(mapcar #'(lambda (var) (if (consp var) (cadr var) nil))
binds)))
ECHO
CL-USER> (echo ((x 2) (y 5)) (+ x y))
7
;;; so power!!
非常感谢,有的时候是好钻牛角尖
我好像理解你说的呀。
展开宏也是解释器负责的,先展开,然后执行。你看我引用的英文,就是你看的那一章里的:
这两句各对应一种处理方式。
你不要先入为主的认为宏就是简单的串处理, 替换连接什么的。
lisp程序不是串, 是符号表达式.
你可以认为在lisp里定义一个宏就是定义一个函数. 宏在展开时用参数调用函数, 返回的是一个表达式. 然后再执行返回的这个表达式.
我不知道你现在学到哪里了. 不过你不应该在这里钻的太深, 向后看, 理解的全面了很自然就明白宏的原理.
再往后会接触到很多程序和数据混用, 互相作用的例子. 那才是重点.
就是这句最关键的没看懂
请你看看我上面的回帖,关键是他在编译/解释的时候执行了一遍,即执行了list函数
您可能没理解我的意思
比如
(defmacro haha (var)
(list ’setq var nil))
这个宏定义,我们调用他(haha x),展开之后是(setq x nil).在这里,而不是简单的替换生成(list 'setq x nil),我的意思是说,在展开的过程中list函数执行了,展开的过程不是简单的替换
编译器或者解释器,怎么会执行list的?
Common Lisp 不合适入门. 它是作为实际需要而设计的'产业'级的lisp方言. 特性繁多, 宣宾夺主.
要学lisp, scheme更好. sicp这本书, 从头到尾基本没有讲宏.
很多讲C语言的书, 全都反对用宏. 主要是宏这种东西, 在记法上作手脚, 很难掌握, 出了问题不好找出来.
现代一点的语言基本上没有一个有宏机制的.
[ 本帖最后由 chenzengjie 于 2009-11-3 13:37 编辑 ]
生成程序的程序, 并不少见.
最常见的各种CGI(perl, python, php程序)生成html程序(当然html严格来说不能算程序设计语言), lex与yacc生成的C程序, 输出PostScript文件的各种程序实际上是在写PostScript这种语言的程序.
C的宏机制(预处理)很简单, 只作一些简单的串处理, 由一个程序(传统上叫cpp)或在编译器里实现; lisp的宏机制实际上由lisp本身来实现, 定义一个宏实际上低层就是在定义一个lisp程序.
这是lisp广为称道的一个特点: lisp并不区分程序和数据. 一个lisp程序(宏)输出一些数据, 这些数据其实是可以被执行的lisp程序.
宏通常用来生成代码,你可以认为有个预处理的过程,即把宏展开。