命运之轮

我最初学编程,应该也就是2010年左右的事情吧。 当时啥也不会,就会在C++吧水贴。 在那,听说过了有一个很厉害很潮流的东西,叫做C++11,有什么叫concept跟module的东西,好像挺厉害的样子。 当时,在clang上就可以用C++11了,只不过这两功能还没有,就有auto, lambda, constexpr 不知道有没有(记不清了),也很好了。 时间快进到现在,这两功能还是没加进去。 不过C++厨们可以稍稍放心,我今天不是来黑C++的。 这固然是C++的悲剧,不过也是所有语言的悲剧。 如果去看历史,去看看一个个语言的发展,我们会发现一个规律: 语言/语言家族的发展,是不停的扩大,直到无法支撑自身的重量而倒下为止。 让我们跳到1958。 ALGOL。 只要大家说计算机历史,就一定要说ALGOL。 因为这可以说是一切的开端。也是一门伟大的语言。 做Algol相关的work的图灵奖得主,足足有6个:John Backus,Alan Perlis,Peter Naur,John McCarthy,Edsger W. Dijkstra,Tony Hoare。还有无冕之王,Peter Landin跟John Reynold。 但是,为何这么成功的语言,却默默无名?因为错在了下一步。 在1960后,ALGOL推出了ALGOL 58,ALGOL 60,还有各种方言后,大家开始慢慢懂该怎么设计语言,实现编译器了。BNF,Recursion,Continuation,Stack,都慢慢被大家发明发现,慢慢熟悉。大家也开始发现了ALGOL 60没做好跟没有做的东西。 于是,1962起,大家开始发明一门新的,叫ALGOL X的语言,旨在把这些问题修好。从1962起讨论,一直到1965,变成一个draft。高兴的ALGOL厨把这叫做ALGOL W,并且等着用了。一切就差一些小修小补了。 就跟物理学大厦就剩下两朵乌云一样。 快进半年。另外一个ALGOL W的draft被奉上。情况不容乐观。 本来说好的三个月,跳票成了半年不说,draft变得更厚更长,问题反而越来越多。于是说在等三个月,我们再修修。 明明说三月,三月后又三月,三月后又三月,都快一年了。 拖了9个月后,在1968年尾,一个叫ALGOL W的,连设计者也不爱的怪兽产生了。 自此,ALGOL被命运之轮碾过。 故事的另一个主角,则知名得多。CPL。 这是1963,离悲剧还远得很,这时候大家都已自己是ALGOL方言为荣。 CPL就是一个ALGOL方言,旨在做更底层的ALGOL。 语言的设计也不算很复杂,唯一的问题就是不知道为啥,编译器死活写不出来。 于是,1967,有人在想,为何我们不把CPL简化点?这样就能做出编译器来了。 然后就出现了BCPL。同年,BCPL的编译器也被实现了。 两年后,为了把BCPL放上微型机,再次简化,出现了B。 同时间,B的一些问题被发现,效率也不够高,于是一个差不多的语言开始被设计,C。 而在C设计过程中,1970年,CPL的编译器终于面世。 命运之轮碾压过ALGOL,再碾压过CPL,碾压一次不够再碾压一次,BCPL,最后出了B,然后造就了C。最大赢家。 之后的,就是历史。 不过,这不是结束。也不是结束的开始。顶多是开始的结束。 还记得最开头的C++吗?没错,命运之轮怎么会放过C。 在C++后,为了简化,出现了JAVA,旨在消除C++的各种复杂性-比如不区分unsigned啊,自动管理内存啊,只有Class啊-只不过,到了最后,还是照样该变大变大。自动管理内存的确比手动简单,但是JVM确变成一个怪兽。就连unsigned这种小东西,也回到语言中了。屠龙的勇士,必成恶龙。 另外一边,PERL崩溃之后诞生的Python也一样,,不知道怎么的,就加入了optional static typing。。。说好的only one way呢?Simplicity呢? 专门搞PL的人别偷笑,Scala就不说了,Haskell也一样,GHC无比复杂,连RecursiveDo都能水一篇170页的Paper,有一个minimal core,也不能解决这问题。也别以为Macro能解决问题-R6RS总共有187页,其中,有90页是语言定义。被称为怪兽的ALGOL W也就265页,实在差不了多少。ALGOL 60呢?17页。ALGOL 58则只有15页。不过R7RS倒是还行,只有77页。当然,这是以丢掉向后兼容性为代价的。 有没有语言试图挑战这命运之轮? 有。Scheme,Python,都壮士断腕,丢掉了向后兼容性。自己不丢,别人就会给你丢。 Go也算是,Rob Pike活了60年,啥大风大浪没见过,尤其是Google的Build Server再也撑不起他们的C++,当然知道复杂度乃洪水猛兽-要不然为啥死撑不肯加generic。...

April 16, 2018 · 圆角骑士魔理沙 · CC BY-SA 4.0

怪名乱神

我想给大家介绍一门语言。 C*。 C*有什么特点呢?很著名很流行。 我们可以看看TIOBE Index:到2017年12月,这门语言的rating达到了30.965%以上,比Java,下一个最热的语言,高了一倍有余。 这门语言被广泛使用于各种领域:操作系统(Linux, Windows),分布式(Spark),深度学习(部分tensorflow),区块链(bitcoin),游戏引擎(Unity)。 同时,C*的方言包含C, C++, Java, C#等知名语言。 我们先从语法开始介绍:C*的一个程序,由多个声明组成。其中,一些声明属于函数声明,而一个函数又由多条语句组成。。。 是不是觉得很荒谬?C没有Class, C++没有垃圾回收,Java跟C#水火不容,为什么被认作同一语言? 而如果我告诉你,现实比这还魔幻呢?世界上有很多语言正被冠以‘C*’这样的名字,而这些语言中,毫无共通点?这些语言中,有的有静态类型,有的有动态类型,有的两个都有,有的GC,有的是为Arduino设计的,有的在JVM上,有的有Class,有的有Reflection,有的没有Assignment,有的基于Lambda Calculus,有的则不是,有的可以任意改自身语法,有的语法是二维的,是个表格,而不是线性的,而有的甚至自带GUI,是livecoding的鼻祖之一。。 而这些语言,通通被称作同一个语言:Lisp。 而更魔幻的在后面:于是,有很多人开始讨论,为啥这门语言没有取得主流化,为啥这门语言效率这么高。。。然后得出很多答案,其中一半的直接是错误的,如: Lisp是第二早的高级语言,所以XXX,所以效率很高 最早的编程语言Plankalkül,是1942到1945设计的,然后Fortran也比任何被称为Lisp的语言早。就算我们取最乐观的时间,1946到1955之间差了10年,里面出现了各种语言,AutoCode, ShortCode, Flow Chart, Haskell Curry的语言。。。 不过上述问题是技术错误,下面的论证则更离谱: Lisp社区很分裂,大家无法合作,所以没有流行 。。。Excuse Me?如果有一天,C, C++, Java, C#都衰落了,再也没有人用,是不是因为C*社区很分裂,C/C++/Java/C#,你任意选出一对,肯定在互捏?大家无法合作也是啊,Java自己有一套库,C#自己一套,C跟C++也是,这么分裂,不衰退才怪! 欲加之罪,何患无辞啊!本来就不是同一个语言,为啥要放一起论证,然后去吐槽大家之间不兼容? 在一推只是因为历史原因被称作一家族的语言之间,找共通点,然后去论证这些语言的兴衰,特性,适用范围。。。能找出啥有价值,nontrivial的insight才怪。 至于S表达式?Logo不用括号,Racket有2d syntax,也有infix expression, Common Lisp有reader macro。。。试问这些语言是不是Lisp?而JMC也说过我们应该往M表达式迁移,那是不是JMC 发现了Lisp的本质劣根性?我们也可以用argument by absurdity,论证C*这个词的合理性 - 有花括号跟分号的就是C*,C*成为世界上最主流语言,C*万岁! ‘Lisp’,这个词,已经没有任何有价值的意义,早就该被废弃,或者仅仅指JMC在1950末造的一个语言。就如同C*这个词不应该被引入一样。 另:最后,我想吐槽小部分所谓的‘Lisp’ 厨。往往,当你问,‘Lisp有什么优势/值得学’的时候(我们先不吐槽这问题提得很糟糕,就如同你不会问为啥要学C*/C*有啥优势),会跳出大致如下的答案:‘大部分主流语言的特性,早在Lisp中存在。主流PL发展只不过是catch up 1960 Lisp。’ 这回答并很具误导性。 因为1960的时候,JMC 的确公开了一个语言,但是这个语言没有macro,是dynamic scope(读作:没有符合lambda calculus的first class function),连special form quote也没有(取而代之的是一个atom,换句话说你要quote compound expression得手动把(A B)转成(pair A B))。在1967年,影响了Smalltalk跟无数学计算机人士的Logo出世,而在1970年,Scheme借鉴了Algol,修复了dynamic scope,也有macro跟continuation。Common Lisp在1984诞生,又在1990带来了Common Lisp Object System,跟metaobject protocol。1994,racket诞生,又在2002带来了composable & compilable macro。在今年,则出现了Collapsing Tower of Interpreter,实现了看上去有无数个interpreter,并且可以到达任何一个interpreter,更改语义,最后再运行普通的代码(并且看到更改语义带来的change),也出现了Type System as Macro,可以用宏代表静态类型。...

December 17, 2017 · 圆角骑士魔理沙 · CC BY-SA 4.0