32 comments

NPR简介

不论在美国的什么地方,只要你有一部收音机,调到一个电台,就立即能够深刻了解世界和社会。 这个电台,就是大名鼎鼎的NPR,美国国家广播电台。

和美国之音这样更多的负责外宣和价值观输出的电台不一样的是,NPR 就是为了教育美国公众而设立的。这个非盈利的电台不播送任何广告. NPR 的节目每个都质量上乘,有极强的知识性。正是如此, NPR 的听众相对教育程度较高。去年有本讽刺搞笑的书叫做《白人喜欢的东东》(Stuff White People Like), 调侃中产阶级白人的各种喜好, NPR 就是其中一样。比尔克林顿这哥们不止一次表示喜欢 NPR。 当年创立麦当劳的亿万富翁的遗孀,更是把所有遗产捐献给NPR基金会. 美国人的确喜欢听 NPR, 每年听众给NPR的捐款,占到NPR所有收入的一半。
对于大部分这篇文章的读者来说,NPR 可以作为一个非常好的英语学习工具。如果你在美国,那么可以免费听到最新鲜的英语,而且一点不需要专门花时间去听,只要闲暇时候带上收音机就行了。我练习发音的方法就是每天开车的时候跟读 NPR。 如果你不在美国也不要紧,NPR 的大部分节目都是可以在 iTunes 里面免费下载的(如果你到 iTunes 的 Podcast 的新闻、咨询分类里面,就会看到NPR的podcast 的流行度永远是前几名)。

我个人喜欢 NPR 的两个节目,一个叫 Wait wait… don’t tell me, 另一个是 Car Talk. 这两个节目都是搞笑见长。 前者是把每周新闻拿过来考打电话进来的听众,后者是两个兄弟解答听众的关于汽车的问题。 其中,Wait wait 可以说集成了美国文化的各个方面,有简单的名人访谈,有所有的美式幽默,有对政治和社会新闻的插科打诨。基本上 Wait wait 能听懂每个笑话的话,对美国社会和文化就有非常深刻的理解了。而一般的名人,都以上NPR 的 Wait wait 为荣。比如 Steven Chu 就说,他虽然是所有兄弟中最不聪明的,可他是第一个上 Wait wait 的。Car talk 则更加搞笑。表面上是一个解答车辆故障的节目,但两位MIT毕业的汽车修理工愣是把这个节目做成了NPR最受欢迎的节目,也让这两个人成为了美国文化的一部分。迪斯尼的电影汽车总动员,就把两兄弟请过去为那个锈迹斑斑的拖车和面包车配音。NASA 的 JPL (喷气动力实验室)的科学家甚至不止一次给他们打电话一起搞笑,有一次问的问题是“我们有个交通工具将要度过一个漫长的冬季,请问我们怎么准备”,结果搞笑了一阵子才知道他们问的是火星车怎么度过火星漫长的冬季。除了这些搞笑之外,Car talk 的确还能帮你学到汽车的一些基本知识,了解莫名其妙的疑难杂症。

除了这两个节目, All things considered 是一个非常好的新闻综述,Science Friday 是一个质量上乘的科普节目(常常采访一线科学家)等等,反正我打开收音机从来没有失望过。即使你不在美国,只要有 iTunes 就可以免费下载到大部分优质节目的 PodCast,所以一定不要错过 NPR。

(写这篇文章的初衷是因为路金波先说“杀孩子的杀了喂狗”,然后连岳评论说这是主张“放弃程序正义”。我觉得这个评价太扯淡了,所以展开来说几句。我在这里说的,都是一些基本的常识,而不是什么深奥的东西。以下所有的都是基于美国宪法)

言论自由(Freedom of speech) 这个概念是美国宪法第一修正案界定的,以前我写过很多次文章介绍了。宪法第一修正案的第一句话是“国会不得立法以:确立国教或禁止信教自由;剥夺言论自由或出版自由;或剥夺人民和平集会和向政府请愿伸冤的权利。” 我们常常说的言论自由,就是来自于此。

正当法律程序(Due process) 这个词,则是美国宪法第五,第十四修正案界定的。其中第五修正案是限制联邦政府权利的,原文如下:“非经大陪审团提起公诉,人民不应受判处死罪或会因重罪而被剥夺部分公权之审判;惟于战争或社会动乱时期中,正在服役的陆海军或民兵中发生的案件,不在此例;人民不得为同一罪行而两次被置于危及生命或肢体之处境;不得被强迫在任何刑事案件中自证其罪,不得不经过适当法律程序而被剥夺生命、自由或财产;人民私有产业,如无合理赔偿,不得被征为公用。”其中,第四款中的“适当法律程序”,就是 Due Process of law 的中文翻译。南北战争之后,国会深感如果不用同样的条文限制州,州也会违反“正当法律程序”,因此,宪法添加了第十四修正案。这个历史和判例,我以前曾经专门写过。如果我们看到第五,第十四修正案,就会很明白,一般法里面所谓的 Due Process, 仅是对联邦和州政府的执法者,如联邦和州的法官,检察官,警察等人群提出的要求。 正当法律程序的一个重要的实现手段,就是程序正义(Procedural due process)。
这可以看成是一个弱化的对正义结果的追求:因为程序正义是最可能达成事实正义的方法,而事实正义本身如何界定争议太大,我们至少先要保障程序正义。不管怎样,Due Process 以及程序正义作为法律上的术语,提的要求是仅限于对政府,而不针对公民的。这一点也很好理解,公民本身没有执法权(如果公民非要说有而执行私刑 Lynching,自然有其他法律定罪,因为这时候已经侵害了他人的基本人权。),所以不能用程序正义来要求公民。这个基本的概念如果不清楚,所有的后面关于程序正义的讨论就没有意义。

程序正义的法理学基础,来自政府应该相信,每个公民都是应该受到尊重的。 当然,这并不蕴含着每一个公民都要相信其他的公民应该受到尊重,正是因为这里面有巨大的鸿沟,所以常常成为辩论的引爆点。比如一个人冲击幼儿园,杀死了12个没有任何防卫能力的小朋友,自然地,出于人性,其他公民就不可能对其表示尊重,甚至有复仇和主持正义的心态,说出如“凌迟一百次”这样的话来。 那么,现在的问题就是,说出凌迟100次这样话的这个公民,是不是影响,或者在反对程序正义。

这里面其实有三个层面的考量。 第一,愤怒驱使下的言论受不受言论自由保护? 第二,公民的言论会不会影响程序正义? 第三,为了程序正义,是不是我们要放弃一部分言论自由。

我们先看第一个。 以前看过我写的第一修正案和相关判例的人都知道,在美国愤怒到烧国旗都是受宪法保护的。 一个言论受不受保护,不是看言论内容是不是合乎大众品味,而是看这个言论能不能导致明显而立即的危险。 如果某种言论能够立即导致危险,那么为了防备这种危险,我们要限制这个言论。 所幸的是,美国最高法院常常发现,所谓的危险常常不存在,所以判决了无数偏向于保护言论自由的判例。 以说出凌迟 100 次这个言论为例。如果这个人不是陪审团的,也不是法官,那这个言论是根本无法造成任何危险的,因为犯罪嫌疑人被严密的看管着,况且你我大家都知道,路金波和看到这句话的人都清楚,他们是不会拿把小刀去凌迟的。因此,这种言论,尽管看上去不理智,不那么深刻,但它的确的确是应该受到言论自由保护的。 这一点,相信大家异议较少,因为路金波也的确表达了,也的确没有人去限制他表达。

关键是第二点。上面我们说了,美国宪法的在程序正义,是用来要求联邦和州,在司法案件中对待公民(其实也包括企业)上的一般原则。 那么,假使一个人,反复的渲染和帮助法律审判中的一方,会不会破坏程序正义呢? 事实上不会。 原因有两个。第一,程序正义强调的是程序,而不是正义本身。程序包括采集证据,法庭辩论等等,是有成文的规定的。在法制健全的国家,是任何言论也没法改变的。最著名的例子就是辛普森杀妻案件了。 媒体和大部分美国人都倾向于他杀了人,可是程序正义依然毫无影响。如果司法机构被影响了,那么只能证明该司法机构不合格。公民和媒体没有任何责任(事实上也不可能)去呵护司法机构维护程序正义,因为这本身就不是公民和媒体的义务。

第三点更加深刻。 有人担心,媒体和公民如此“煽动”,恐怕有不好的结果发生,所以最好要让他们理智一点,避免影响司法公正,所以,最好要限制这种言论自由。 事实上,言论自由正是程序正义的一个保障。历史告诉我们,如果律师不能说话,如果受害人老是被雪藏,如果没有言论自由,就根本没法有程序正义所要求的公正采集证据,寻访证人,也不可能有正当的法庭辩论。 为了程序正义,我们至少不能限制言论自由。 当然有人要说了,我们可以放开这一类的自由,但是限制那些“煽动”的言论自由。 这个提议看起来很好,也符合很多“理智主义”者的想法。事实上,这是大错特错。 美国宪法的立法者早就意识到,如果你限制了一种言论自由而放开另一种言论自由,那这就不是言论自由了。 那些希望用程序正义这个光亮的果子来诱使人民相信必须要限制不理智的,煽动仇恨的,会影响司法公正的人,充满了理性优越感的想要通过正义而理智的立法限制言论自由的时候,却惊讶的发现碰到了永远越不过的石头墙:宪法第一修正案赫然写着“国会不得立法限制言论自由”。 其实这不值得惊讶,美国的开国先贤知道后来的理智的聪明人会这么干,所以早就把你要走的路堵死了!

再说一次废话:我写的这些东西,都是基本到不能再基本的,每一个美国中学生都熟悉的宪法知识。我也是只读了一些基础的书,可见要掌握这些基本概念不难。我希望我的读者能够读一些这样的关于公民权利和第一修正案的书,你读了这些书以后,就知道我在这里写的都是废话。你要是真的觉得我写的全是你已经知道的废话,我反而会很高兴,因为你已经成为一个值得我尊敬的公民了。 如果你还年轻,想成为一个正直的人,那么,了解什么是自己的自由,什么是他人的自由很重要,因为这样你就不会有意无意的侵害他人自由而不自知。其实人际关系中,正直的基本定义就是如此。哦,对了,我只和正直的人成为朋友,因为不正直的人侵害我的私利的概率比较大,请原谅我的自私。

13 comments

Borg

Star trek 是基本上属于 Geek 必看的科幻剧了,虽然年代久远了一点,但里面很多词和符号都成了 Geek 文化的一部分。
我甚至怀疑乔布斯老师是按照 Star trek 里面人手一个 PADD 的创意发明 iPad 的。

Startrek 剧集中塑造了一个外星种族,叫做 Borg. 我觉得很有意思,来八卦一下。

首先,Borg 这个种族常常和邪恶帝国挂上等号。如果你去翻 New Hacker’s Dictionary 的 Borg 条目, 他就会告诉你, See also: Evil Empire. 如果你是 geek 网站 slashdot 的常客,你就会发现, 上面每条微软的新闻旁边,都是比尔盖茨同学戴了一个机械状的头盔/帽子, 是的, 这就是隐喻了比尔盖茨的微软是个邪恶帝国。

为什么说 Borg 是邪恶帝国呢? 这要从 Borg 的生存方式说起。 所有的 Borg 成员,都随时听从一个中央命令机构,叫做 Collective (集体). 这个集体, 随时能够和任何一个 Borg 成员通信, 在 Borg 成员里共享一切信息. 每一个 Borg 成员并没有名字,而是以代号相称, 比如第一联合方阵第一分队 9 人组第 7 号(著名的 Seven of nine)。 这些成员也没有任何所谓的个人意志,都是属于 Borg 集体里的一个工蜂而已。

Borg 本身只是一种社会组织方式,蜜蜂和蚂蚁基本上也是这样组织的。 Borg 的邪恶之处在于,他生存的唯一目标,就是不断的同化其他的种族,以达到自身种族的完美。 他们对其他种族的同化显然非其他种族自愿的,于是他们就不断的发动战争,其中就包括对人类的战争。 同时,他们的武器系统还很发达,能够自动适应对手的武器系统,所以基本上同化其他种族好不费力气。 Startrek 剧集放到 Voyager 的时候,他们基本上已经统治了银河系第四象限的绝大多数星球系统了。 一个种族一旦被同化,就彻底变成了 Borg 集体里面的一个零件,所以,Borg 几乎是所有其他种族的敌人。

Borg 同化的方法也很神奇,就是给你注射一种纳米级别的生物芯片,这种生物芯片一旦到了被同化的生物的体内,就开始改造这个生物。 以人类为例,Borg 认为人的视觉系统不够发达,所以同化人类为 Borg 的时候,人就会被添加一个发红光的眼睛部件。 Borg 的这个特征很显著,盖茨大叔的图就是这么回事。

Borg 这种集中的,集体的,一致对外的组织方式,是效率无比之高的。 当然,Borg 也有一个致命的弱点: 他们的技术非要通过同化其他生物才能获得,他们本身的研发技术却不见得怎么样。用句流行的话说就是 “一直在模仿,从来不创新”。 所以假如遇到不能同化的生物,他们就非常郁闷。比如说,Borg 编号为 8472 的生物的免疫系统特别强, Borg 的生化武器完全不起作用,这时候 Borg 就被打得落花流水。 最后还是靠英勇的人类船长和神奇的医生研发的技术才勉强打败了 8472 号生物的一次进攻。

Star trek 中有多次 Borg 的成员被同化后脱离了组织再次变成一个个体的例子。 最显著的就是 Seven of Nine 的去 Borg 过程了。 Seven 是一个人,很小的时候就被同化成 Borg, 一开始是作为合作来到 Voyager 船上的,但是时刻不忘和集体保持联系。因为一次事故,她和集体的连接被切断了,她立即感觉到“我再也听不到集体的声音了,我很孤独”。 的确,Borg 集体的力量和声音是非常有安全感的,一瞬间失去了之后必然会感到很孤独。 船长 Janeway 就说,你不是 Borg, 你首先是一个人,不要感到孤独,我们船上所有的人都是你的朋友。 Seven 最终摆脱了 Borg 集体的影响,成了 Startrek 系列中最性感的角色,哈哈。

最后附送一个和 Borg 有关的好玩的技术八卦。 大家都知道 GoF 的 Design Pattern 里面的 Singleton Pattern, 就是一个类只能有一个实例。 在 C++ 等标准的静态语言上,实现方法是私有化构造函数等等。 在 Python 这种藏不住构造函数又动态的语言中,
实现 Singleton 看上去是比较麻烦的。 不过,有一个叫做 Borg Pattern 的实现,优雅得实现了 Singleton。 如果你了解了 Borg 种族的特点,又知道 Python 的一些基本知识, 你看下面的这个代码肯定会赞叹到笑出来。

class Borg:
    __collective_mind = {}
    def __init__(self):
        self.__dict__ = self.__collective_mind

    # and whatever else you want in your class -- that's all!

Borg Pattern 就这么简单。对于小项目中顺手写一些控制资源访问的 Singleton 来说,这个 Borg Pattern 实在是不能再好了。

设计新语 (new speak) 这种语言的目的,不仅仅是一种适合表达 Ingsoc 的世界观和思维习惯的媒介,更加要紧的是,其他的思维方式根本无法在新语下表达。 — George Orwell  “1984

语言是能够影响思维的,这一点基本上对语言和思维有认识的人都能够体会到。

一、

亚马逊丛林里面有个部落,语言中没有数字的概念,因此,当地说这个语言的人只能够分辨两框苹果哪个多哪个少,却不能数出这框苹果比那框苹果多多少。非洲也有一个部落,语言里面没有左和右的概念,只有东南西北。他们也就没有“右手”这个词,只能根据身体的朝向说你“东边的手”或者“西边的手”等等。因此当地人方向感特别强,到什么地方先要分清楚东南西北,否则没法表达一些意思。

阿拉伯人常常和骆驼打交道,因此有几十个关于大骆驼小骆驼公骆驼母骆驼等等的不同的词。 爱斯基摩人天天出门见雪,因此有地上蓬松的雪,结了冰的雪,刚下的雪,屋子上的雪等等十几个不同的词。假如他们看到一副画,就要先思考这个画里面的骆驼或者雪是什么属性的,如果不知道属性(比如卡通画里面的骆驼或者雪),他们就不知道怎么说才好。这些都是语言对思维的限制的例子。

语言对思维还有一种误导的作用。比如我们小时候常常听说的一个词叫做“早恋”。这个词在中文里面包含了偏见,好像是本来不应该的,提早了的恋情。这个词本身表达的概念应该是中性的(英文里这个词叫做 puppy love, 小猫小狗之间的恋情,媒体和大众对这种现象都是中性态度),但是中文表达出来,却包含了一种价值判断(“早”字包含了不应该的意思)。 中文中有无数这样不科学的,包含了偏见和价值判断的词(这些词被李笑来老师称为恶词)。任何一个想要独立思考的人都应该避免使用这些恶词。

二、

我们说了语言能够影响思维,那么语言是不是决定了思维呢? 这就是著名的 Sapir-Whorf 猜想。 这个猜想是说,语言对思维是有决定性影响的,即存在这样的一个语言,使得某种意思能够在这个语言中得到表达,但不见得在另外的一个语言中得到表达。 假如说 Sapir-Whorf 真的能够成立的话,那么 1984 和新语真的不是痴人说梦。

三、

所幸的是,很简单可以证明 Sapir-Whorf 猜想不正确。 大家都知道,计算机语言是一种非常受限的语言,然而只要这个语言是“图灵完全“的,他们在最根本的表达能力上都是没有区别的。乔姆斯基更加猜想,人的语言的生成机制,就是一个图灵机。 这个猜想其实和丘奇-图灵论题是等价的。 我在之前一些文章中提到的,人工智能的符号学派假设人的思维完全来自于对符号的处理,根据丘奇图灵论题,那么只要一种语言能够容纳图灵机,就能容纳其他语言了。 我们常用的自然语言是显然能容纳图灵机的, 因此,理论上来说,只要语言足够复杂,就不大可能完全决定我们的思维,使得一种语言能表达的意思完全不能由另一种语言表达。当然,不同的表达有效率的问题,因此即使本质等价,从效用上看也不等价。

四、

中文中唐诗宋词的结构之美,是其他基于字母的语言难以企及的,所以,审美是和语言息息相关的。 Python 编程中的美,函数式编程中的美,也是 FORTRAN 所未能得见的。 中文的美一定程度上来自于其搭配的模糊性和意象类比,读多了唐诗,宋词的人就知道,几乎没有一个没有类比的。 这种意象类比在文学作品中出现是一种优美的事情,但在非文学作品中,在评论,科学写作和日常交流中,这往往是正确思维的敌人。 这在一本叫做 The Alphabet Effect 的书中讲得很仔细。

英国科学家李约瑟毕生研究中国科技史,他很好奇,古代中国拥有世界上最先进的技术和生产水平,为什么却没有发展出现代科学呢? 到底是中国古代社会哪一方面出了问题呢? 这个“李约瑟问题”的答案有很多种,其中 The Alphabet Effect 这本书就提出了一种解释: 中国的书写系统不是字母化的,而是方块字。 或者简单的说,就是全怪仓颉这个人,怎么不造出拼写文字?

大体说来,此书认为,第一,中文读,写系统分离(看到,听到一个字不知道怎么写)使得阅读中文的时候较多的采用非线性(右脑)思维,而人在进行逻辑思考的时候较多的是左脑思维。两脑并用不是优势,所以中文书写系统影响了左脑的发展。 这一点我不知道对错。 第二点说,中文的字,都是从具体的图画而来,而中文的词,都是单字组合而来,这些单字组合,又必须要尊重原来具体单字的含义;加上单字又是抽象了具体的,可以画出来的事物,所以中文的抽象程度不高,且一词多义现象非常严重。 而现代科学需要的是高度抽象的词,和高度精确的概念。这一点我是同意的。现代汉语里很多词,在新文化运动前是没有的,比如“科学”,“哲学”,“政府” 等等。古希腊的拼写文字组合灵活,很早就形成了如“质”,“量”,“比率”,“几何学”,“心理学”等等和现代科学相关的,抽象程度很高的词,而这些概念则是古代汉语中从来没见到过的。第三,活字印刷术虽然号称是中国发明的,但其实一直没有大规模使用,在清代还是雕版为主。而普遍采用字母的欧洲则迅速采用了活字技术,使得雕版技术只在高档场合有所保留。 这一来更加拉大了信息传播的差距。

五、

俗话说,人穷不能怪父母,用批评中文本身的方法来掩饰在科学上的落后只是一种学说而已。 如果现代汉语和其他语言处于同一起跑线的话,本应当有足够的机会弥补这个缺口。 不过,英语已经成为一种事实上的语言了,所有的新的概念和新的学说,基本上都是以英语发表。作科研的人做到后来也知道,有些概念不知道怎么翻译成中文(而且一翻译就是错的,比如俄狄浦斯情节,翻译成中文叫做恋母情节,其实完全是把一个好词翻译成了恶词,抽象程度大大降低)。 我一直鼓吹,如果要学习计算机科学的话, 会英语的人能看英文就少看中文,因为中文中,对计算机科学中相关概念的精确程度的确比不上英文,而且一翻译就错。

英文 wikipedia 有几百万个词,而中文只有十万个,撇去因为审查制度造成的不便外,英文比中文的复杂度是在高太多了。(从这个意义上来说,审查制度是不是在扼杀中文?)
六、

语言是一种媒介,不光是语言能影响人的思维方式,物理媒介本身也能影响人的思维方式。 你是否曾经觉得在多媒体计算机屏幕前看书怎么也看不下去,一换到纸质的书就能看下去? 是否觉得小时候爱看电视的人长大了思维不连续,没逻辑? 是的,媒介会构建和摧毁你的思维方式。 多媒体计算机有很多的视觉元素,会抑制你的左脑的线性思维,激化你右脑的模式识别能力,所以,在多媒体计算机前看书的你,会自觉不自觉的被转换到右脑的思维方式,看电视也一样。 这是无法避免的事情。 科学研究发现,儿童看很多电视会影响后天的智商和持续思维能力,因为电视屏幕平均每隔90秒就要换一次场景,儿童的大脑就会发展为适应这样的持续激励的右脑思维方式,而左脑得不到必要的训练。

想买 iPad 看书的同志们,可要想好了你买了 iPad 之后大脑是不是会和你作对不让你看书哦 :) 如果你常常用 iPad 看电影上网的话,看书可能是一件让大脑感到困难的事情 :)

我的 wordpress 的 index.php 文件总是在最后莫名其妙的出现 一个 iframe, 里面有 http://www.kmsjwg.***com****/x*******x.htm 昨天晚上我检查的时候还没有,今天就已经被举报成恶意站点了。

我怀疑是博客哪个地方有漏洞,目前正在修复。 哪位有线索也可提供。

谢谢阅读

待月西厢下,迎风户半开。隔墙花影动,疑是玉人来。

最近 twitter 上最流行的一个关键词是”西厢计划”. 这个计划名字取得很浪漫,客户端叫做张生,对,就是西厢记里面那个翻墙去见崔莺莺小姐的张生;显然,服务器端必然叫做崔莺莺。客户端的张生是最重要的部件,可以不依赖于服务端工作。

我是个特别好奇的人,遇到好玩的总要学习一下看看是怎么弄的。因为西厢计划的作者只是简要的介绍了一下原理,其他报道又语焉不详,我当时就觉得很好奇,花了昨天一个晚上详细读了一下源代码,终于知道怎么回事了,觉得原理非常漂亮,所以写篇文章介绍总结一下。

先说大方向。大家都知道,连接被重置的本质,是因为收到了破坏连接的一个 TCP Reset 包。以前剑桥大学有人实验过,客户端和服务器都忽略 Reset, 则通信可以不受影响。但是这个方法其实只有理论价值,因为绝大多数服务器都不可能忽略 Reset 的 (比如 Linux, 需要 root 权限配置iptables, 而且这本身也把正常的 Reset 给忽略了)。只要服务器不忽略 Reset, 客户端再怎么弄都没用,因为服务器会停止发送数据,Reset 这条连接。所以,很多报道说西厢计划是忽略 Reset, 我从源代码来看应该不是这样。在我看来,西厢计划是利用了墙的一个可能的弱点–墙只在连接发起的时候把一个 TCP 连接加入监听序列,如果墙认为这个连接终止了,就会从监听序列中去掉这条记录,这样,这条连接上后续的包就不会被监听。西厢计划就是让墙“认为”这个连接终止的一个绝妙的方法。只要墙认为这个连接两端都是死老虎,墙就不会触发关键词检测,其后所有的数据,都不存在连接被重置的问题了。

如何让一个连接置之死地而后生,就是西厢计划那帮黑客神奇的地方了。这也不是一日之功。 首先,这帮牛人发现,墙的是一个入侵检测系统,把含有关键字的包当成一种“入侵”来对待。采取这种设计有很多好处,但缺点是入侵检测系统可能具有的问题,墙都可能有。西厢计划主页上那篇著名的论文就是讲这些七七八八的漏洞的。可以说处理这些七七八八的漏洞是非常困难的,迫使墙的设计者“拆东墙,补西墙”。这样补来补去,外表看起来好像很牛逼的墙,其实有很多本质上无法简单修补的漏洞,其中有一个致命的,就是 TCP 连接状态的判定问题。 出于入侵检测系统这种设计的局限,墙没有,也没办法准确判定一条 TCP 连接的状态,而只是根据两边收到的数据来“推测”连接的状态。而所有的关键词检测功能,都是基于“连接还活着”的这个推测的结果的。因为墙的规则是在连接发起的时候开始对这条连接的检测,在连接终止的时候停止对这条连接的检测,所以,一旦对连接的状态推测错误,把还活着的连接当成已经关闭的连接,墙就会放弃对这条连接上随后所有的包的检测,他们都会都透明的穿过墙的入侵检测。

上面只是想法,具体到 TCP 协议实现这一层,就要只迷惑墙,还不能触及我要通信的服务器。最理想的情况下,在任何有效通信之前,就能让墙出现错误判断,这些,就需要对 TCP 协议有深刻理解了。西厢计划的那帮黑客,居然真的去读 TCP 几百页的 RFC,还居然就发现了方法(这里我假设读者都知道 TCP 的三次握手过程和序列号每次加一的规则)。 我们都知道,三次握手的时候,在收到服务器的 SYN/ACK 的时候,客户端如果发送 ACK 并且序列号+1 就算建立连接了,但是客户端如果发送一个序列号没 +1 的 FIN (表示连接终止,但是服务器知道,这时候连接还没建立呢, FIN 这个包状态是错的,加上序列号也是错的,服务器自己一判断,就知道这个包是坏包,按照标准协议,服务器随手丢弃了这个包), 但这个包,过墙的时候,在墙看来,是表示连接终止的(墙是 ma de in china, 是比较山寨的,不维护连接状态,并且,墙并没有记下刚才服务器出去的 SYN/ACK 的序列号,所以墙不知道序列号错了)。所以,墙很高兴的理解为连接终止,舒了一口气去重置其他连接了, 而这个连接,就成了僵尸,墙不管你客户端了,而这时候,好戏才刚刚开始。

事实上,墙是双向检测的(或者说对每个包都检测的),因此,对服务器和客户端实现相同的对待方法,所以,墙不管客户端还不行,假如服务端有关键词传给客户端,墙还是有可能要发飙的(这里说有可能,因为我也不知道)。所以,最好的办法就是,让服务端也给墙一个终止连接的标志就好了。可是这个说起来简单,做起来难,怎么能让不受自己控制的服务器发一个自己想要的包呢? 西厢计划的那帮黑客,再次去读几百页的 RFC, 令人惊讶的发现,他们居然在 RFC 上发现了一个可以用的特性。我们上面说了,三次握手的时候,在收到 SYN/ACK 后,客户端要给服务器发送一个序列号+1 的ACK,可是,假如我不+1呢,直接发 ACK 包给服务器。 墙已经认为你客户端是死老虎了,不理你了,不知道你搞什么飞机,让这个 ACK 过了。可是服务器一看,不对啊,你给我的不是我期待的那个序列号, RFC 上说了,TCP 包如果序列号错了的话,就回复一个 Reset. 所以,服务器就回复了一个 Reset。这个 Reset 过墙的时候,墙一看乐了,服务器也终止连接了,好吧,两边都是死老虎了,我就不监听这条连接了。而至于客户端,这个服务器过来的 Reset 非常好识别,忽略就是。随后,客户端开始正确的发送 ACK, 至此,三次握手成功,真正的好戏开始,而墙则认为客户端和服务器都是死老虎,直接放过。所以,张生就这样透明的过了墙。 至于过墙以后所有的事情,《西厢记》里面都有记载,各位读者自行买书学习。

现在的西厢计划客户端,即“张生”模块的防连接重置的原理就是这样,服务器端,即莺莺模块的实现也是类似的。防DNS那个,不懂 DNS 协议,所以看不懂。我猜想,因为开发人员都是黑客,所以自然喜欢用最经得起折腾和高度定制的 Linux 开发。 现在看西厢计划的实现,因为依赖于 Linux 内核模块 netfilter, 在 Linux 上如鱼得水,但往其他平台的移植可能是个亟待解决的问题。 我觉得,在其他平台上,可以通过 libpcap 和 libnet ,在用户态实现相同的功能,就是有点麻烦而已,有兴趣的懂网络的可以照西厢计划原理,在家自行做出此功能;当然,全中国人民都用 Linux 最好 :)

PS 1: 据说是西厢计划一个作者画的原理图:http://img.ly/DIi
PS 2: 我对 TCP 的理解仅限于课本,如果上面的对技术的理解有错,请大家指出。
PS 3: 有些漏洞,可能是设计上本质缺陷,不是那么容易修复的。
PS 4: 除了最后一个图,本文没有其他相关链接,如需相关资料,自行 Google。

(2010年3月16日更新:在霍炬老师和他的朋友的帮助下,实习已经找到;在博文视点的 yeka 老师的安排下,我弟弟已经在北京安顿下来。感谢各位老师读者以及推特上各位好友的转推,关注和帮助! )

我们家有两个男孩子,原因是我小时候身体不太好,旁人都让我父母再要一个孩子,因为两个孩子好养 :) 所以我就有了一个亲弟弟,他和我妈妈姓,叫朱爱宥。

我弟弟本科的专业是园林设计,今年7月份就要毕业了。上大学的时候他忙着读书,也没有想到要找实习。现在想找个实习,积累一些经验,他自己也投了不少简历,正好我这里读者人脉广泛,所以我想问问各位读者有没有在房地产/建筑/建材/工程等相关土建类行业的,或者有朋友在这些行业的,能够有一些推荐的机会。

我弟弟在校成绩很不错,建筑景观手绘能力很强,在 Auto CAD, Sketchup, Photoshop 等软件上花了不少功夫,在我看来已经用到出神入化了;他也很勤奋努力,作事情很稳当,能满足绝大部分工作单位对新人的要求。如果哪位读者能够提供信息或者机会,我弟弟和我都感激不尽。

你可以直接与他 “aiyou.zhu@gmail.com” 联系,或者在下面留言。 谢谢各位!

一周前我和 Tinyfool 闲聊苹果操作系统,都认为对于开发人员来说,苹果操作系统(Mac OS)是上佳的选择。 Tinyfool 笔头很快,当即就写了一篇长文章, 我则笔头很慢,今天才全部码好。 他的文章的主要切入点在于 Mac 平台作为目标开发平台的优势,而我这篇的切入点主要是 Mac OS 作为一种开发工具的优势。

开发人员的趁手工具
对于开发人员来说,所有的开发工具的最大的用途,就是最大限度的提高开发人员的生产率 (productivity) 和创造力(creativity)。在我们这个时代,使用 GUI (图形界面) 是一个提高生产率的好手段。虽然上一代的那些 UNIX 开发人员的确不需要 GUI。一个屏幕,一个键盘,一个编辑器,在陋巷,人不堪其忧,也不改其乐的黑客比比皆是, 但二十多年过去了, 现如今开发环境发生了巨大的变化。 比如说,相比较于当年程序员使用的基于文本的环境,在 GUI 下格式丰富的文档显得更直观,阅读体验更加好;就算工作中不需要开发任何 GUI 程序,现代开发人员也会使用 GUI 来完成网页图片和文档阅览等等。 因此,即使是最传统的用命令行的开发人员,其实也能沾 GUI 的光。 比如说现在最好的终端程序,都是 X 下模拟的,因为这些模拟的终端的出现,一些复杂的可视化功能可以在这些终端中实现了,比如 Unicode 的显示(rxvt-unicode)等等。

对于开发人员,拥有一组非常好用的,能够最大程度的提高生产率的开发工具乃是一大人生梦想。那么,这套开发工具从何而来呢? 大体来说,这些工具来自于三个方面: 1. 通过系统和单一的应用软件提供的;2. 通过搭配使用各种应用软件 3. 通过定制和改变现有的应用软件。 这三点,对于 UNIX 开发人员是再熟悉不过的了, 无非就是写脚本,走管道而已。 所以,在前 GUI 时代,这一套哲学非常盛行, 开发人员都知道,需要通过安装脚本解析器,写一些的脚本,配置一些环境等等,才能把刚出厂的 UNIX 系统,改造成自己使用起来得心应手的系统。 基本上任何一个使用 UNIX/Linux 系统多年的人,机器里面都有各种各样的“私藏”的脚本。离开了这些脚本,他的效率会大打折扣。

GUI 时代传统的丧失

上世纪 80年代的时候,GUI 时代和个人计算机普及的时代降临了。从此,计算机变成了个人电脑,历史上第一次,计算机不是专为开发人员设计,而是为了普通用户设计。普通用户的需求就是完成一个一个的现实问题,软件产业提供的解决办法就是为用户提供一个一个的应用软件,而不是让用户自己一行一行的编程和写脚本,巨大的软件需求瞬间成就了一个巨大的软件产业。 这样的一个间接后果就是,对于普通用户来说,让一台计算机变成能够帮助自己完成任务的“个人计算机”的唯一手段,就是叠床架屋的不断的装各种应用软件。

我们可以用一个简单的例子说明这种使用模式。 我们都知道,安装 Windows 系统的一个经验原则是把操作系统和应用程序分成两个逻辑盘,一个在 C 盘,一个在 D 盘。这个磁盘分区的经验原则不光网吧老板知道,连我大学里面只会点鼠标的那些女同学都知道。为什么有这个奇妙现象呢?其实,这是由 Windows 系统的用户的典型使用模式决定的。 在 Windows 系统上, 应用程序和文档是关键,操作系统只是一个随时可以重装的东西而已,所以干脆两者分开,互不影响。在这样的使用模式引导下,Windows 系统上格盘重装是非常低成本的,只要文档不丢,应用程序不丢就行。这种使用习惯,浪费了多少 geek 男美好的时光为人重装系统,又促成了多少美妙的姻缘 :)。 总之,在 GUI 时代,要解决一个问题,就装一个应用程序。至于应用程序之间的通信,和用非键盘鼠标的方法控制应用程序等等,都不再是要考虑的问题,有这样的需求的人成了非主流,非主流到以致于主流的操作系统和应用软件都不让你这么干了。 操作系统把所有其他的路都封死,就是明摆着告诉你,要想某样功能,请出门买软件。

Smalltalk 的启示


其实 GUI 时代原本不应该是这样的。 我们都知道,GUI 原本是施乐的 Alan Kay 那一帮人做科研做出来的,Bill Gates 和 Steve Jobs 各自到施乐”抄袭” 了一部分过来,于是窗口啊按钮啊就到处都是了。 他们都看到了图形界面和面向对象的形, 看到了图形界面就是把按钮图标等等对象放好,然后鼠标点击拖动等等这些表面的东西。 因为所有的 GUI 界面都是从文字界面起步的,所以所有的 GUI 程序,其实就是原来的可执行程序的包装。 C++ 这个语言的出现也很讨巧,把 C 包装成了一个面向对象的语言,包装对包装, C++ 很讨巧的适应了把可执行程序 GUI 化的趋势, 成了 GUI 时代的主流开发语言。从表面上看,只要运行这些可执行的程序,就能够看到图形界面,就能够用鼠标点击操作他们,可是这些东西的底层,都是一个编译过了的可执行程序,原先 Smalltalk 中的那些运行时环境啊,对象容器啊,都统统不见了,所有的图形界面程序,还是直接运行在计算机的 CPU 上,而不是一个虚拟的面向对象的容器上。而这个面向对象的容器(也叫做“运行时”或者“运行环境”),才是 Smalltalk 的神。 简单的说,Smalltalk 本身具有一个面向对象的运行时,所以即使到了执行的时候,里面所有的对象还是可以互联互通的。 而 C++ 写出来的程序,除了编译之前是面向对象外,只要一编译,就全部变成机器码,和对象就再也没有任何关系了,也就不存在运行时去动态的查看(inspect) 和改变(modify) 这些程序对象的说法。 总之,因为历史的局限,这些 GUI 的平台,都是渐进的照猫画虎的演变的,所以没有一个平台像 Smalltalk 那样细致地考量过对象的互相通信的问题,再加上我们上面说了,反正扩展系统的方法就是引入新的应用软件而已,本身也没有互联互通的需求,所以这种抛弃运行时的,不让对象被外部程序控制的实现方法也无所谓不好。

可是开发人员不是普通用户啊,他们依然要改造计算机成为自己的工具的。在现有的现有工具不能解决问题的时候,要不然自己重新发明轮子,要不然就复用现有的一些工具,或者重新按自己的需求重新配置这些工具。 所以,和一般用户不一样,开发人员需要这些 GUI 的可配置性,也需要这些 GUI 程序之间的互联互通。 用黑话来说,第一个问题关系到 GUI 应用程序的脚本化, 第二个问题关系到 GUI 程序之间的进程间通信。 这两个问题,说起来简单,但都牵扯到 GUI 系统的根本设计问题。 历史在这里开了一个不大不小的玩笑,把这个唯一的机会给了 Mac OS X。其他操作系统,都因为这样那样的原因,在这两个问题上没有很好的解决方案。

进程间通信,苹果的方案

花开两朵,各表一只。我们先说 GUI 程序的进程间通讯的问题。 所谓的进程间通信 (IPC),就是两个程序之间的信息共享。 我们都知道,*nix 的一个强大之处就在于管道,管道是最简单,最廉价也是最常用的 *nix 进程间通信的方法。在 GUI 时代,最常用的 IPC 机制成了剪切板和鼠标拖放操作。这两个操作虽然都很直观,但都要人操作,离开了人,程序根本无法自动完成进程间通信。 而要工作效率的提高,就是要让计算机离开了人的干涉,也能完成这些任务。为了自动化这些任务,操作系统就不能简单的绘制窗口然后万事大吉了,它必须要知道哪些程序在运行,哪个运行的程序可以给哪个程序发消息通信等等,比如说,如果我们想自动的在阅读器里面选择一个词送给字典程序查释义,计算机就需要知道字典程序在运行的时候可以接受一个字符串,但是不可以接受图片。如果我们把字典程序抽象成一个可以提供“查字典”服务的对象的话,毫无疑问,如果想要向字典程序发送字符,必须首先知道字典程序能够接受什么,用什么方式把这个单词发送给字典等等。 所有的这些信息,都必须由操作系统托管才行(不可能每个应用程序里面都要记着字典这个程序能接受字符串不能接受图片,这样每个应用程序都要记下所有其他可能的应用程序的信息,这是一个平方级别的关系,需要开发人员开发一个程序的时候还要兼顾其他所有程序,这显然是不现实的)。用行话来说,必须要有一个统一管理的运行环境,来管理这些程序之间的互相通信问题。 我们上面说了,Smalltalk 的神在于一个统一的面向对象的运行时,使得所有的应用程序能互联互通。 可是所有平台上的 GUI 程序的演化进程都没有走这条路,而是只把外表给模仿走了;有的平台即使想做互联互通,也做得不彻底(比如微软的 OLE,COM 等等)。

是好东西,总会发光的。 但是要想让这个好东西被新的操作系统全盘采纳,要想让一个系统能够从底层到上层全部采用统一的运行环境,就要扔掉很多的历史包袱。甩掉这种历史包袱,对于任何操作系统都是不容易的。如果我们回到当年,一定会幻想,要是有个神人,能够不管市场也不管现有平台,从头打造一个没有任何历史包袱的干净整洁的 GUI 系统该多好。 历史就是这么戏剧,还真就安排了一个人,做成了这件事情,这个人,就是那个斯蒂夫乔布斯。

1985 年,乔布斯被苹果扫地出门,成立了 Next 公司, 一心想要做出质量上乘的 GUI 计算机系统。 历史给了乔布斯一个全部从头做的机会。这一次,乔老师和 Next 的开发人员意识到,光照搬 Smalltalk 的形是不行的,要连它的神也拿过来,重头设计进程间通信和 GUI 系统。 在内核层面,他们用了 Mach 这个为 BSD 设计的微内核。 这个操作系统内核就是为了替换已经过时的 UNIX 内核而设计的,其中的一个核心设计哲学就是重新设计进程间通信; 虽然现在基于微内核的操作系统已经不是什么潮流(为此 Linus 和 Tanenbaum 吵了一场著名的架),但在相比较于当时 UNIX 系统的内核(此时 Linux 还没出现的,UNIX 内核只有 BSD, Bell, SUN 等几套),Mach 算是一个高的起点。在这个内核上,Next 公司的工程师开始构建面向对象的基础系统。 这套系统在 Smalltalk 中已经有了蓝图,因此这些工程师以 Smalltalk 为蓝图,先设计了一套基于 C 的语言,也就是 Objective C,照搬了 Smalltalk 的经典的 [对象 消息: 参数] 语法。 (我个人不喜欢 Objective C 这个语言,Smalltalk 是一种纯面向对象的动态类型的语言,Next 公司当年完全有机会用 Smalltalk 语言的,如果用了 Smalltalk,现在的 Cocoa 框架还会更加漂亮,代码更加干净;用 Objective C 这个自创的语言,不知道是不是因为专利的考虑,反正 Objective C 这20年的所有创新,就是在慢慢的更像 Smalltalk 而已,Java 和 Ruby 这几年也是不断的从 Smalltalk 拿东西)。有了内核,有了语言,Next 构建了一个纯的面向对象的运行环境和类库(和 Java 和 .Net 的统一类库想法类似,只不过超前了十几年), 这套类库,在当时叫做 NextStep, 所以所有的类名前面都带有 NS 前缀,无比丑陋。可惜的是,当年这个超越时代的类库太阳春白雪了,话说 Smalltalk 超越了时代 20年,所以90 年代中期的时候, 程序员才想起来当年 Smalltalk 的好,出现了 Java Ruby 等等受  Smalltalk 启发的语言。 乔老师虽然落后了 Smalltalk 5 年,却领先也业界 5-10 年,所以在 1995 年的时候, Windows 95 卖疯了, 乔老师的 NextStep 却没动静,只能把这个类库重新打包当成 Web 类库卖卖,即 WebObjects。这倒是无心插柳,生意不错,因为当时的 Web 开发已经吃尽了没有一个统一的运行环境的苦头(这也是日后 Java 风行的原因)。 我们说,是金子总要发光的,但是前提是要 (1) Next 再等几年,等业界回过神来认识到它的好处,(2) 获得一个主流的操作系统支持,把底层全换成乔老师的东西。 乔老师也知道这两个条件,所以加快了和 SUN 合作的步伐,想要把这套系统放到 SUN 的工作站上。 但是 SUN 本身有很强的底层技术,那段时间又狂推 Java, 所以其实乔老师在 SUN 这条路上胜算不大,况且 SUN 自己内核技术很强,所以肯定要肢解 NextStep 把内核重写,如果不和 SUN 玩,一来Next 这家公司能够多撑 5 年都是问题,二来几乎每家做个人计算机的公司都倒戈微软了,其他做工作站的公司又都有自己很强的底层技术,不可能用乔老师的玩意儿的,所以看起来乔老师和他的阳春白雪好像前景不妙。 可是天无绝人之路,放眼看当年的市场,只有一家公司没有倒戈微软,又没有很强的底层技术,又和乔老师有一些渊源,历史就是这么戏剧,这家公司就是把乔老师扫地出门的苹果。

90年代中期苹果的日子很不好过,个人电脑市场败给了 Wintel 联盟,新兴的市场上成绩也一塌糊涂,投资人也不糊涂,把当年让乔老师扫地出门的 Sculley 也扫地出门了,随后就把乔老师的公司给买了回来,让乔老师复职负责复兴苹果。 所以,上面我们说的两个条件就这样突然的满足了: 第一,他现在是老大了,所以可以彻底的把原来苹果的系统推倒重来,用自己的新家伙;第二,原来 Next 公司的那帮工程师不要担心失业了,现在由苹果负责发工资了,所以,正好可以让这些人着手改造苹果系统,主要的工作就是用自己带过来的新系统取代苹果的旧系统,并且让新系统的图形界面和旧系统保持风格的一致。 这个工作,从1995年 Next 被收购,到 2001 左右的时候才做好,这6年的时间里, 乔老师也顺带让苹果重新盈利了。

2001 年发布的 Mac OS X, 是苹果操作系统的第十代,完全基于了乔老师在 Next 开发出来的那套类库,所以自然的,具有了一个统一的面向对象的运行时。 这个运行时和类库系统,Mac OS X 把它叫做 Cocoa。其实 Mac OS X 刚出来的时候也不怎么好,不过依赖于这套设计精良的底层系统,Mac OS X 的迭代开发周期要比其他操作系统短多了 (仅慢于Linux, 不过 Linux 只有内核部分). 在短短的 8 年里,Mac OS X 就搞出了 7 次大的版本发布。 虽然我们看 Mac OS 好像从 10.0 到 10.6 只是次版本号在进步, 其实每次都是一个 major release, 大致相当于从 Window 95 到 Windows 98 或者 Windows 2000 到 Windows XP 这样级别的升级。 这样的发布却不改主版本号,一方面是从市场上考虑,另一方面也的确说明 OS X 的底层已经处于一个相对稳定的状态。 有很多 Windows 程序员非常推崇 .Net。 是的,.Net 的确是一个非常好的框架,可是想像一下,苹果在1995年的时候就有了一个统一的运行时,加上这么多年所有的程序都在这个统一的框架上开发,如果论在 Mac OS X 这个平台上的经验积累,应该说 Cocoa 社区是比 .Net 社区更加成熟的。

应用程序脚本化

光有进程间通信的系统还不能算是一个完全成熟的 GUI 系统,因为进程间通信依然是相对底层,而 GUI 上的应用软件是层出不穷的,不可能任何问题都跑到底层用进程间通信解决;所以,要想让 GUI 系统进化到易用和易于定制的水平,就需要开放对 GUI 程序的脚本控制。只有 GUI 程序能被外部控制了,才能真正的达到搭配使用 GUI 系统的效果。 其实,一旦有了一个统一的运行时,只要开发应用软件的时候统一设计一下脚本接口,用脚本控制 GUI 程序应该不难。 比如说,微软的 Office 系列套件, 就完全可以用 VBScript 去控制。 可惜的是,没有一个系统能够实现全系统的控制。 要实现全系统的控制,不仅仅要这个系统能够提供底层的支持,更重要的是要能说服所有的开发人员,或者说让所有的开发人员养成开放脚本接口的好习惯。 从技术上来说,这不是太大的问题,只要开发人员按照统一的脚本通信协议,实现特定的接口就行了,可是,如果一个平台上开发 GUI 的方法太多,开发人员只选自己喜欢的来,这种标准就不可能统一。 比如说 Linux 上 KDE 和 Gnome 都有自己的脚本化系统,可是开发人员有的用 KDE, 有的用 Gnome, 有的干脆两者都不用,这就谈不成有一致的接口。 一个平台要想有一致的脚本控制接口,除非 (1). 这个平台上就一种 GUI 开发方法,自古华山路一条,要不不做,做出来的东西就只能是标准的接口; (2). 这个平台上大部分的,主流的应用软件,都实现了这个脚本接口,这样因为这些程序的拉动,其他 GUI 程序想要融入这个平台上现有的应用软件的圈子相互通信,那也就必须要实现这个接口。 在 2000 年的时候,又只有一家公司能够同时满足这两个要求,就是苹果。 微软部分做到地了这两条,基本上用 VBA 统一了 Office 的控制,但是跳出 Office,微软的 OLE 对象模型几乎没有任何用武之地,与之捆绑密切的 VBA 自然无人问津。 不过据一些在金融行业工作的朋友说, VBA 能够大大提高 M$ Office 的生产率。

GUI 脚本化不是一夜之功,特别是我们说要做出统一的脚本接口,能兼顾各种程序的需求,这就完全不是一两年的时间能够搞定的,总需要很多年的技术积累和设计取舍后才能收敛到一个相对稳定成熟的系统, 而苹果,居然很神奇在十几年前就有这方面的经验,苹果再次怎么这么幸运呢?

在 80 年代后期的时候,苹果机上有一个非常超越时代的软件,叫做 Hypercard。 这个软件我曾经在上一代苹果上玩过,具体的思想就是你可以存储一张一张的“卡片”,这些卡片上面可以放置多媒体的声音,图像文字和其他对象,基本上就和现在网页一回事,唯一的区别就是这些卡片都存在本机。 在没有 Powerpoint 这类软件之前,这个 Hypercard 的软件可以用来做课件,做幻灯片演示等等,是个极其强大的工具。 为了让用户可以定制这个卡片,这个程序提供了一套非常强大的编程系统,叫做 Hypertalk。 因为这种编程语言是给普通人而不是程序员用的,所以你会感觉根本不是编程,而是写英语。这套东西,虽然本质上也是从 Smalltalk 学来的,但是用英语语法的方法编程的确是一个全新的思路,苹果把这个给普通人编程的语言发扬光大了,用更加贴近自然语言的方法重写了语言和文档,模仿 Hypertalk 系统,发布了一个跨系统的脚本控制语言,叫做 Applescript。这个语言就和自然语言没什么区别,比方说, 获取窗口的大小不再是
window.getSize()
而是
get size of window

显示第 22 段的 第一个单词不再是
print(paragraph[22].getWordByIndex[0])
而是
print the first word of paragraph 22

更狠的是,你还能用法语和日语写。 80年代后期的时候和整个 90年代初期,苹果基本上已经被 PC 机逼到墙角了,只剩下出版行业,设计行业等等专业的行业因为应用软件和图形处理能力的关系,依旧在守着苹果机。 两个行业的用户都需要自动化的 GUI 控制,但是编程都不怎么样,于是,这些应用软件的开发商也主动掺合加入 Applescript 旗下。 在90年代乔老师没有加入前,苹果自己把 Finder 全部脚本化,出版业的 QuarkXPress 和 Filemaker 也都完全脚本化,等乔老师入主苹果后,基于 Cocoa 的新技术,苹果一口气在 Mac OS X 上推出了 Safari, iTunes, iPhotos 等等软件,一股脑儿的全部脚本化了。 在别的公司都可望而不可求的历史机遇,又是被苹果给抓住了,一股脑儿全部塞进了 Mac OS X。这下,所有的第三方开发的工具,如 Firefox, Adium 这些,其实本来都不是苹果开发的,也没有太强的苹果渊源,但是 Firefox 要读 Safari 书签吧,哈,那就用 Applescript 吧,所以, Firefox 也逼着脚本化了(这个在其他平台上都不存在的事情)。 Adium 也是,这个聊天软件想要把 iTunes 正在播放的歌曲当成状态信息,好呀, Applescript,所以,也被带着脚本化了,而在 Linux 上的对应产品 pidgin 就没有这么脚本化。 所以,苹果平台已经成了一个惯性,你不想脚本化,就不带你玩,看你还脚本化不?

结语

我们都知道, UNIX 时代的主要哲学是提供给开发人员一组小巧精美且可以任意搭配使用的小工具,也就是所谓的 Software Tools, 然后任由开发人员由此出发,自己搭建自己的工具,打造自己的瑞士军刀。而开发人员所用的操作系统的目的,要不就是提供这样的一组开发工具,要不就是为这样的开发工具提供一个便利的平台,使得这样的工具变为可能。如果说 UNIX 是命令行时代的一个易于改造成 “自己的操作系统” 的操作系统的话, Mac OS X 就是 GUI 时代的这样的一个操作系统。 即使是从应用软件的层面看, Mac OS X 的底子好,更加容易出精品软件,所以即使仅使用应用软件,开发人员也应当优先考虑 Mac OS X。

附A: 相对正确的 Mac OS X 使用习惯

0. 一定要装 Quicksilver 或者用“服务”,否则就是把苹果当 Windows 用。
1. 在苹果计算机上,因为有服务和 Quicksilver 这样的工具,90% 的程序间的拷贝粘帖都是可以避免的。
2. 剩下的 10% 的程序内的拷贝粘帖,如果用一个好的编辑器的话,又可以省略掉 90%。

附B: 为什么 Linux 系统在这个方面还不够好

第一, Linux 上的 GUI 子系统,其实不是 Linux 的一部分,而是 X 和上面的 KDE 以及 Gnome
等等。 这几年,这些系统终于开始统一管理一个面向对象的运行环境了。可是这两个系统都是用C++ 所写,所以免不了费很大的力气才有了运行时信息,绕了一个大弯路,如果一开始这两个系统就用 Smalltalk 之类的有运行时的语言编写,至少现在应该有能和 Cocoa 抗衡的框架。

第二, 这几年 X 也认识到了在脚本化控制上面的不足,所以几年前做桌面的 Redhat 提出了 DBus 标准。 可惜的是不是每个程序都开放了 Dbus 接口,所以和苹果比起来,还有比较长的路要走。