如何设计一门编程语言(五) 面向对象和消息发送2014-08-23面向对象这个抽象的特例总是有说不完的话题,更糟糕的是很多语言都错误地实现了面向对象——class居然可以当一个变量类型什么的这只是让人们写代码写的更糟糕而已。当然这个话题第三篇文章已经说过了,现在来谈谈人们喜欢拿来装逼的另一个话题——消息发送。按照惯例先来点题外话。说到消息发送,有些人喜欢跳出来说,objective-c的消息做得多优雅啊,代码都可以写成一句话[golang screw:you you:suck]之类的。其实这个还做得不够彻底。在几年前易语言曾经火了一阵,但是为什么大家这么讨厌他呢?其实显然不是因为每个token都是汉字,而是因为他做的一点都不像中文,谁会说话的时候带那么多符号呀。其实objective-c也一样,没人会因为想在一句英语里面用冒号来分割短语的。当我还在读大三的时候,我由于受到了Apple Script(也是苹果做的)的启发,试图发明一门语言,让他可以尽量写起来像自然语言——当然他仍然是严格的编程语言。但是这门语言因为其奇特的语法结构,我只好自己想出了一个两遍parse地方法。第一遍parse出所有函数头,让后用这些函数头临时组成一个parser,用它来parse语句的部分。后面整个也实现出来了,然后我就去做了一下调查,发现大家不喜欢,原因是要输入的东西太多了。不过我这里还是贴一下当初是怎么设计的:
phrase print(content) isexternal function "writeln"end phrasephrase first (count) items of fibonacci sequence isif count equals to 1 thenresult is [1]else if count equals to 2 thenresult is [1,1]elselet list be [1,1]repeat with i from 3 to countlet list be list joins with item length of list - 1 of list + item length of list - 2 of listendresult is listendend phrasephrase (number) is odd isresult is number mod 2 is 0end phrase alias odd numberphrase append (item) after (list) islet 0 element of list from length of list be [item]end phrasephrase ((item) is validated) in (list) islet filtered list be []repeat with item in listappend item after filtered list if item is validatedendresult is filtered listend phrasephrase main isprint odd number in first 10 items of fibonacci sequenceend phrase
倒数第二个函数声明甚至连函数指针的声明也如此的优雅(我自己认为的),整个程序组织起来,我们要输出斐波那契数列里面前10个数字中间的奇数,于是就写成了print odd number in first 10 items of fibonacci sequence看起来比objective-c要漂亮把。其实如果想把所有的东西换成中文,算法也不需要变化。现在用空格来分割一个一个的词,中文直接用字符就好了,剩下的都一样。要parse这个程序根本没办法用流行的那些方法来parse。当然我知道大家也不会关心这些特别复杂的问题,于是题外话就到这里结束了,这个语言的实现的代码你们大概也永远都不会看到的,啊哈哈哈哈。为什么要提这件事情呢?我主要是想告诉大家,就算你在用面向对象语言,想在程序里面给一个对象发送一条消息,这个对象并不是非得写在最前面的。为什么呢?有的时候对象不止一个——这个东西叫multiple dispatching,著名的问题就是如何给一堆面向对象的几何体类做他们的求交函数——用面向对象的惯用做法做起来会特别的难受。不过现在我们先来看一下普通的消息发送是什么样子的。对于一个我们知道他是什么类型的对象来说,发送一个消息就跟直接调用一个函数一样,因为你不需要去resolve一下这个函数到底是谁。譬如说下面的代码:
class Language{public:void YouSuck(){ ... }};Language golang;golang.YouSuck();