• Lisp的“失败”就是由于它太成功了
  • 发布于 2个月前
  • 164 热度
    0 评论
  • 0 粉丝 5 篇博客
  •   
我学习Lisp的主要原因是受了那些大神的蛊惑,说它是有史以来最强大的语言,厉害的程序员都用Lisp...... 于是我也心痒痒地去学了。

刚开始的时候,主要是忍受着它那前缀表达式和大量的括号,去学习它的函数式编程,这时候没觉得Lisp有多厉害,等到学到了宏(macro)这个主题的时候,就被Lisp的变态的能力真正地震撼了:这不是一门简单的编程语言,它是一门创造其他语言的语言,尤其是把代码当成数据来处理,实在是刷新三观。

大家经常用Java中的循环来做距离,最早的时候它只有for循环,没有for each ,用起来很不爽。

Java程序员也没有办法,只能眼巴巴地看着别的语言的for-each,与此同时祈祷下一版的JDK中也有这个特性。

但是对于Lisp程序员,这就是小菜一碟,你不是没有for-each 吗, 我用宏自己写一个,然后直接就可以用了,更牛X的是这个新写的for-each 和Lisp中其他的关键字具备同等地位,相当于把语言增强了。

就是由于这种变态的元编程能力, “Lisp 赋予了你自定义操作符的自由,因而你得以随心所欲地将它塑造成你所需要的语言。如果你在写一个文本编辑器,那么可以把 Lisp 转换成专门写文本编辑器的语言。如果你在编写 CAD ,那么可以把 Lisp 转换成专用于写 CAD 程序的语言。”  --- Paul Graham 《On Lisp》。

你还可以把Lisp转换为专门用于处理订单的语言,专门用于查询数据库的语言...... 这是不是非常酷?

文本编辑器,CAD,订单,数据库查询就是所谓的业务领域(Domain),Lisp可以变成领域特地语言,即DSL(Domain Specific Language)。

Lisp在制造别的语言(DSL)时是如此的成功,以至于它最终走向了“失败”。

很多语言解决问题的思路是分而治之:把一个大任务拆分成一个个小任务,再把小任务拆分成更小的任务,然后去编码实现。

Lisp则有着截然不同的思路,由于其强大的能力,Lisp程序员倾向于改造Lisp,把这门语言改造成一个问题领域相关的语言,即DSL ,然后用这个DSL来轻松编程,去解决问题。

当然这个改造的过程是个渐进式的:

“在编程的时候你可能会想 'Lisp 要是有这样或者那样的操作符就好了。' 那你就可以直接去实现它。之后,你会意识到使用新的操作符也可以简化程序中另一部分的设计,如此种种。语言和程序一同演进。就像交战两国的边界一样,语言和程序的界限不断地移动,直到最终沿着山脉和河流确定下来,这也就是你要解决的问题本身的自然边界。最后你的程序看起来就好像语言就是为解决它而设计的。并且当语言和程序彼此都配合得非常完美时,你得到的将是清晰、简短和高效的代码。”    --- Paul Graham 《On Lisp》。

这种使用DSL去解决问题的方法有什么问题呢?

碎片化!  会出现很多“小语言”,这些语言之间有细微的不同,这就是为什么你的Lisp代码对别人来说读起来很吃力的原因。 

而其他语言则不存在这个问题,相对容易去理解代码的含义。Lisp, 由于其变态的表达能力, 一个符号可能是个变量,函数,操作符。你需要花费大量时间去阅读代码才能搞清楚它到底是什么含义,这就太悲催了。

Lisp的“失败”的一大原因就是它的碎片化,而碎片化又源于语言本身的特性和它那用DSL解决问题的风格。

注意,我在说“失败”的时候,一直用引号, Lisp真的失败了吗?No!Lisp的思想已经进入到了现在主流的语言中,无论是Python,JavaScript,甚至Java都具备函数式编程的能力,还有像Scala这样既能OOP,又能FP的语言。

但是,Lisp那强大的宏,那运行时改变自身的能力并没有被其他语言接受,Ruby比较接近,但是差得还很远。可能大家害怕这个双刃剑了吧!
用户评论