lisp中getkword输入默认_Lisp: 我不是为了 (zhuang) 宏(bi),我只是为了(ke)读(du)取(xing)...

注意:这儿的例子仅仅在 https://github.com/jlongster/outlet 有效,请参考你熟悉的 lisp/scheme 版本中的 read (或者叫其他的什么 forms ) 相关文档。

真理是:真的不是为了(zhuang)宏(bi)而宏的。

Lisp 的优势更长远。让我们停止把宏往人脸上糊(并且说宏是唯一更好的抽象方式)。那些人想不通是因为这需要亲自体会。如果只用普通的函数就很合适的情况下还用宏,就更让人困惑了。"Why do you need a macro(宏)? I can abstract the same thing with a function!"

我不是为了 (zhuang) 宏(bi),我只是为了(ke)读(du)取(xing)

read 是一个内置的读取对象的函数,在大多数的 lisp 实现中。对象可以是任何原子(数字,字符串,等等),或者一个数据结构比如 list,下面是例子:

(read "3") ; 3

(read "foo") ; '>>> 'foo

(read "\"foo\"") ; "foo"

(read "(foo bar baz)") ; (list 'foo 'bar 'baz)

稍等,看看 lisp 的代码,他真的都是 list 组成的:

(define (foo x)

(+ x 1))

一旦你理解了 lisp 代码就是数据 (即:atom 列表),那么你懂了,你能用 read in 来读取 lisp 代码作为数据。由于 lisp 提供了一组函数,优雅的处理列表,解析 lisp 代码突然就变得很简单了。

举个栗子:

;; program.lisp

(define (foo x)

(+ x 1))

;; our parser

;; get-file-contents returns a file's contents as a string

;; (defined elsewhere)

(define src (get-file-contents "program.lisp"))

;; src is a string, turn it into data

(define forms (read src))

;; `car` retrieves the first item of a list

(display (car forms)) ; 'define

;; `cons` puts an item at the beginning of the list

;; `cdr` gets the rest of the list after the first item

;; `cadr` is a combination, equal to (car (cdr x))

;; `cddr` is a combination, equal to (cdr (cdr x))

(let ((name-args (cadr forms)))

(cons 'lambda

(cons (cdr name-args)

(cddr forms))))

;; output: (lambda (x) (+ x 1))

我们这就写了个把所有的 define 表达式转换为 lambda 表达式。

这应该是另人印象深刻的。python js 你怎么做?你需要转换成 ast ,还要学习很多内置方法来解析他。在 lisp 代码就是 ast 结构的数据。

把 read 看成 js 中的 JSON.parse ,js 代码和数据是不同的, JSON.parse 也不能解析所有的东西。在 lisp 他们都是一样的。

宏究竟是啥?它只为了读取打包的漂漂亮亮的数据到正式系统中。你能在编译器上安装宏功能。编译器把程序作为数据读入,用解析并查找宏调用的方式展开他。当找到一个宏调用,编译器把程序作为数据传给宏,这时你可以对程序做任何事情。然后你返回一些数据给编译器,作为代码来解析执行。

如果你依然没被说服,这里,你能写一个 30 行的 lisp 来实现一个宏系统 https://gist.github.com/1712455,你只需要 read ,并且它很简单。

所以这有什么意义呢

我不想这篇文章变成“Lisp 真是太酷啦”类型的又一篇文章,每个语言都有他自己的益处,选择你喜欢的。

我只想解释清楚,为什么 lisp 族人呼吁宏。他基于 lisp 代码即数据的事实,象征着更强大的一种能力。如果你真的对此好奇,我鼓励你跟随所想,你会发现你想知道的东西。

一些例子,有这些功能的话那么:调试工具变得很容易写(比如一个 40行 tracer https://gist.github.com/1840230 )单元测试能追踪到失败的原始表达式,所以它能展示出错误背后真正所发生的情况。我很难展示出这特性所包含的所有潜力。

Viaweb 编辑器的源代码,可能有 20 - 25%的宏。宏比普通的 lisp 函数难写,而且在没必要使用宏的地方,宏被视作不好的代码风格。所以每个宏都是不得不用的时候才写的。也就是说至少 20 - 25% 的代码功能很难用任何别的语言轻易的做到的。无论如何,炮灰猴子可能依然怀疑这神秘的 lisp 能力,这应该会让他感到很古怪。

如果函数比宏更合适,不要考虑这么小的尺度。在更大的尺度上考虑,如果你能写一个解析器来对你的代码做一些疯狂的必要的事情,也许这只要 50 行代码,这是别的语言无法做到的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值