Mar 7, 2010 - 帮我弟弟找园林建筑相关行业的实习

Comments

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

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

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

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

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

Feb 27, 2010 - 开发人员为何应该使用 Mac OS X 兼 OS X 小史

Comments

一周前我和 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 使用习惯

  1. 一定要装 Quicksilver 或者用“服务”,否则就是把苹果当 Windows 用。

  2. 在苹果计算机上,因为有服务和 Quicksilver 这样的工具,90% 的程序间的拷贝粘帖都是可以避免的。

  3. 剩下的 10% 的程序内的拷贝粘帖,如果用一个好的编辑器的话,又可以省略掉 90%。

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

第一, Linux 上的 GUI 子系统,其实不是 Linux 的一部分,而是 X 和上面的 KDE 以及 Gnome

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

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

Feb 10, 2010 - 编程珠玑番外篇-I. 高级语言是怎么来的-5

Comments

LISP 语言是怎么来的–LISP 和 AI 的青梅竹马 B

上回我们说到 LISP 和 AI 很是青梅竹马的时候,浮光掠影地说因为 LISP 的基本数据单元–“链表”在知识表示上的比较优势。 我们说, AI 要处理的数据结构和要刻画的现实世界的模型很复杂,使得数组等其他简单数据结构不能胜任,所以“链表”成了最佳的选择。 如果我们顺着这样的逻辑线往下看,似乎选择 LISP 这个“列表处理的语言”似乎是理所当然的。 可是,这个原因并不充分。 因为 LISP 语言可不仅仅是列表处理,还包括函数式编程等等其他。 反过来说,如果仅仅是列表处理对于 AI 至关重要的话,那么在 FORTRAN 和 Algol 这些通用编程语言又非常普及的传统语言里面写一些关于列表处理的函数岂不是更加直观和方便? 归根结底,到底 LISP 还有什么其他奥妙呢?

当我们追寻函数式编程这条线索的时候,就会不可避免的触及到 AI 的早期历史。LISP 的特性,其实都是和当时 AI 的范式 (paradigm) 息息相关的。

AI 范式的演变

早在 McCarthy 这一代人提出 AI 之前,冯诺伊曼等人就开始研究什么是智能以及如何实现智能的问题了。 所不同的是,他们更加偏重于研究大脑的内部工作机理,并且试图通过在模拟大脑的工作机理,来实现智能。 这一学派的哲学很清晰: 人类大脑是一个标准的智能体,我们只需要让计算机模拟人的大脑的工作方式,计算机就有了和人类大脑一样的智能了。 对于这一派的研究者来说,他们相信大脑的结构和工作机理决定了智能,至于大脑是用脑细胞构成的,还是用电子电路模拟的,对于智能来说毫不重要。 这方面的著名工作就是冯诺伊曼的《计算机和大脑》这篇论文。 在这篇不算很学术的随笔里面,他分析了人的大脑有多少个神经元,计算机有多少个晶体管,通过这些定量的比较来解释计算机和人的大脑的差距。 当时和冯诺伊曼齐名的另一个神童是开创控制论的维纳。 他和冯诺伊曼一样,兼通很多学科。 和冯诺伊曼一样,他职业是数学家,但是也精通如神经科学和脑科学等学科。一个显然的例子就是在《控制论》这本书里面, 维纳对大脑和神经的分析比比皆是。这种对大脑和神经分析的传统,从 Cajal (对,就是写 Advice for a Young Investigator 的那个大神) 开始,一直延续到了后来 AI 中的联接主义(主要研究神经网络的一个人工智能学派)。

