免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 10395 | 回复: 10
打印 上一主题 下一主题

lisp钟macro到底是什么? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-11-02 16:34 |只看该作者 |倒序浏览
再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. ”

但是我还是理解不了,便一起是怎么执行这个宏,产生程序代码的


写得有一些乱,请大虾务必看看,谢谢

论坛徽章:
0
2 [报告]
发表于 2009-11-03 00:07 |只看该作者
宏通常用来生成代码,你可以认为有个预处理的过程,即把宏展开。

When Lisp is interpreted, rather than compiled, the distinction between macro expansion time and runtime is less clear because they're temporally intertwined . Also, the language standard doesn't specify exactly how an interpreter must handle macros--it could expand all the macros in the form being interpreted and then interpret the resulting code, or it could start right in on interpreting the form and expand macros when it hits them.

论坛徽章:
0
3 [报告]
发表于 2009-11-03 13:20 |只看该作者
生成程序的程序,  并不少见.
最常见的各种CGI(perl, python, php程序)生成html程序(当然html严格来说不能算程序设计语言), lex与yacc生成的C程序, 输出PostScript文件的各种程序实际上是在写PostScript这种语言的程序.
C的宏机制(预处理)很简单, 只作一些简单的串处理, 由一个程序(传统上叫cpp)或在编译器里实现; lisp的宏机制实际上由lisp本身来实现, 定义一个宏实际上低层就是在定义一个lisp程序.
这是lisp广为称道的一个特点: lisp并不区分程序和数据. 一个lisp程序(宏)输出一些数据, 这些数据其实是可以被执行的lisp程序.

论坛徽章:
0
4 [报告]
发表于 2009-11-03 13:36 |只看该作者
Common Lisp 不合适入门. 它是作为实际需要而设计的'产业'级的lisp方言. 特性繁多, 宣宾夺主.

要学lisp, scheme更好. sicp这本书, 从头到尾基本没有讲宏.

很多讲C语言的书, 全都反对用宏. 主要是宏这种东西, 在记法上作手脚, 很难掌握, 出了问题不好找出来.
现代一点的语言基本上没有一个有宏机制的.

[ 本帖最后由 chenzengjie 于 2009-11-3 13:37 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2009-11-03 20:22 |只看该作者
原帖由 win_hate 于 2009-11-3 00:07 发表
宏通常用来生成代码,你可以认为有个预处理的过程,即把宏展开。


您可能没理解我的意思
比如
(defmacro haha (var)
      (list ’setq var nil))

这个宏定义,我们调用他(haha x),展开之后是(setq x nil).在这里,而不是简单的替换生成(list 'setq x nil),我的意思是说,在展开的过程中list函数执行了,展开的过程不是简单的替换

编译器或者解释器,怎么会执行list的?

论坛徽章:
0
6 [报告]
发表于 2009-11-03 20:32 |只看该作者
原帖由 chenzengjie 于 2009-11-3 13:20 发表
生成程序的程序,  并不少见.
最常见的各种CGI(perl, python, php程序)生成html程序(当然html严格来说不能算程序设计语言), lex与yacc生成的C程序, 输出PostScript文件的各种程序实际上是在写PostScript这种语言的程序.
C的宏机制(预处理)很简单, 只作一些简单的串处理, 由一个程序(传统上叫cpp)或在编译器里实现; lisp的宏机制实际上由lisp本身来实现, 定义一个宏实际上低层就是在定义一个lisp程序.
这是lisp广为称道的一个特点: lisp并不区分程序和数据. 一个lisp程序(宏)输出一些数据, 这些数据其实是可以被执行的lisp程序.

就是这句最关键的没看懂
请你看看我上面的回帖,关键是他在编译/解释的时候执行了一遍,即执行了list函数

论坛徽章:
0
7 [报告]
发表于 2009-11-03 21:10 |只看该作者
你不要先入为主的认为宏就是简单的串处理, 替换连接什么的。
lisp程序不是串,  是符号表达式.

你可以认为在lisp里定义一个宏就是定义一个函数. 宏在展开时用参数调用函数, 返回的是一个表达式. 然后再执行返回的这个表达式.

我不知道你现在学到哪里了. 不过你不应该在这里钻的太深, 向后看, 理解的全面了很自然就明白宏的原理.

再往后会接触到很多程序和数据混用, 互相作用的例子. 那才是重点.

论坛徽章:
0
8 [报告]
发表于 2009-11-03 22:27 |只看该作者
原帖由 xdshting 于 2009-11-3 20:22 发表

您可能没理解我的意思
比如
(defmacro haha (var)
      (list ’setq var nil))

这个宏定义,我们调用他(haha x),展开之后是(setq x nil).在这里,而不是简单的替换生成(list 'setq x nil),我的意思 ...


我好像理解你说的呀。

展开宏也是解释器负责的,先展开,然后执行。你看我引用的英文,就是你看的那一章里的:

it could expand all the macros in the form being interpreted and then interpret the resulting code,

or it could start right in on interpreting the form and expand macros when it hits them.


这两句各对应一种处理方式。

论坛徽章:
0
9 [报告]
发表于 2009-11-04 17:56 |只看该作者
原帖由 chenzengjie 于 2009-11-3 21:10 发表
你不要先入为主的认为宏就是简单的串处理, 替换连接什么的。
lisp程序不是串,  是符号表达式.

你可以认为在lisp里定义一个宏就是定义一个函数. 宏在展开时用参数调用函数, 返回的是一个表达式. 然后再执行返 ...

非常感谢,有的时候是好钻牛角尖

论坛徽章:
0
10 [报告]
发表于 2009-11-05 22:06 |只看该作者
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!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP