© Syeerzy|Powered by LOFTER
写了 30 年代码的大叔

几乎99.9%的编程语言设计书都主要介绍编程语言的"实现" 而不是 "设计", 想象所有设计书都介绍 "Photoshop的技巧" 而非 "美学", 会是什么场景? 


大概所有人都觉得, 一是根本没几个人会去正儿八经设计一门编程语言, 更多是因为某个原因去实现或改进一个语言. (就像觉得没几个人会正儿八经去自己设计东西, 更多是网上搜个图拿来P一下, 所以Photoshop技巧比美学和设计重要)  另外一个原因是觉得, 语言的设计很随意, 如果你知道怎么实现,  想怎么设计就怎么设计, 随便你.


事实并不是这样.


编程语言设计有一系列的科学和规则需要去考虑, 并不是随意的. (我的一名下属就曾在公司一款产品中, "随意"地设计了一门领域语言(DSL), 后来出现冲突了, 就修改修补, 再后来冲突更多, 就再修改修补... 可是随着时间推进, 需要修补的东西越来越多, 冲突也越来越多, 每个冲突的修改又引起其他冲突, 就像进入一个迷宫一样)


举几个简单的例子:

1. 设计一种对 html css 选择器的扩展语法,  比如用 .text 和 .html 后缀分别表示目标标签的innerText 和innerHtml,   很简单的导致的结果是如果目标对象的子对象具有 class="text" 或者 class="html" 则会引起冲突. 尝试引入一个新符号比如 $, 用$text和$html来表示,  则冲突变成了如果目标标签的id或class以$text或$html为结尾, 并且你的选择器使用了它, 又会冲突,如此种种.  这是最简单的情况.


2. 假设你设计一个新语言, 具有以下设计:

if 后面的小括号可以省略(像Python和Go一样), 并且不需要那个冒号. 

那么导致:

为了区分判断部分和语句部分, 花括号一般不好省略, 假设代码为:

if TrueOrFalse {

    doSomething()

这当然一开始没有问题了, 然后如果后面你觉得ruby的语句块语法非常棒, swift的回调参数语法也很帅, 想要引入类似的语法, 也就是如果一个函数的最后一个参数是函数(或等价的东西, 如lambda表达式或方法), 则可以写到后面, 用{}括起来, 比如:

doSomething(0, a -> a+1)  

可以写成

doSomething(0) { a-> a+1}

如果函数没有参数则进一步写成

doSomething(0) { 100 + 1 }

那么, 现在考虑一个语句:

if doSomething(0) {

     100 + 1

}

这个语句将会有两种歧义, 可能是 doSomething(0) 的返回值是bool值用于判断, 如果true则执行100+1

第二种意思是if 后面是带2个参数的 doSomething调用(第二个参数是()->{100+1}),  并且具有空的语句体(或后面第一句语句是if的内容)


函数回调写法跟if本来毫不相干, 但是这种情况下就冲突了, 这也是为什么if后面可以省略小括号的编程语言都带有类似 冒号这样的分隔符的原因.


3. 类似的,  有些约束是连锁约束影响,  比如python决定了使用缩进来表示代码结构, 省略了花括号, 一系列连锁影响后付出的代价是无法像ruby和clojure那样省略return 关键字,  进一步地很难优雅地实现完整的lambda表达式. 于是python之父在20多年前的缩进决定, 在今天付出了代价. (虽然他说是故意不想实现完整的lambda的....更像个借口)


凡此种种, 事实上因为我没有在国内找到过哪怕一本讲解这方面知识的书籍, 因此才萌生了写一个这种系列, 把这些琐碎知识记录下来的想法.  微博夹杂了太多噪音, 我又不用微信,  找了一下, lofter差不多是唯一活着的短博客,虽然跟程序和技术不沾边, 还是决定写在这了.