可是,从脑科学和认知科学的角度去分析智能在当时有一个非常大的局限: 脑神经解剖学本身不成熟。 比方说,现如今脑科学家在分析脑功能的时候一般会借助于 fMRI 和其他一些神经造影技术。这些技术可以做到实时观测到脑中血氧分布,直接确定大脑在执行特定任务时候的活跃部分。当年的科学家则只能使用有限的几种医学成像技术,或者从血管摄影的角度研究大脑。 受限于当时的研究条件,当年的研究者很难直接观测到脑神经的实时工作状态,分析大脑的实时工作机理。 因此,对脑的研究就很难做到非常深刻。 医学研究条件的限制,加上当时电子学的发展和集成度远远不够,用电子电路模拟大脑生成智能就显得非常遥远。 因此,虽然这一派的思想超前,但是大部分的工作都不在于真正的用电子电路模拟大脑,而是在探索脑科学和神经科学本身,或者仅仅用电子电路模拟一些简单的神经动力学行为和小规模神经网络。正是因为连接主义在实现人工智能本身方面进展并不大,所以在AI领域中一直不是潮流的研究方向。上个世纪 80 年代前成功实施的一些人工智能系统,极少是来自于连接主义学派的。直到80年代后随着 BP 算法的重新发现,联接主义才迎来了第二春。 这时候,LISP 已经过完 20 岁生日了。所以,联接主义 对 AI 领域使用的编程语言的选择的影响并不算大。

符号主义

虽然联接主义这一学派在当时不怎么流行,当年的 AI 研究可是进行的如火如荼。这如火如荼的学派,采用的是另外一套方法,我们称之为“符号主义学派”。 符号主义学派的渊源,可以直接追溯到图灵。图灵在人工智能方面做过很多的研究,其中最为大家所知的就是“图灵测试“了。 有句俗话叫做“在网上,没人知道你是一条狗”, 在这句话里,只要把“狗”换成“计算机”,就是简单版的图灵测试了。 用个比较“潮”的比方,图灵测试就是让一台计算机或者一个真实的人(又叫评委)在网上交流,然后让这个评委猜测和他交谈的究竟是人还是计算机。 如果这位评委也不能分辨谈话的对方到底是人还是计算机的话,我们就认为这个计算机已经足以“以假乱真”,拥有“和人类一样的智能”了,也就是通过“图灵测试了”。

在很长一段时间里,图灵测试一直是人工智能研究的圣杯(holy grail)。 也就是说,通过”图灵测试“ 成了人工智能研究的终极目标。 那么,自然的,最最直接的通过图灵测试的方法不是让计算机和人脑一样思考,而是只要能够让计算机处理对话中用到的的单词,句子和符号,并且在对话中能够和人一样的操纵这些单词和符号,计算机就有很大的希望通过图灵测试。 从最极端的情况来看,计算机甚至都不需要去“理解”这些句子的含义,都有可能通过图灵测试。 [具体细节可以阅读 Wikipedia 上的“Chinese Room (中文房间)”条目]。 有一个开源的聊天机器人,叫做 A.L.I.C.E., 就把上面我们说的“只要能够处理和操纵符号,就有可能通过图灵测试”发挥到了近乎极致。 这个聊天机器人在图灵测试比赛中已经多次骗过人类评委,到了非常“智能”几乎能以假乱真的地步。可是,就是这样一个离通过图灵测试很近的机器人,其基本结构却简单到了我们都不能想像的地步:A.L.I.C.E.  的数据库里面有一条一条的规则,这些规则规定了她看到你说什么的时候她说什么。唯一有点“智能”的地方,就是有些规则不光取决于你这句话,还取决于你的上一句话。 [比如日常对话中我们先问“你喜欢看电影么?”,接着再问“什么类型的?”,这时候就需要前一句话推出这个问题是“(喜欢)什么类型的(电影)”]。“中文房间”的例子,和 A.L.I.C.E. 机器人如此简单的结构,都出人意料的显示出,即使计算机拥有了对符号的操作能力,通过了图灵测试,它也未必是是“有智能”的。 可惜这句话只是我的马后炮而已,在 AI 发展的早期,因为图灵测试的拉动,联接主义的相对弱势和符号主义的繁盛,都把全世界的 AI 研究往一个方向拽,这个方向,很自然的,就是“符号处理”。

符号处理和 LISP 补充

其实上一篇我们已经提到了,Alan Newell 和 Herbert Simon 认为对符号演算系统就可以衍生出智能,所以上面的文字,算是对符号主义这个 paradigm 做一个历史的小注解。 当我们把 LISP 放到这段历史中,就会自然的想到, 什么语言适合人工智能的问题,就变成了“什么语言能做符号处理”。这个问题的答案,读者也都猜到了,就是 LISP。

符号处理在 LISP 里面的长处前文我已经介绍过一些了,这里我们可以再补充几点零碎的。LISP 里有一个大家都知道的统一表示程序和数据的方法,叫做 S-Expression。 这个 S,其实就是 Symbolic 的意思。 把程序和数据都统一的当成符号,用现代编程语言的话说,就是 LISP 支持 meta-programming。LISP 程序可以处理,生成和修改 LISP 程序。这个特性,加上函数是一阶对象的特性,使得 LISP 远远比同时代的任何语言灵活。我本人不是 LISP 的用户(初级用户都算不上),因此在这一点上所知有限。但单就我有限的对 LISP 的理解,我认为 LISP 的这种灵活,恰好满足了基于符号处理的 AI 领域对语言的“强大的表达能力”(可以对任何复杂系统建模)和“高层的抽象能力” 的需求。关于第一点,有一个著名的段子,说任何一门编程语言技巧和思想被提出的时候,总会有一个高人出来,说,这个玩意儿在 LISP 里面早就有了,具体的例子包括刚才说的 metaprogramming, object oriented language。这里面蕴含的,就是 LISP 的强大的表达能力,使得很多编程的范式,在 LISP 里面都能实现,或者找到影子。 关于第二点,SICP 中例子比比皆是,讲得都比我深刻许多,就无需废话了。

在上篇文章中我提到,翻开任何一本编程的书,都会讲到“LISP是适合 AI 的编程语言”。那么,如果您和我当年一样,有兴趣从事 AI 方面的研究和探索,就不免要疑惑:“为了学习 AI, 我要不要学习 LISP” 呢?现在距离我当年的这个疑惑已经差不多8年了,我并没有一个确定的答案,但是我知道了更多的一些事实。

如今的 AI 范式

如果你让任何一个 AI 方向的研究者推荐几本适合初学者的书的话,十有八九他会提到 “Artificial Intelligence: A Modern Approach”(人工智能,一种现代方法) 和 “Artificial Intelligence: A New Synthesis” (人工智能,一个新的综述)。 这两本书的作者分别是 Peter Norvig 和 Nils Nilsson,都是 AI 领域的元老级人物。 如果你是一个对书名很敏感的人,你肯定会想:奇怪了,这种书又不是畅销书,难道这两位大牛写了书怕卖不出去,非要在书名上加一个 “现代” 或者 “新” 来吸引眼球? 事实上,这个“现代”和这个“新”都大有来头。 实际上,这二十年来,AI 研究领域接连发生了好几个非常大的 paradigm shift. 传统的基于符号的 AI 方法不再是主流,取而代之的,是多种多样的基于统计的,基于自动推理的,基于机器学习的,基于群体智慧的,基于大规模数据集的等等各种各样研究方法的兴起。 这个 paradigm shift, 对于领域之外的人好像是静悄悄的,可实际上 AI 领域早已发生了翻天覆地的变化。所以才会有 “新” 和 “现代” 这样的词出现在书标题上。 不幸的是,大多写编程语言书的作者,未必全部知晓这个变化,因此还沿袭原来的框架,继续写下 “LISP是适合 AI 的编程语言” 这样一个早就不能完全反映现状的断言。 如果我们统计一个从事 AI 研究的研究者或者科学家用什么语言,答案可能是五花八门无所不有: 做 AI Search 的用 C/C++/Java, 做机器学习的如果模型和矩阵关系密切,可以用 Matlab, 如果统计计算较多,也可以用 R。 至于做数据挖掘等等,语言和库更加五花八门,根本无法宣称那一个语言占上风。LISP 是适合 AI 的语言的教科书神话,也早就被无数的这样的实例给打破了。

延伸阅读:

http://stackoverflow.com/questions/130475/why-is-lisp-used-for-ai

Feb 3, 2010 - 从无知到有知

Comments

[这篇文章是以前写的,主要是提醒自己的]

人的一生是要不断学习的。这里面的动力很简单:因为我们在有些方面还“无知”, 无知是做事情的一个障碍。我们如果想做好事情,就要求知,要改变这种无知的状况。

可是大多数人不知道的是,“无知” (ignorance) 其实不是一个状态,而是两个截然不同的状态,一种叫做不知道型无知 (uninformed ignorance),另一种叫做知道型无知 (informed ignorance)。 相信很多人都有这个体会:某天看到一本书,一篇文章,觉得这里面的学问知识,是自己从来没有想过或者接触过的,是一个崭新的领域,这就代表了你突然发现了自己的无知,而且知道自己的这种无知,也就是,从 uninformed ignorance 跨入了 informed ignorance. 这两种无知的另一个不同在于,第一种无知可以让人无知无畏,因为自己不会认识到这种无知。第二种反而让人小心翼翼,知道自己不懂这方面的知识,或者咨询专业人士,或者恶补相关的知识。我们人生下来,所有的知识都在脑袋的外部,所以,我们最初处于一个纯粹的 uninformed ignorance 状态, 所以,从无知到有知,必然要经过两个过程,第一个过程是从第一种无知变到第二种无知;第二种是消灭部分的第二类无知,达到部分有知。 这两个过程其实截然不同,但是实际上我们常常把他们混淆。

第一个过程其实是非常轻松愉快的过程,甚至不需要花太多的力气。有句话叫见多识广,就是说游山玩水也能增广见识。 在互联网发达的今天,随便点几个链接,随便查几个维基百科,都能够让人获得“增长见闻”的感觉。 这是一个好事,因为我们更加容易的发现自己的无知。 同时,在这个过程里也很容易有认知满足感。 所以,很多人不知不觉的觉得每天只要“增广见闻”就行了,轻松愉快又每天都有新的见闻输入,是多么美好的事情呀。不幸的是,这个过程至多只能让人 informed, 而不能让人 knowledgeable。 想要 knowledge, 绕不过去的是持久的,深入的,有系统的学习。更加不幸的是,这个过程是不那么轻松愉快的。

我上高中的时候非常喜欢数学,正好图书馆里面有大学数学书,我就不管看得懂看不懂都借来看,看着那些如“微分方程”,“复变函数”之类的名词觉得很欣喜,虽然是不断的发现自己以前的无知,却也觉得学到了新东西,新名词,新概念。可是总所周知,“看”是不需要花费任何脑力的,尤其是从不知道到知道自己不知道这个状态,简直就是所谓的顿悟(由此我也怀疑所谓的顿悟其实可能也是突然间觉得自己是个笨蛋,也就悟了)。 就这样,我一度以为自己在数学上是非常的 knowledgeable 了。 然后我大学上了数学系,我突然发现,高中看的那些书,虽然也看了,也仅仅是知道名词 ( informed ) 而已,真正的数学训练,还是等到我用书中知识做后面习题的时候才开始的,而这个过程才不是轻松愉快呢。 我不知道是不是普遍的情况,就我见到的同学,有很多高中原来很喜欢某个专业的,等到真的选了这个专业,突然就不喜欢了,这也是 be informed 和 be knowledgeable 两种认知过程不一样造成的。 这种两种认知过程,是不管怎么都没法互相替代的。换句话说,如果只想捡便宜果子吃,只做第一步,或者用第一步里面的那些轻松愉快来代替第二步,就想变成有知识的人,是不可能的。

