Common Lisp vs Python学习难度

Common Lisp有多复杂?

《Common LISP The Language Second Edition》包含了Common Lisp语言的所有核心内容,但这些内容不包括:网络库、多线程、系统操作等等,这本书有1,096页左右。下图是A4纸打印装订后和《算法导论 第三版》的厚度对比:

1.png

同样只包含语言核心内容的《Learning Python, 5th Edition》就已经超过了1,500页了,覆盖了Python2.7和3.3的内容。而Common Lisp整体变化几乎是微乎其微,标准也有很多年没有做过修正,甚至Paul Graham在1995年写的400多页的《ANSI Common LISP》至今仍是Common Lisp入门的主要书籍(这400多页,附录、索引就占了很多)。而Python语言却越来越走向复杂的路线,对Common Lisp而言,就算要增加新特性,无非就是表面看上去多了几个“函数”而已。

所以,学习一门经久不衰的语言是很值得的,更何况天下语言大多带有Lisp基因?

那学习Lisp的难度在哪儿?无非就是思维的转变。

*比如饱受争议的括号太多。*其他很多语言不仅有小括号,还有中括号和大括号,以及逗号,甚至分号。而Python也是满篇的缩进符,大多人会认为Python的缩进会让可读性更好,正解,读Common Lisp代码,看的也是缩进,而不是括号。比如下面这段代码:

(dolist (i '(1 2 3))
  (print i))

很明显可以从缩进看出print是dolist循环体中的代码,良好的Lisp编辑器都可以很完美地帮你解决缩进问题。有人又会说,那用记事本写的Lisp代码怎么办?我想也没几个人会用记事本写Python吧?就算去掉缩进,Lisp代码仍旧能正确执行,而Python没有了缩进,就没法正确执行了,有个好玩的真实故事:以前有个哥们花了几千块钱从老外手中买了一个漏洞利用脚本,脚本是Python写的,老外在给他时把缩进全部删了,导致他花了很长时间才缩进正确,脚本才能执行……

*不习惯前缀表达式*也是被大多人不能接受的原因,而前缀表达式是Lisp非常强大的地方。

它让Lisp解析器工作起来更加简单:

(+ 1 1)

Lisp解析器把第一个“+”当作函数,其余当作参数。而其他中缀的语言要完整这个加法运算,还需要建立语法抽象树,运算符是运算符,关键字是关键字,函数是函数,分得很明细。在Lisp里,这些用起来感觉全是函数一样,就像上面的代码里“+”不是运算符一样。这又给我们带来个很强大的特性,看看下面这段Common Lisp代码:

(reduce #'+ '(1 2 3))

注:Common Lisp是Lisp-2,所以为了表达函数,需要加“#+”开头

Python里可以这么写吗:

reduce(+, [1, 2, 3])

显然不行,Python中“+”是运算符,上面代码执行会报错:

In [4]: reduce(+, [1, 2, 3])
  File "<ipython-input-6-6ffbf65f8bb7>", line 1
    reduce(+, [1, 2, 3])
	    ^
SyntaxError: invalid syntax

你得这样做:

In [10]: reduce(lambda a, b: a + b, [1, 2, 3])
Out[10]: 6

或者更简单点:

In [11]: import operator

In [21]: reduce(operator.add, [1, 2, 3])
Out[26]: 6

并且前缀表达式还解决了运算符优先级的问题,你不用像写中缀表达式的语言那样停顿下来思考优先级。

学习Python,你得熟悉它的语法,包括怪异的语法。Python随着不断地改进,语法和自身特性也会有变动,这也引发了兼容性的问题。而在Common Lisp中只有括号和前缀,改动几乎很少,如此简单优美的表达方式也可以让你自由定义新功能,新的功能使用起来和本身定义好的无差别,所以很多古老的Lisp代码至今也能运行。

接着就是**编程范式**问题,大多数人以为Lisp就是函数式编程语言,学习Lisp就要学习函数式编程。实际上不对的,在强大的表达方式下,Lisp是多范式的编程语言。Common Lisp和Python一样,它支持面向对象、面向过程和函数式,只是说函数式编程是Lisp常用的编程范式。更悬一点地说,就算某一天某个新的编程范式成为主流,想要Common Lisp支持它,你可以自己去定义。《On Lisp》这本书中,作者就用Common Lisp实现了一个面向对象系统。

学习Python时,你可能会去学元编程,而在Lisp中有更强大的宏;使用类,还得学习面向对象,不仅要学会如何组织类,还要学会设计模式,这种思维模式在Common Lisp中仍可用。Python也有很多地方都是借鉴了Lisp,学习Lisp后,Python水平也会跟着上去的,甚至可以用Lisp的思维写Python代码。

最后,*关于开发环境*,无论使用Python还是Common Lisp,我们都享有REPL。Python有很多好用的商业和免费的IDE,而Common Lisp主要的开发环境是Emacs+Slime,一些商业版的Common Lisp系统也有他们自己的IDE,另外Vim也可以,但大多数还是用的Emacs。虽然说学习Emacs又是一个很高的成本,但是,在学会Common Lisp和Emacs的同时,等同又送了你Elisp,因为Elisp和Common Lisp非常像,这收获是非常丰富的。

所以,综合来说,我觉得Python学起来也不简单,Common Lisp学起来也不难。并且学习Common Lisp收获是很丰富的——在学习过程中可以不断感受着,唯独需要的就是时间和耐心,去习惯那种思维,吸收Lisp中的思想——终身受用。学习Python,你会的仅仅是Python,而学会了Common Lisp,你会的不仅是Common Lisp。