缺少持久,系统和深入的学习,知识结构就会处于半调子的状态。 李笑来老师在学英语的若干文章中都提到精读和查字典的重要性。比如说,如果在学英语中满足于 informed ignorance, 遇到不认识的单词仅仅是猜一个意思,也不记下这个单词的用法的话,这个单词还是不能成为自己的词汇。然后,如果仅仅是记下用法,而不在以后有意识的练习使用(或者多次再见到)这个词的话,或许很快也就忘掉了。我们对学语言要系统的精耕细作很同意,但是未必能体会到所有其他学科都需要如此,尤其是在那些我们认为“简单”或者“零碎”的领域,我们往往像蜜蜂一样,成了不知疲倦的收集者,不断的 be informed, 而忘了 be knowledgeable 的背后,不是收集,而是学习。知道自己无知是一件非常好的事情,不过不要容忍处于 knowledge 和  be informed之间的尴尬处境,要不代理给专业人士,要不,抓紧时间学习,赶快从无知,到有知。

Jan 23, 2010 - 父母来美国旅行的一些事项

Comments

我父母和弟弟前段时间来参加我的婚礼。 签证和一切都比较顺利,所以好几个朋友都发信问我签证啊安排啊什么的,所以我干脆写一篇文章共享一下我的一些经验。 **

**

签证前

让他们办一张双币信用卡,让他们少带现金。 当然也看父母习惯, 比如我爸一向习惯用现金不刷卡,也无所谓,就是带大额现金换汇比较麻烦。

**

签证准备材料**

156 表,157 表。 如果父母不懂英文,可以帮父母填然后 FedEx寄回去,注意核对一下信息的正确性,以及在他们该签名的地方提醒他们签名

158 表签证没有需要

资产证明: 我是让我父母开了一个存款证明,比我这里弄简单多了

学校的邀请信: 让学校国际学生办公室开

给签证官的信: 注意措辞,网上的所有模板几乎都有英语语法错误,不能照搬, 记得签名

**

需要你自己的**

护照, I-20, I-94, SSN 复印件, 成绩单(in case) 学校/系证明你依然是学生的一个信

其他就没有了,网上说的还有啥啥材料的都是锦上添花的,比如照片什么的,不是必须的。

让父母不要紧张, 只要理由充分肯定能过.

旅行简要攻略:

**

** 1。 不要相信中国的交通设施的准时性,一定要提前到机场。 我父母来的当天上海地铁出事故了,幸亏他们随机应变,倒了很多次地铁才到了机场。

2。 在候机的时候,(如果父母不懂英语)让父母多和同机的乘客交谈,交朋友。 我父母就是遇到了好几个好心人,虽然不懂英语,一路有人家协助,很顺利。 还借手机让我父母打。

3。 提醒他们飞机上的食品中,沙拉是冷的。 我父母从来没吃过冷蔬菜。 飞机上有热茶,需要向空姐要求。

4。 随身就带护照等材料就行了,无需要随身带太多东西,不好管理。

5。 入关需要检查的材料里面包含回程机票,所以把机票打印出来随身携带。

6。 冬季航班总是会有延误的,让父母做好心理准备

7。 写一份简要的攻略,包含怎么填 I-94表,怎么填报关表,怎么联系你等等。

**

父母在美国的生活**

1。 为他们买一个热水壶

2。 让他们不要大包小包的带药,美国的 OTC 非常便宜,效果也好。

3。 我父母喜欢到外边溜达,可以画一张家附近的地图和自己的紧急联系方式,让他们至少知道怎么溜达回家。更有钱的可以让父母带上一 GPS 或者 iPhone, 然后随他们走去哪个公园玩 :)

4。 家里有宠物的要考虑一下父母对宠物是不是过敏

5。 无论何时,谨慎驾驶