大多数想法都来自此前的想法。六十年代,在美国国防部高级研究计划局(ARPA)圈内,分时计算机、图形屏幕和指点设备催生了大量人机共生的设想,高级语言被用来模拟炼油厂等复杂系统。随后现代个人计算、重叠窗口界面与面向对象设计的范式转变,正源于把六十年代的工作看作不止是改良旧物。
正文
摘要
大多数想法来自先前的想法。六十年代,尤其在 ARPA 共同体中,通过交互式分时计算机、图形屏幕和指点设备,产生了一大批关于“人机共生”的观念。高级计算机语言被发明出来,用于模拟炼油厂等复杂系统和半智能行为。随后发生的现代个人计算、重叠窗口界面和面向对象设计的范式转移,来自把六十年代的工作看成不只是“更好的旧事物”——不只是更好的大型机计算方式、更好的让最终用户调用功能的方式、更好的抽象数据结构的方式。计算量/美元指数增长的前景要求把六十年代看成“几乎是一种新事物”,并找出实际的“新事物”是什么。例如,用手持 Dynabook 计算的方式不可能在共享大型机上实现;数百万潜在用户意味着用户界面必须成为蒙台梭利和布鲁纳式的学习环境;大范围、降低复杂度和最终用户读写能力的需求,要求废除数据和数据结构,转向一种更生物学的方案:受保护的通用细胞只通过消息交互,并能模拟任何想要的行为。
早期 Smalltalk 是这些新观点的第一次完整实现,它的前身遍布硬件、语言和用户界面设计。它成为新计算的范例,部分原因是我们真的在尝试信念结构的质变——一种与印刷机发明同精神的库恩式新范式——因此采取了几乎迫使这些新风格被发明的极端立场。
引言
我在 35000 英尺高的飞机上写这篇引言。膝上是一台五磅重的笔记本计算机——1992 年的“临时 Dynabook”——到年底售价不到 700 美元。它有平坦、清晰的高分辨率位图屏幕,重叠窗口、图标、指点设备、相当大的存储和计算能力,最好的软件是面向对象的。它内置先进网络,已有无线网络选项。Smalltalk 运行在这台系统上,是我和孩子们工作时使用的主要系统之一。某些方面它已超过 Dynabook(数量上),某些方面还没完全达到(质量上)。总的来说,很像六十年代末所设想的东西。
Smalltalk 是我称为“个人计算”的更大追求的一部分,先属 ARPA,后属 Xerox PARC。每个阶段都有太多人参与,准确分配功劳极其困难。不如像 Bob Barton 常引用的歌德那样,“分享发现的兴奋,而不要徒劳地争夺优先权。”
我会说明大多数影响来自哪里,以及它们如何在新的个人计算隐喻形成的磁场中被转化。Smalltalk 的发明既靠先驱们的伟大想法,也靠他们的态度。我当时最敬佩的许多人,如 Ivan Sutherland、Marvin Minsky、Seymour Papert、Gordon Moore、Bob Barton、Dave Evans、Butler Lampson、Jerome Bruner 等,似乎都有一种极好的意识:他们的创造虽然按相对标准很精彩,但远未达到必须跨越的绝对门槛。小头脑试图形成宗教,伟大人物只想找到更好的上山路线。牛顿说他是站在巨人肩上才看得更远,计算机科学家却常常站在彼此脚趾上。编程语言可以分为命令式、应用式、逻辑式、问题导向式等,但它们似乎要么是“特征的聚集”,要么是“风格的结晶”。COBOL、PL/1、Ada 属于前者;LISP、APL 和 Smalltalk 属于后者。很可能不是偶然,聚集型语言似乎都由委员会发起,结晶型语言由单个人发起。
Smalltalk 的设计和存在,源于一个洞见:我们能描述的一切,都可以由同一种行为积木的递归组合来表示;这种积木把状态和过程藏在自己内部,只能通过交换消息来处理。哲学上,Smalltalk 对象与莱布尼茨的单子、20 世纪物理学和生物学观念有很多共同之处。它制造对象的方式相当柏拉图:有些对象充当概念的理想化——理念——可以从中创造显现。理念本身也是显现,理念-理念是一种显现-理念,而后者又是自身的一种,因此系统完全自描述。柏拉图会把这当成一个极实用的笑话。
用计算机术语说,Smalltalk 是对计算机本身概念的递归。它不把“计算机材料”分成数据结构和过程、函数等每样都比整体弱的东西;每个 Smalltalk 对象都是对计算机全部可能性的一次递归。它的语义有点像成千上万台计算机用极快的网络连在一起。具体表示的问题几乎可以无限推迟,因为我们主要关心计算机行为是否合适,只有结果出错或返回太慢时才关心特定策略。
尽管有高贵的祖先,Smalltalk 的贡献是一种新设计范式——我称为“面向对象”——用于攻击专业程序员的大问题,并让新手用户能处理小问题。面向对象设计是一次成功的尝试,旨在定性提高建模效率,以应对硅爆炸带来的日益复杂的动态系统和用户关系。
“我们若知道他们做的时候怎么想,就会知道他们怎么想。”——理查德·汉明 “记忆和想象只是同一事物的两个词。”——托马斯·霍布斯
在这段历史中,我会尽量忠于汉明的请求,并接受霍布斯观察的调节。以前写 Smalltalk 很难,因为我的情感一直集中在个人计算作为人类触及范围的放大器,而不是编程系统设计,而且我们还没到那一步。虽然我是 Smalltalk 的发起人和原设计者,但它更多属于让它运转并出门的人,尤其是 Dan Ingalls 和 Adele Goldberg。每位 LRG 成员都以深刻而出色的方式贡献。我认为大家都同意,在 Smalltalk 的大部分发展过程中,Dan 是中心人物。编程本质上是一门建造真实事物的实践艺术,所以真实的实现必须存在。事实上,许多语言今天被使用,不是因为有什么真正优点,而是因为它们存在于一台或多台机器上,能自举等。但 Dan 远不止是伟大实现者,他也越来越成为设计者,不只是语言,还有 Smalltalk 进入实用世界后的用户界面。
这里我主要聚焦导致 Smalltalk-72 的事件,以及它向现代形式 Smalltalk-76 的过渡。大多数想法都发生在这里,而 OOP 最早阶段的许多内容记录极差,参考资料几乎找不到。
这段历史太长了,但我惊讶地发现,许多有影响的人和系统只以影子出现或根本没出现。抱歉不能多谈 Bob Balzer、Bob Barton、Danny Bobrow、Steve Carr、Wes Clark、Barbara Deutsch、Peter Deutsch、Bill Duvall、Bob Flegal、Laura Gould、Bruce Horn、Butler Lampson、Dave Liddle、William Newman、Bill Paxton、Trygve Reenskaug、Dave Robson、Doug Ross、Paul Rovner、Bob Sproull、Dan Swinehart、Bert Sutherland、Bob Taylor、Warren Teitelman、Bonnie Tennenbaum、Chuck Thacker 和 John Warnock。更糟的是,我略过了许多我讨厌其设计、但它们通过反作用产生了有用想法和态度的系统。换句话说,“历史”不应被太当真,而应看作演员离场很久后的“微弱手势”。
感谢众多审稿人忍受许多草稿。特别感谢 Mike Mahoney 温和而有效地帮助,以及老朋友 Jean Sammet,她几乎把我吓到必须写完。Sherri McLoughlin 和 Kim Rose 在收集材料上帮助很大。
I. 1960—66:早期 OOP 与六十年代的其他形成性观念
OOP 来自许多动机,两个核心是:大规模上,为复杂系统寻找更好的模块方案,隐藏细节;小规模上,寻找更灵活的赋值版本,然后试图完全消除它。和大多数新想法一样,它最初以孤立的方式断断续续出现。
新想法会经历接受阶段。从内部看,先是几次“隐约看见”一个模式,然后注意到但不理解其“宇宙”意义,再在几个领域操作性地使用它,接着发生“大旋转”,模式成为新思维方式的核心,最后变成它最初打破的那种僵化宗教。从外部看,如叔本华所说,新想法先被谴责为疯子的工作,几年后被认为显而易见、平庸,最后最初的谴责者会声称自己发明了它。
1961 年前后,我在空军当程序员时几次“隐约看见”这个想法。第一次是在 Burroughs 220 上,一种把文件从一个空军训练司令部安装点传到另一个的风格。当时没有标准操作系统或文件格式,某位至今未知的设计者决定把每个文件分成三部分。第三部分是实际数据记录,大小和格式任意。第二部分包含 B220 程序,知道如何访问记录和字段来复制和更新第三部分。第一部分是指针数组,指向第二部分程序的入口点(初始指针按标准顺序,代表标准含义)。这想法很好,后来在许多系统中使用,直到强制使用 COBOL 把它赶出存在。
![]()
第二次隐约看见稍后,ATC 决定用 B5000 替换 220。我当时没有眼光真正欣赏它,但注意到它的分段存储系统、高效 HLL 编译和字节码执行、自动子程序调用和多进程切换、用于共享的纯代码、保护机制等。我看到对程序引用表的访问对应于 220 文件系统提供过程接口给模块的方案。不过,这台机器当时给我的大收获不是 OOP 想法,而是对 HLL 翻译和求值的洞见。
离开空军后,我靠编程读完大学剩余部分,主要为美国国家大气研究中心的大型天气数据集合编写检索系统。
![]()
我对一般模拟感兴趣,尤其是用一台机器模拟另一台,但除了在 CDC 6600 上做一维位字段块传输(bitblt)来模拟各种机器的字长,大部分注意力被学校,或者说是学校剧院,分散了。在 Chippewa Falls 帮调试 6600 时,我读到 Gordon Moore 的文章,预测芯片上的集成硅密度和成本会在许多年里指数改善。1965 年,站在房间大小、氟利昂冷却的 10 MIP 6600 旁,他那惊人预测对我的视野几乎没有投射。
Sketchpad 与 Simula
由于一连串偶然,我 1966 年秋进入犹他大学研究生院,“什么都不知道”。我从未听说过 ARPA 或其项目,也不知道犹他在这个共同体中的主要目标是解决 3D 图形中的“隐藏线”问题,直到我走进 Dave Evans 的办公室找工作和工作台。Dave 桌上有一英尺高的棕色文件堆,他递给我一份:“拿去读。”
每个新人都有一份。标题是《Sketchpad:人机图形通信系统》。它能做的事相当惊人,和我遇到的任何计算机用途完全不同。最容易理解的三个大想法是:它发明了现代交互式计算机图形;事物通过制作“主图”来描述,主图能产生“实例图”;控制和动态由“约束”提供,约束也是图形形式,可施加到主图上,塑造相互关联的部件。它的数据结构很难懂——唯一隐约熟悉的构造是嵌入指向过程的指针,并用反向索引跳转到例程,像 220 文件系统。它最早有裁剪和缩放窗口——在一张约三分之一英里见方的虚拟纸上“素描”。
![]()
头晕目眩地找到工作台,上面有一堆磁带和打印件,还有一张纸条:“这是 1108 的 Algol。它不能工作。请让它工作。”最新的研究生得到最新的脏活。
文档无法理解。据说这是 Case-Western Reserve 1107 Algol,但被改造为一种叫 Simula 的语言;文档读起来像挪威语转写成英语,事实上就是。其中“活动”和“过程”等词似乎不符合正常英语用法。
最后,另一个研究生和我在走廊里展开 80 英尺长的程序清单,爬过去互相喊发现。最怪的是存储分配器,它不遵守 Algol 通常的栈纪律。几天后,这提供了线索。Simula 分配的结构很像 Sketchpad 的实例。有像主图的描述,可以创建实例,每个实例是独立实体。Sketchpad 称为主图和实例,Simula 称为活动和过程。而且,Simula 是一种过程语言,用于控制类似 Sketchpad 的对象,因此比约束灵活得多(代价是优雅性)。
这是巨大的冲击,我自此不同。冲击如此之大,是因为我已在足够多不同形式中见过这个想法,最终认出时用的是如此一般的术语,具有顿悟性质。我的数学专业集中在抽象代数,少数运算通常适用于许多结构。我的生物学专业关注细胞代谢和更大规模形态发生,其中有简单机制控制复杂过程、一种积木能分化成所有需要的积木。220 文件系统、B5000、Sketchpad,最后 Simula,都用同一想法做不同事。Bob Barton,B5000 主设计者和犹他教授,几天前在一次演讲中说:“递归设计的基本原理是让部件拥有与整体相同的威力。”我第一次把整体想成整台计算机,并奇怪为什么有人要把它分成更弱的数据结构和过程。为什么不分成小计算机,像分时开始做的那样?但不是几十台。为什么不是几千台,每台模拟一个有用结构?
我回忆起莱布尼茨的单子、柏拉图“在关节处分割自然”的论述,以及其他解析复杂性的尝试。哲学关乎意见,工程关乎行动,科学是中间地带。可以不太夸张地说,我此后大多数想法都扎根于 Simula——但不是试图改进它,而是它承诺了一种全新的结构化计算方式。结果,花了好些年才理解如何使用这些洞见,并设计高效执行机制。
II. 1967—69:FLEX 机器,首次基于 OOP 的个人计算机尝试
Dave Evans 不太相信研究生院制度。像许多 ARPA“承包商”一样,他希望学生做“真实事物”,尽快读完,论文应推进技术前沿。Dave 常为学生找咨询工作。1967 年初,他介绍我认识 Ed Cheadle,当地航空航天公司的友好硬件天才,正在做一台“小机器”。它不是第一台个人计算机——那是 Wes Clark 的 LINC——但 Ed 想把它给非计算机专业人士,尤其想用 BASIC 这样的高级语言编程。我说:“JOSS 呢?更好。”他说:“行,随你想。”这就是我们称为 FLEX 机器的愉快合作开始。随着设计深入,我们意识到想动态模拟和扩展,而 JOSS(或我知道的任何现有语言)对此不特别擅长。机器太小,跑不了 Simula,所以排除。JOSS 的美丽在于对最终用户的极度关注——这方面它未被超越。JOSS 对严肃计算太慢,没有真正过程、变量作用域等。看起来有点像 JOSS 但潜力大得多的语言是 Wirth 的 EULER。这是 Algol 的推广,沿着 van Wijngaarden 先提出的路线:丢弃类型,合并不同特征,过程成为一等对象。其实有点像 LISP,但没有 LISP 的深层洞见。
但 EULER 足以是“几乎一种新事物”,提示同样技术可用来简化 Simula。EULER 编译器是其形式定义的一部分,容易转换成类 B5000 字节码。这很吸引人,因为 Ed 的小机器可以用当时可能的较长慢微码模拟字节码。但 EULER 编译器用“扩展优先级”文法渲染,很别扭,还要求语言语法让步。我起初采用自底向上的 Floyd-Evans 解析器,后来转向各种自顶向下方案,有些与 Shorre 的 META II 有关,最终把翻译器放入语言命名空间。
现在叫 FLEX 的语言,其语义需要更多受 Simula 而不是 Algol 或 EULER 影响。但不完全清楚怎么做。也不清楚用户应如何交互。Ed 的第一台机器就有显示器(用于绘图等),LINC 有“玻璃电传打字机”,但类 Sketchpad 系统似乎远超我们预算允许的 16K 16 位字。
![]()
Doug Engelbart 与 NLS
1967 年初,我们思考 FLEX 机器时,Doug Engelbart 访问犹他。他是圣经级先知,是我在 FLEX 机器上开始称为“个人计算”的许多父亲之一。他实际上带着自己的 16mm 放映机和遥控器来播放进展(人们那时还不习惯看和跟随光标)。他对 ARPA 梦想的看法是:在线系统 NLS 的使命是通过交互载体在“概念空间中的思想向量”中航行,来“增强人类智力”。他的系统当时能做的事——即使按今天标准——也令人难以置信。不只是超文本,还有图形、多窗格、高效导航和命令输入、交互协作等。整个概念世界和世界观。这个愿景在“渴望被增强”的人心中产生了交互计算应是什么的 compelling 隐喻,我立即为 FLEX 机器采用了许多想法。
在 ARPA 人机共生背景和 Ed 的“小机器”面前,Gordon Moore 的“定律”再次浮现,这次影响巨大。我第一次跳到把房间大小的交互 TX-2 甚至 10 MIP 6600 放到桌上。我几乎被含义吓到;我们所知的计算机无法幸存——这个词的实际意义变了——这一定像人们读哥白尼后,从不同的地球仰望不同的天空时的迷失。
世界上最多几千台机构大型机——即使 1992 年,全世界估计也只有 4000 台 IBM 大型机——每种应用最多几千名训练有素的用户,而将来会有数百万台个人机器和用户,大多不在直接机构控制下。应用和培训从哪来?为什么指望应用程序员预见数百万潜在用户中某一个的具体需求?似乎需要一种外延系统,最终用户自己做大部分裁剪(甚至直接构造)工具。ARPA 已在早期分时成功中想通这一点。他们更大的人机共生隐喻帮助共同体避免把子目标当成宗教,专注于“增强”这一抽象圣杯。
![]()
NLS 的一个有趣特征是用户界面是参数化的,可由最终用户以“交互文法”形式提供,用他们的编译器编译器 TreeMeta 编写。这类似 William Newman 早期的“反应处理器”工作,通过让最终用户或开发者用平板和笔构造图标正则表达式文法,状态上有动作过程。这有很多吸引人之处,尤其 William 的方案,但对我来说有个巨大 bug:这些文法迫使用户处于某种系统状态,必须先退出才能做新交互。在层次菜单或“屏幕”中,必须回溯到主状态才能去别处。似乎需要的是每个状态都有到所有其他状态的转移箭头——这在形式文法理论中不是富有成果的概念。换句话说,需要更“扁平”的界面——但这样的东西能做得足够有趣和丰富吗?
FLEX 机器的范围又太小,做不了 miniNLS,我们被迫找替代设计,纳入新想法的部分威力,有时改进它们。我决定 Sketchpad 的通用窗口概念——观看更大虚拟世界——比受限水平窗格更好,我和 Ed 弄出一个裁剪算法,很像 Sutherland 和学生在哈佛为 3D“虚拟现实”头盔项目同时开发的那个。
对象引用在 FLEX 机器上作为 B5000 描述符的推广来处理。不是几种引用数字、数组和过程的格式,FLEX 描述符包含两个指针:第一个指向对象“主”,第二个指向对象实例(后来我们意识到应把主指针放在实例中以节省空间)。处理广义赋值用了不同方法。B5000 用 l-value 和 r-value,对某些情况有效,但不能处理更复杂对象。例如 a[55] := 0,如果 a 是稀疏数组且默认元素为 0,仍会在数组中生成一个元素,因为 := 是“运算符”,a[55] 在任何人看到 r-value 是默认元素前就被解引用为 l-value,不管 a 是数组还是代表数组的过程。需要的是类似 a(55, ':=', 0),可以在任何存储发生前查看所有相关操作数。换句话说,:= 不是运算符,而是一种索引,能从复杂对象中选择行为。我花了好久才看到,部分因为必须反转传统的运算符和函数等观念,才能看到对象需要私有地拥有全部行为:对象是一种映射,其值是它的行为。Carnap 的逻辑书帮助了我,表明“内涵”定义覆盖与传统外延技术相同的领域,且常常更直观方便。
![]()
和 Simula 一样,协程控制结构用来挂起和恢复对象。持久对象如文件和文档被当作挂起进程,按 Algol 式静态变量作用域组织。它们显示在屏幕上,可指向打开。协程也用作循环控制结构。单个运算符 while 用来测试生成器,生成器无法提供新值时返回 false。布尔值用来连接多个生成器。所以“for 型”循环写成:
while i <= 1 to 30 by 2 ^ j <= 2 to k by 3 do j<-j * i;
其中 ... to ... by ... 是一种协程对象。许多这些想法后来在 Smalltalk 中以更强风格重新实现。
![]()
FLEX 另一个有趣的控制结构是事件驱动的“软中断”,叫 when。它的布尔表达式被编译成“锦标赛排序”树,缓存所有可能的中间结果。相关变量穿过所有 when 的所有排序树,因此任何变化只需计算布尔值的必要部分。效率很高,类似现在电子表格用的技术。这带来事件驱动系统中常见的“财富的尴尬”:很难控制 when 何时应敏感的上下文。布尔表达式的一部分必须用于检查上下文,我觉得程序结构应该能设置和取消事件驱动器。这超出 FLEX 范围,需要更好的架构。
不过,许多 FLEX 原初想法在其前对象形式中确实小到可在机器上实现。我正在写第一个编译器时,发生了不寻常的事:犹他研究生被邀请参加当年在犹他 Alta 举行的 ARPA 承包商会议。三天将结束时,接替 Ivan Sutherland 担任 ARPA-IPTO 负责人的 Bob Taylor 问研究生(围坐在约 20 名承包商外圈)有没有评论。John Warnock 举手指出,既然 ARPA 研究生很快都会成为同事(而且反正我们做所有实际工作),ARPA 应每年为研究生开一次承包商式会议。Taylor 觉得好,安排在下个夏天。
那个春天晚些时候,Park City 又有一次滑雪小屋会议。主题是教育,我第一次听 Marvin Minsky 演讲。他对传统教育方法发出精彩抨击,我第一次从他那里听到 Piaget 和 Papert 的想法。Marvin 谈我们如何思考复杂情况,以及为什么学校是学习这些技能的糟糕地方。他不必对计算机+孩子做任何声明就能说明观点。很明显,教育和学习必须根据 20 世纪认知心理学以及优秀思考者实际如何思考来重新思考。计算作为一种新表示系统进入,带有处理和复杂性的新而有用隐喻,尤其是系统。
![]()
1968 年夏天在伊利诺伊 Allerton House 的 ARPA 研究生会议上,我把 FLEX 机器的所有机制浓缩成一张 2x3 英尺的图表。包括所有“对象结构”、编译器、字节码解释器、I/O 处理程序,以及简单的文本和图形显示编辑器。研究生们是杰出群体,后来确实成为同事。我的 FLEX 机器演讲成功,但对我最大的冲击是在参观伊利诺伊大学时,看到一块 1 英寸见方的玻璃和氖气,单个点可被命令点亮——第一块平板显示器。我在会议剩余时间计算 FLEX 机器的硅何时能放到显示器背面。根据 Gordon Moore 的“定律”,答案似乎是七十年代末或八十年代初。还很久——当时似乎太久,不必太担心。
![]()
但那年晚些时候,在 RAND 我看到一个真正美丽的系统。这是 GRAIL,JOSS 的图形后继。第一块平板(著名的 RAND 平板)由 Tom Ellis 发明,用于捕捉人类手势,Gabe Groner 写了程序高效识别和响应。虽然一切用泡泡糖粘着,系统经常崩溃,我从未忘记与它的最初交互。它是直接操作,是类比式的,是无模式的,是美丽的。我意识到 FLEX 接口全错了,但 GRAIL 需要整个独立 360/44 才能跑,怎么塞进那么小的机器?
一个月后,我终于拜访 Seymour Papert、Wally Feurzig、Cynthia Solomon 和其他原始研究者,他们建造了 LOGO 并在 Lexington 学校与孩子使用。这里有孩子用专门设计的语言和环境做真正编程。就像 Simula 导向 OOP,这次相遇终于让我明白个人计算的命运真正是什么。不是恩格尔巴特隐喻中与 IBM“铁路”对立的个人动态“车辆”,而是更深刻的东西:个人动态“媒介”。车辆可以等到高中给“驾驶教育”,但如果是媒介,它必须延伸到童年世界。
现在 FLEX 机器、平板显示、GRAIL、Barton 的“通信”演讲、McLuhan 和 Papert 与孩子的工作碰撞在一起,形成个人计算机应是什么的图像。我记得 Aldus Manutius 在印刷机后 40 年把书做成现代尺寸,能放进马鞍袋。它必须不大于笔记本,需要像 JOSS、GRAIL 和 LOGO 一样友好的界面,但具有 Simula 和 FLEX 的触及范围。清晰的浪漫愿景有神奇能力聚焦思想和意志。现在容易知道下一步做什么。我做了纸板模型看外观和感觉,倒入铅粒看必须多轻(少于两磅)。我放了键盘和笔,因为即使手写印刷和书写被完美识别(没有理由期待如此),仍需在笔提供的低速触觉自由度和更有限但更快的键盘之间平衡。由于 ARPA 开始试验分组无线电,我预期 Dynabook 十年左右出现时会有无线网络系统。
1969 年初有个可扩展语言会议,几乎所有该领域著名人物都参加。辩论伟大而沉重——是一场未实现、思考不周想法的宗教战争。正如计算机科学伟人 Alan Perlis 以其特色机智所说:
我很久没见过这么多熟悉面孔在这么多熟悉想法中喊叫。在编程语言中发现新东西,像任何发现一样,情绪序列有点类似坠入爱河。尖锐兴奋,接着狂喜,独特感,最终是游移的目光(泛化冲动)。
但全是空谈——没人做了什么。此时 Ned Irons 站起来展示 IMP,一个已运行数年的系统,比大多数未运行提案更优雅。IMP 的基本想法是,你可以用文法中任何短语作为过程标题,并用已扩展的语言写语义定义。
我已把第一版 FLEX 机器做成语法驱动,但短语意义按更通常方式定义为发出的代码。这把编译器扩展部分与最终用户分开。在 Irons 方法中,系统中每个过程都以自然有用方式定义自己的语法。我把这些想法纳入第二版 FLEX 机器,并开始实验直接解释器而非语法指导编译器。在这些事中,我意识到通向基于对象系统的桥梁可以是:每个对象作为发给自己消息的语法指导解释器。这一下子把面向对象语义与完全可扩展语言的理想统一起来。心理图像是分开的计算机向其他计算机发送请求,接收者必须接受和理解,然后才可能发生事情。用今天的话说,每个对象都是服务器,提供服务,其部署和决定完全取决于服务器与客户关系的概念。如莱布尼茨说:“要从无中得到一切,只需找到一个原理。”这还没想得足够清楚,不能帮 FLEX 机器,但形成了我的论文的好出发点,正如 Ivan Sutherland 爱说的,论文是“你能让三个人签字的任何东西”。
三个人签字后(Ivan 是其中之一),我去了斯坦福 AI 项目,花更多时间想笔记本儿童计算机而不是 AI。但有两个 AI 设计很有趣。第一是 Carl Hewitt 的 PLANNER,可编程逻辑系统,构成 Winograd 的 SHRDLU 的演绎基础。我设计了几个基于 FLEX 和 PLANNER 模式匹配方案结合的语言。第二是 Pat Winston 的概念形成系统,构建语义网络并比较以形成类比和学习过程。它有点“面向对象”。它许多好想法之一是,网络中作为 AOV 三元组属性的弧本身应被建模为网络。例如,一阶弧 LEFT-OF 可被问高阶问题“你的反向是什么?”,其网络可回答 RIGHT-OF。这个观点后来成为 Minsky 框架系统的基础。几年后我希望当时更注意这个想法。
那个秋天,我听 Butler Lampson 关于 CAL-TSS 的精彩演讲,一个基于能力的操作系统,看起来很“面向对象”。不可伪造指针(B5000 式)由位掩码扩展,限制对对象内部操作的访问。这确认了我的“对象作为服务器”隐喻。异常处理也有很好的方法,让我想起模式匹配系统中处理失败的方式。唯一问题——CAL 设计者根本不认为是问题——是只有某些(通常大而慢)东西是“对象”。快东西和小东西等不是。这需要修复。
1969 年末在 SAIL 最大的收获是真正理解 LISP。当然每个学生都知道 car、cdr 和 cons,但犹他很贫乏,没人用 LISP,因此没人穿透 eval 和 apply 的奥秘。我几乎不能相信 LISP 的想法如此美丽和精彩。我这样说是因为 LISP 不仅存在够久,长出一些诚实的藤壶,更糟的是,其逻辑基础有深层缺陷。纯语言本应基于函数,但其最重要组件——如 lambda 表达式、quote 和 cond——根本不是函数,而是所谓特殊形式。Landin 等人用各种聪明有用的技巧把 quote 和 cond 归结为 lambda,但缺陷仍在宝石中。实际语言中情况更好。不只有 EXPR(求值参数),还有 FEXPR(不求值)。我下一个问题是,为什么叫函数式语言?为什么不把所有都基于 FEXPR,在需要时强制接收方求值?我从未得到好答案,但这个问题在发明 Smalltalk 时非常有用,因为它开始了一条思路:“把你需要做的最难最深刻的事拿出来,做到伟大,然后用它构建所有更容易的事。”这是 LISP 的承诺和 lambda 的诱惑——需要的是更好的“最难最深刻”的东西。对象应该是它。
III. 1970—72:Xerox PARC,KiddiKomp、miniCOM 与 Smalltalk-71
1970 年 7 月,Xerox 在首席科学家 Jack Goldman 敦促下,决定在加州帕洛阿尔托设立长期研究中心。9 月,George Pake 聘请 Bob Taylor(已离开 ARPA,在犹他休假)开始“计算机科学实验室”。Bob 访问帕洛阿尔托,我们通宵谈论。Mansfield 修正案威胁盲目封杀最开明的 ARPA 资助,转而支持直接军事研究,这个新机会看起来有希望。但为公司工作?他想让我咨询,我要求方向。他说:跟随你的直觉。我立即开始做新版本 KiddiKomp,可量产,用于最终笔记本用户界面设计实验。Bob Barton 爱说“好想法通常不能缩放”。用在 FLEX 机器上确实如此。B5000 不能直接缩成小机器。只有字节码可以,甚至也需要修改。我决定再看 Wes Clark 的 LINC,这次更欣赏它。
![]()
我仍喜欢模式导向方法和 OOP,所以设计了一种叫“Simulation LOGO”或 SLOGO 的语言(我感觉第一版会跑得又好又慢)。它要装进 SONY“肚子特丽珑”,使用粗位图显示和 FLEX 机器橡胶平板作为指点设备。
我遇到的另一个美丽系统是 Peter Deutsch 的 PDP-1 LISP(他 15 岁时实现)。只用 2K(18 位字)代码,在 4K 机器上跑得很好(它自己的操作系统和界面)。似乎如果系统字节码化,由好客于动态系统的架构运行,并塞进越来越大的 ROM,还能做更多。从 Seymour 得到的基本洞见之一是,不必做很多就能让计算机成为孩子的“思考对象”,但做的必须好,并能深度应用。
1971 年新年刚过,Bob Taylor 取得巨大成功,把挣扎中的 Berkeley Computer Corp 大部分吸引到 PARC。包括 Butler Lampson、Chuck Thacker、Peter Deutsch、Jim Mitchell、Dick Shoup、Willie Sue Haugeland、Ed Fiala。Jim Mitchell 力劝聘请 CM 的 Ed McCreight,他很快到达。Gary Starkweather 已在那里,因想造激光打印机被 Xerox Rochester 实验室赶出(违反当地宗教)。不久后,Doug Engelbart 的许多人加入——部分原因是他们想重实现 NLS 为分布式网络系统,而 Doug 想留在分时。包括鼠标共同发明人 Bill English、Jeff Rulifson、Bill Paxton。
几乎立刻我们和 Xerox 陷入麻烦,小组决定新实验室需要 PDP-10 以与 ARPA 共同体连续。Xerox(几年前基本没看就买下 SDS)对实验室使用其主要竞争对手的计算机感到恐惧。他们反对。新成立的 PARC 小组开会,决定为 XDS SIGMA-7 做好操作系统要三年,但可以一年“建自己的 PDP-10”。我反应是“天哪!”事实上他们相当漂亮地做到了。MAXC 实际上是 PDP-10 的微码模拟,首次使用新集成芯片存储器(1K 位!)而非磁芯。拥有这两种新技术的实际内部经验,对后来更激进的系统至关重要。
LISP 美丽的小事件发生在 Allen Newell 访问 PARC,带着分层思维理论,被挑战证明。他得到一个编程问题,同时收集协议。问题是:给定项目列表,产生一个列表,包含所有奇数索引项后跟所有偶数索引项。Newell 的内部编程语言类似 IPL-V,显式操作指针,他挣扎很久。我 2 秒写下:
oddsEvens(x) = append(odds(x), evens(x))
这是 Landin LISP 语法下问题的陈述——也是解的第一部分。几秒后:
where odds(x) = if null(x) ∨ null(tl(x)) then x else hd(x) & odds(ttl(x))
evens(x) = if null(x) ∨ null(tl(x)) then nil else odds(tl(x))
用声明形式写下许多解,同时它们也是程序,是这类语言吸引力和美丽的一部分。看一个比我聪明得多的人挣扎 30 多分钟还没完全解出(有 bug),印象深刻。再次让我明白“观点值 80 个 IQ 点”。我并不更聪明,但有更好的内部思维工具放大能力。这件事和其他类似事使我相信,任何给孩子的工具都应“内置”伟大思维模式和深层美。
![]()
大约此时,我们和 Xerox 管理层尤其是“规划者”头 Don Pendery 有冲突。他真不理解我们谈什么,而对“趋势”“未来会怎样”以及 Xerox 如何“防御”感兴趣。我很不安,对他说:“看,预测未来的最好方式就是发明它。别担心其他人会做什么,这是几乎任何清晰愿景都能实现的世纪!”他仍不信,这导致著名的“PARC 规划用 Pendery 文件”,一批关于未来各方面的文章。我的提议是笔记本作为“显示转换器”,Jim Mitchell 的题为“小型机上的 NLS”。
Bill English 把我置于羽翼下,帮我开始小组,因为我一直是独狼,不知怎么做。一个建议是应该做预算。我恐怕真问了 Bill:“预算是什么?”我记得在犹他,Mansfield 修正案前,Dave Evans 去 ARPA 旅行时对我说:“我们快没钱了。得再去弄点。”这对我似乎很对。他们给你钱。你花掉来发现下一步做什么。花完。他们再给。如此等等。PARC 从未达到那田园标准,但头五年接近。我需要小组,因为我终于意识到没有完全完成一个想法所需的所有气质。我称它学习研究组(LRG),尽可能模糊章程。我只雇听到笔记本计算机想法时眼里有星星的人。我不喜欢会议:不相信头脑风暴能替代冷静持续的思考。有人问做什么而我没有强烈想法时,我会指着笔记本模型说:“推进它。”LRG 成员关系非常密切——正如 Dan Ingalls 后来说:“……其余的都通过整个学习研究组的爱和能量展开。”许多白天在 PARC 外度过,打网球、骑自行车、喝啤酒、吃中餐,不断谈论 Dynabook 及其放大人类触及范围的潜力,给急需的摇摇欲坠文明带来新思维方式。
1971 年夏天,我把 KiddiKomp 想法精炼成更紧凑的设计,叫 miniCOM。它用类似 NOVA 1200 的位片方法,有位图显示、指点设备、可选“二级”(其实是三级)存储,以及我现在叫“Smalltalk”的语言——意为“编程应该……”和“孩子应该用……编程”。名字也是对“印欧神理论”的反应,那种系统叫 Zeus、Odin、Thor,却几乎做不了什么。我认为“Smalltalk”这个标签如此无害,如果它做了什么好事,人们会惊喜。
![]()
这种 Smalltalk 语言(今天标为 -71)深受 FLEX、PLANNER、LOGO、META II 和我自己的衍生影响。它是一种带对象附着的解析器,直接执行记号。我对作为代数模式的程序不如对能处理多种编程风格的清晰方案感兴趣。模式化前端允许简单扩展,模式作为“数据”可检索,简单把行为附着到对象,以及用我认为孩子在几年简单编程经验后能理解的术语初步清晰表达 eval。程序存储被排序到区分网中,求值直接模式匹配。
如前所述,LISP 表面美被一些关键部分必须作为“特殊形式”而不是其据称的通用积木函数引入所损害。LISP 的实际美更多来自其元结构的承诺,而不是实际模型。我花不少时间思考如何把对象表征为通用计算机,而中心隐喻没有任何例外。似乎需要完全控制消息发送中传递什么;尤其表达式何时、在什么环境中求值。
Dave Fisher 在 CMU 的论文提出优雅方法,关于控制结构合成。ALGOL60 需要单独链接用于动态子程序链接和访问静态全局状态。Fisher 显示这些链接的推广可模拟多种控制环境。解决 LISP“funarg 问题”的一种方式是把正确的全局状态链接关联系到以后要求值的表达式和函数,使引用的自由变量是语言静态形式实际暗示的那些。这也预示了“惰性求值”。今天这叫反射式设计。与 FLEX 模型结合,提示“正确做 LISP”或“正确做 OOP”所需要的只是处理模块间调用机制,而不必担心模块细节。LISP 和 OOP(或任何其他系统)的区别将是模块能包含什么。通用模块(对象)引用和消息持有结构,如果发送者和接收者相容,可以是虚拟的,能服务所有人。
如果按此观点枚举信使结构的字段,会有:GLOBAL 参数值环境、SENDER 消息发送者、RECEIVER 接收者、REPLY-STYLE 等待/分叉、STATUS 消息进度、REPLY 最终结果、OPERATION SELECTOR 相对于接收者、参数数目、P1...Pn。这是栈帧的推广,类似 B5000 所用,非常像操作系统如 CAL-TSS 中良好模块间方案所需——每个事务大量状态,但值得思考。
在这段优雅状态中(还没有可工作的实现),许多思考关于“美丽”在面向对象设计中可能意味着什么。美丽事物的主观定义容易但帮助不大:我们认为事物美丽因为它唤起某些情绪。陈词滥调说它“在观者眼中”,所以美不过是主体和客体之间的关系,主体的 predispositions 最重要。如果有普遍吸引人的形式,或许可以从共享生物 heritage 找 predispositions。但对于 LISP 这样的对象,几乎可以肯定我们判断的基础大部分是学来的,与我们认为美丽的其他相关领域如数学有关。
数学感知美的一部分与简约、普遍、启发和技巧之间奇妙的协同有关。例如勾股定理可用一行表达,对无限多个直角三角形都成立,理解许多其他关系时极其有用,且可用几个简单深刻步骤证明。转向各种指定计算的语语言,许多是普遍的,少数是简约的。例如通用机器语言可用几条指令定义,能指定任何可计算的东西。但大多数我们不会称为美丽,部分因为做任何有趣事情要写的代码量和种类如此造作和浮夸。一个简单小系统能做有趣事也需要“高斜率”——即有趣程度与表达所需复杂度之间的良好匹配。受精卵能把自己转化成复杂有机体所需的无数特化,具有简约、普遍、启发和技巧——简言之美丽,一种更符合我自己美学的美丽。我的意思是自然在优雅和实用上都很精彩——细胞膜部分是为了允许有用的进化 kludge 做必要工作,同时通过向世界呈现统一界面仍能作为组件。
当时我持续担心之一有位图显示的大小。即使使用混合模式(细粒度生成字符和粗粒度通用位图图形之间),也很难在屏幕上放足够信息。我在淋浴时(我最喜欢的思考处)想到,位图显示上的 FLEXtype 窗口可以做成桌面上重叠文档的样子。当一个被重叠的窗口刷新时,它会出现在栈顶。当时这没显现为问题的绝妙解决方案,但它极大地放大了显示的有效面积,所以我决定采用。
为了研究视频作为显示媒介,Bill English 和 Butler Lampson 为 POLOS(PARC 在线办公系统)终端指定了一个实验性字符发生器(由 Roger Bates 建造)。Gary Starkweather 刚让第一台激光打印机工作,我们把同轴电缆拉到他的实验室喂文本打印。“SLOT 机器”(扫描激光输出终端)令人难以置信。Gary 能弄工作的唯一 Xerox 复印机每秒一页,不能减速。所以 Gary 就让激光以该速率运行,分辨率每英寸 500 像素!
字符发生器的字体内存大到可模拟位图显示,如果显示固定“strike”并写入字体内存。Ben Laws 建造了美丽字体编辑器,他和我花几个月学习人类视觉系统的特殊性(它绝对非线性)。我对高质量文本和图形呈现很感兴趣,因为我认为通过简单替换学校课本,把 Dynabook 作为“特洛伊木马”带进学校,比向教师和学校董事会解释个人计算的真正伟大之处更容易。
![]()
整个实验室大体进展顺利,直到 1972 年 5 月我想获取资源造几台 miniCOM。一位相对新的高管(“X”)不想给。我写了备忘录解释系统为何好,然后开会讨论。“X”完全否定,说我们用了太多绿色 stamps 让 Xerox 资助分时 MAXC,用资源做个人机器会让他们困惑。我震惊。我爬回实验字符发生器,制定计划再造 4 台,连到 NOVA 做初始儿童实验。
我让斯坦福暑期学生 Steve Purcell 按我的设计做位图绘画,让孩子能素描并显示计算机图形。John Shoch 做了基于 Ledeen 的线条绘制和手势识别系统,与绘画集成。POLOS 的 Bill Duvall 做了 miniNLS,速度和威力相当惊人。第一批重叠窗口开始出现。Bob Shur(在 Steve Purcell 帮助下)做了 2.5D 动画系统。加上 Ben Laws 的字体编辑器,我们能对接下来几年真正要建的东西做相当轰动的演示。我记得给一位 Xerox 高管演示,包括在新绘画系统中画他的肖像,最后得意地说:“真正棒的是它只有 20% 成功机会。我们在冒险,就像你要求的那样!”他直视我说:“孩子,那很好,但确保它能工作。”这是典型高管对风险的观念。他想让我们百分之百处在“20%”里。
![]()
那年夏天,我舔伤口、让演示模拟建成运行,同时 Butler Lampson、Peter Deutsch 和我制定通用方案,用于模拟 HLL 机器语言。我喜欢 B5000 方案,但 Butler 不想解码字节,指出既然 8 位字节有 256 种可能,我们应把不同含义映射到“指令空间”不同部分。这给我们一个“穷人的 Huffman 码”,既灵活又简单。之后 PARC 所有模拟器都用这个通用方案。
我又对孩子的语言做了一次尝试。Jeff Rulifson 是 Piaget(和符号学)的粉丝,我们多次讨论“阶段”和图标思维可能是什么。读了 Piaget 尤其 Jerome Bruner 后,我担心 FLEX、LOGO(和当前 Smalltalk)采用的直接符号方法对孩子困难,因为有证据表明符号阶段(或心智)刚开始启动。事实上,我敬佩的所有教育家(包括 Montessori、Holt、Suzuki)似乎都呼吁更形象、更图像的方法。Rudolph Arnheim 写过关于视觉思维的经典书,著名艺术评论家 Gombrich 也是。这里确实需要做更好的东西。GRAIL 不是,因为它用图像来描绘和编辑流程图,似乎大大倒退。但 Rovner 的 AMBIT-G 更有希望。它有点像视觉 SNOBOL,模式匹配想法似乎适用于我使用的更 PLANNER 式方案。
Bill English 仍鼓励我做更多看起来合理的事以获得更高可信度,比如做预算、写计划、里程碑笔记,所以我写了一个计划,提议接下来几年在字符发生器加 NOVA 上建真实系统,涉及 OOP、窗口、绘画、音乐、动画和“图标编程”。后者被认为很难,将按处理难题的通常方法交给研究生。
![]()
IV. 1972—76:第一个真正的 Smalltalk(-72),诞生、应用与改进
9 月,几周内发生了两个赌注,改变了我大部分计划。首先,Butler 和 Chuck 过来说:“你有钱吗?”我说:“有,大约 23 万美元用于 NOVA 和字符发生器。怎么?”他们说:“你想让我们为你建小机器吗?”我说:“很好。是什么?”Butler 说:“我想要一台‘500 美元 PDP-10’,Chuck 想要‘快 10 倍的 NOVA’,你想要‘儿童计算机’。你需要什么?”我告诉他们我们从字体、绘画、分辨率、动画和音乐研究中得到的大部分结果。我问这突然从哪来,Butler 告诉我他们无论如何想做,高管“X”离开几个月去“工作组”,也许能“偷偷塞进去”,Chuck 和 Bill Vitic 打赌他能在 3 个月内做完整台机器。“哦,”我说。
第二个赌注结果更惊人。我原以为新 Smalltalk 会是一种图标语言,至少两年才能发明,但命运介入。一天,在典型 PARC 走廊闲谈中,Ted Kaehler、Dan Ingalls 和我站在一起谈编程语言。话题转到威力,他们俩想知道要造多大语言才能获得巨大威力。我尽可能气势十足地宣称,你可以在“一页代码”里定义“世界上最强大的语言”。他们说:“拿出来,不然闭嘴。”
Ted 回 CMU,但 Dan 还在,怂恿我。接下来两周我每天凌晨四点去 PARC,工作到八点,然后 Dan 和 Henry Fuchs、John Shoch、Steve Purcell 来看早晨的工作。
我最初夸口是因为 McCarthy 的自描述 LISP 解释器用自身写成。它大约“一页”,就威力而言,LISP 是函数式语言的整个九码。我相当确信我能为面向对象语言做到同样,而且能像 FLEX 机器技术那样为代码做出合理语法。
结果比我想的难,原因有三。第一,我想让程序更像 McCarthy 的第二个非递归解释器——那个实现为循环、尽量像 Steve Russell 原版 709 实现的。它更“真实”。第二,“解析”与消息接收交织——参数的求值在 LISP 中分开处理——要求我的面向对象解释器比 LISP 更早(其实早得多)重新进入自身。最后,我仍不清楚 send 和 receive 应如何配合。
前几版有缺陷,被小组严厉批评。但到早上 8 点左右,出现一个似乎能用的版本。与稍后正式 Smalltalk-72 的主要区别是,第一版符号是字节码,从发送接收返回值的对称——即接收可像参数绑定——这对返回多个值特别有用。因各种原因,这被放弃,改用更面向表达式的函数式返回风格。
当然,我费了不少劲避免为赌注做任何“真实工作”,但我觉得证明了我的观点。这是从官方“图标编程”追求中一次有趣的假期,我以为到此为止。令我惊讶的是,几天后 Dan Ingalls 给我看方案在 NOVA 上工作。他用 BASIC 编码,加了许多细节,如记号扫描器、列表制造器等,它就在那运行。正如他爱说:“你只管做,就做完了。”
它求值 3+4 非常慢(Butler 说“冰川般”),但答案总是 7。好吧,只能继续。Dan 喜欢在“总能运行”的系统上自举,接下来十年他做了至少 80 个各种 Smalltalk 的主要版本。
11 月,我向 MIT AI 实验室展示这些想法和解释方案演示。这最终导致 Carl Hewitt 更正式的“Actor”方法。第一篇 Actor 论文与 Smalltalk 最接近。后来路径分岔,部分因为我们更感兴趣做东西而非理论化,部分因为我们有别人没有的东西:Chuck Thacker 的临时 Dynabook(后来叫“ALTO”)。
Chuck 开始做机器前,我给全国英语教师委员会一篇论文,关于 Dynabook 及其作为学习和思维放大器的潜力——论文是一篇扩大的凹版印刷“用 Dynabook 做的 20 件事”。我从明尼苏达回来时,Stewart Brand 在《滚石》上关于 PARC 和周边黑客社区的文章已出版。令我们极其惊讶的是,它在康涅狄格州斯坦福的 Xerox 总部引起轩然大波。虽然文章精彩,真正捕捉了整个文化精神,Xerox 却发疯,强迫我们戴徽章(多年来许多印在 T 恤上),并严重限制出版物种类。这对 LRG 尤其灾难,因为我们是“疯狂边缘”(其他计算机科学家这么叫),计划去学校,需要与 Seymour Papert 和 Don Norman 等同事分享想法和程序。
高管“X”显然在斯坦福听到关于我们的严厉话语,因为他在圣诞节前后回来,发现临时 Dynabook,更加愤怒,试图扼杀它。Butler 写了一篇大师级辩护挡住他,他又回去“工作组”。
![]()
Chuck 在 1972 年 11 月 22 日开始“赌注”。他和两名技术员做了除磁盘接口外的整台机器,磁盘接口由 Ed McCreight 做。它有约 50 万像素(606x808)位图显示,微码指令速率约 6 MIPS,总共 128K,整台机器(不含内存)用 160 个 MSI 芯片分布在两张卡上。它很美丽。机器的一个奇妙特征是“零开销”任务切换。它有 16 个程序计数器,每个任务一个。条件标志与有趣事件相连(如“水平回扫脉冲”“磁盘扇区脉冲”等)。旁视逻辑在当前指令执行时扫描标志,挑选最高优先级程序计数器下一个取指。机器从不必等待,结果大多数硬件功能(尤其涉及 I/O 如喂显示和处理磁盘)可用微码替代。甚至 MOS 动态 RAM 刷新也由一个任务做。换句话说,这是协程架构。Chuck 声称他从我几个月前关于协程的演讲得到想法,但我记得 Wes Clark 的 TX-2(Sketchpad 机器)先用过,我可能在演讲中提到。
四月初,开始后仅三个多月,第一台临时 Dynabook,名为“Bilbo”,问候世界,几分钟内我们就有第一张位图图片在屏幕上:我在绘画系统上画的 Muppets 的 Cookie Monster。
很快 Dan 把 Smalltalk 自举过去,许多个月它是临时 Dynabook 上唯一的软件系统。附录 I 有我当时的“致谢”文档,有趣地分配功劳和相关优先级。我的 23 万美元够买原计划 30 台中的 15 台(多年间实际造了约 2000 台临时 Dynabook)。忠于叔本华观察,高管“X”现在觉得临时 Dynabook 是好主意,想要除两台外全部给他实验室(我在另一个实验室)。我费很大劲拿回我们的机器,终于成功。
到这时,Smalltalk 的方案已整理成六个主要想法,符合设计解释器的最初前提:
- 一切皆对象。
- 对象通过发送和接收消息通信(用对象表示)。
- 对象有自己的记忆(用对象表示)。
- 每个对象都是类的实例(类也必须是对象)。
- 类保存其实例的共享行为(以程序列表中的对象形式)。
- 要求值程序列表,控制传给第一个对象,其余作为其消息。
前三个原则是对象“关于什么”——从外部看和用。多年来不需修改。后三个——对象内部——每个 Smalltalk 版本(以及后续 OOP 设计)都修补。在这个方案中,(1 和 4)意味着类是对象,且必须是自身的实例。(6)意味着类似 LISP 的通用语法,但接收对象是第一项,后跟消息。例如 c i <- d*e(下标写作“○”,乘法为“*”)意味着:
接收者 | 消息
c | ○ i <- d*e
c 绑定到接收对象,整个 ○ i <- d*e 是给它的消息。消息由字面记号“○”、在发送者上下文中求值的表达式(此处 i)、另一个字面记号 <-、后跟发送者上下文中求值的表达式(d*e)组成。由于“LISP”对由二元素对象构成,它们可更简单索引:c hd、c tl、c hd <- foo 等。
像 a+b 和 3+4 这样的“简单”表达式起初似乎更麻烦。把它们想成:
接收者 | 消息
a | + b
3 | + 4
如果只考虑整数,似乎愚蠢,但“+”有许多其他隐喻读法,如字符串拼接、数组加法等。这导致为消息符号寻找通用行为的风格。“多态”是官方术语(我相信来自 Strachey),但并不很贴切,因为原意只适用于能接受多种参数类型的函数。Smalltalk-72 中一类对象,如 CONS 对的模型,会看起来像下面的模型:
![]()
![]()
因为控制先传给类,然后才考虑消息其余部分——类可自行决定不接受——所以保留完全保护。Smalltalk-72 对象是“闪亮的”,不受攻击。环境的一部分是“信使对象”(广义活动记录)中 SENDER 的绑定,允许接收者确定差别特权。这预见了 Smalltalk 最终作为网络 OS 的使用,我不记得在 Smalltalk-72 中常用。
从 Smalltalk-71 保留的风格之一是函数和类观念的混合。换句话说,Smalltalk-72 类看起来像函数,也可用作函数,但容易通过对象 ISNEW 产生实例(一种闭包)。因此 factorial 可“外延”写成 to fact n (^if :n=0 then 1 else n*fact n-1),或“内涵”写成 integer 类的一部分。当然,Smalltalk(和一般 OOP)的整个想法是内涵地定义一切。随着我们学会用新风格编程,方向也如此。我从不喜这个语法(太多括号和嵌套),想要更扁平、更像文法的,如 Smalltalk-71。几年后我们在 Dan 的 Smalltalk-76 设计中看到更像这样的东西。我想 LISP 也发生类似事——你能实际编程的直截实用语法的“现实”战胜了从未建成的幻想。
Smalltalk-72 系统与应用的发展
真实机器上的真实 Smalltalk 出现,开始了爆炸般的平行路径,很难严格按历史顺序交织。先讲 Smalltalk-72 系统到向 Smalltalk-76 过渡的一般发展,再讲以孩子为主的多年工作,那是项目的主要动机。临时 Dynabook 上的 Smalltalk-72 解释器并不快(Butler 说“庄严”),但容易改,对许多实时交互系统足够快。
![]()
重叠窗口是第一个项目(与 Diana Merry)。Diana 为可变间距字体显示和一般屏幕书写做了早期位字段块传输(bitblt)。第一版窗口是真正 2.5D 可拖动对象,但太慢不实用。我们决定等 Steve Purcell 的动画系统做对,选择今天仍在用的风格,更像“2.25D”。窗口也许是 Smalltalk 中重新设计和实现最多的类,因为我们没有足够算力做持续查看“世界坐标”和刷新,那是我在犹他前同事在 Evans & Sutherland 飞行模拟项目开始实验的。这是简单强大模型,但即使 2.5D 也难实时。Smalltalk 第一批实用窗口用 GRAIL 的敏感角落约定来移动、缩放、克隆和关闭。窗口调度用简单“无循环”控制方案,把所有窗口串起来。
接下来实现的类之一(在数字、字符串等基础后)是 Ted 做的面向对象版 LOGO 海龟。可制造许多海龟实例,既用于绘图,也作为图形变换的值。Dan 创建了“指挥官”海龟类,能控制一群海龟。很快海龟能被窗口裁剪。
John Shoch 做了鼠标驱动的 Smalltalk 代码结构化编辑器。
![]()
Larry Tesler(当时为 POLOS 工作)不喜欢 NLS 的模式化和一般方法,想给前 NLS 人展示替代方案,并进行一些用户研究(当时几乎 unheard of)关于编辑。这导致他用 Smalltalk 编写 miniMOUSE,PARC 第一个真正 WYSIWYG 排版编辑器。它几乎无模式,不仅对我们而且对他测试的许多人都有趣。miniMOUSE 很快成为 Smalltalk 代码的替代编辑器,我们最好的演示有些用了它。
1974 年春,我在成人班上试的一个“小程序”项目是一页段落编辑器。结果太复杂,但我给他们展示的例子完全无模式(在空中),成为接下来几年 Smalltalk 文本工作的基础。大部分改进由 Dan 和 Diana Merry 做。当然,对象意味着多媒体文档,几乎免费得到。早期我们意识到,这种文档中每个组件对象应处理自己的编辑杂务。Steve Weyer 建了最早的多媒体文档,后来被 Bob Flegal、Diana Merry、Larry Tesler、Tim Mott 和 Trygve Reenskaug 大大扩展。
Steve Weyer 和我设计了 Findit,“按例检索”界面,用类到实例的类比形成检索请求。PARC 图书馆多年用它控制流通。
我在 NOVA 上开发的采样合成音乐能生成 3 个高质量实时声部。Bob Shur 和 Chuck Thacker 把方案转到临时 Dynabook,实现 12 个实时声部。我们为低速设备指定的 256 位广义输入(用于鼠标和键盘)使再连 154 个输入很容易,接上两个风琴键盘和一个踏板。编程了 portamento 和衰减等效果。Ted Kaehler 写了 TWANG,音乐捕获和编辑系统,用我们设计的 tablature 记谱法让孩子易懂。采样的难点之一是“Well Tempered Synthesizer”上流行的压控振荡器效果。一个夏天后,另一位聪明暑期学生 Steve Saunders 被挑战在 ID 上实时实现 John Chowning 非常非实时的 FM 合成。他必须完全换一种方式思考,成功做出 8 个实时声部并集成到 TWANG。
![]()
Chris Jeffers(音乐家兼教育家,不是计算机科学家)用 OPUS 让我们震惊,第一个实时乐谱捕获系统。与今天大多数系统不同,它不要求节拍器式演奏,而是先扫一遍找强拍和弱拍(乐句),建立可能的速度波动的局部模型,然后用曲线拟合和外推判断音符落在小节哪里、时值多少。
NOVA 上的动画跑 3—5 个对象,约 2—3 帧每秒。用双缓冲足够产生 phi 现象,但我们想要迪士尼级的每秒 10—15 帧,10 个以上大对象和更多小对象。任务交给巧妙的 Steve Purcell。到 1973 年秋,他能演示 80 个乒乓球和 10 匹飞马以每秒 10 帧在 2.5D 中跑。下一任务是把演示变成通用系统设施,从中构建动画系统。他的 CHAOS 系统 1974 年 5 月工作,正好赶上暑期访客 Ron Baecker、Tom Horseeley 和专业动画师 Eric Martin 来建 SHAZAM,一个极其强大又简单的动画系统,基于 Ron 六十年代末在 TX-2 上的 GENESYS 论文项目。
这段时间主要论文项目是 Dave Smith 的 PYGMALION,一篇关于图标编程的论文(不,我们没完全忘记)。通过向系统展示应如何修改来编程,很像在黑板前向另一个程序员演示。这个程序成为后来许多“按例编程”系统的起点。
应该说这些程序的大小。PYGMALION 是 Smalltalk-72 写过的最大程序,约 20 页代码——临时 Dynabook ALTO 能放下的全部——全文在 Smith 论文中。其他应用都更小。例如 SHAZAM 动画系统在 1974 年夏天写和修改多次,最后是 5—6 页应用,包括图标控制的多窗口用户界面。
由于源于模拟语言,用几页写 Simpula 很容易,一个 SIMULA 排序集调度方法的简单版本。到这时我们决定协程可通过把单个方法调度为单独模拟阶段来更干净地呈现。SIMULA 的通用例子是 job shop。这可推广成许多有用形式,如医院有资源部门服务病人。孩子不喜欢医院,但看到可模拟游乐园如迪士尼乐园、学校、他们和父母购物的商店等。后来这个模型成为 Smalltalk Sim-kit 的基础,一个高级最终用户编程环境。
许多漂亮的“计算机科学式”构造在 Smalltalk-72 中容易做。例如当时争议之一是要不要 goto(我们不要),如果不要,某些非常有用的控制结构——如循环多出口——怎么指定?SLAC 的 Chuck Zahn 提出事件驱动 case 结构,可定义一组事件,遇到事件时退出循环,事件选择 case 块中的语句。假设要写简单循环从键盘读字符输出到显示。正常在按回车时退出,按删除时错误退出。John Shoch 定义了这种控制结构。
Smalltalk-72 的演化
Smalltalk-74(有时称 FastTalk)是 Smalltalk-72 版本,纳入重大改进:提供真正“信使”对象,类的消息字典(向真正类对象迈进一步),Diana Merry 的 bitblt(现在著名的位图图形 2D 图形算子)由 Dan 重新设计并用微码实现,以及更好更通用的窗口界面。Dave Robson 在 UC Irvine 读学生时听说项目,对实现 OOPL 做了相当好的尝试。我们邀他暑期来,再没让他回去——他在制定 Smalltalk 官方语义上帮助很大。
最加冕的添加是 OOZE(面向对象分区环境)虚拟内存系统,服务 Smalltalk-74,更重要的是 Smalltalk-76。ALTO 不大(128—256K),尤其有页大小的显示(64K),即使小程序也很快用完存储。2.4 MB 的 model 30 磁盘驱动器比软盘快且大,比今天的硬盘慢且小。它很像 FLEX 机器上惠普直接接触磁盘,我在上面试过 B5000 段交换器的细粒度版本。它没像我希望的那样工作,尽管在清除时选择对象有一些好想法。当大伙想采用这个基本方案时,我说:“但我从没让它好好工作。”我记得 Ted Kaehler 说:“别担心,我们会让它工作!”
所有这些系统的基本想法是能收集尽可能全面的工作集对象。最容易的是交换单个对象。问题变成清除非工作集对象以腾出空间的开销。两个想法帮助很大。第一,Butler 在 GENIE OS 的洞见:花小部分时间清除脏对象,使核心尽可能干净是值得的。这样崩溃伤害较小,且总有干净存储可把页面或对象从磁盘取入。另一个来自 FLEX 系统,我建立随机决策机制(基于对象类),在清除时决定是否扔掉对象。这有两个好处:重要对象不易出去,错误只会把它再带回,分布确保该对象很快再被清除的概率低。
另一个问题是指针完整性(我在 FLEX 机器没找到足够好方案)。真正需要的是完整事务,一种全新保证无论系统何时崩溃都能恢复的技术。这被称为“宇宙射线保护”,因为早期 ALTO 会一天无故崩溃一两次。这并不特别困扰任何人,因为容易做撤销和重放机制绕过宇宙射线。对于自动存储管理的指针系统,这有点更棘手。
Ted 和 Dan 决定用常驻对象表控制存储,机器地址只在那里找到。其他有用信息也放在那里帮助 LRU 老化。清除在后台做:选一个类,把磁盘定位到其实例(同类的都存一起),然后跑 ROT 找存储中的脏对象并流出去。这相当高效,忠于 Butler 的洞见,提供足够大的干净存储池可覆盖。但设计关键(和事务机制实现)是他们想出的检查点方案,保证可恢复镜像不超过几秒旧,不管何时崩溃。OOZE 在 80KB 工作存储中交换对象,可处理约 65K 对象(最多几 MB,足够整个系统、界面和应用)。
“面向对象”风格
这里适合评论我们想的 OOP 风格与学术界刚开始研究的表面封装“抽象数据类型”之间的区别。我们早期“LISP 对”定义是抽象数据类型例子,因为它保留“字段访问”和“字段重绑定”,那是数据结构的标志。六十年代相当多工作关于推广这类结构。官方计算机科学界开始把 Simula 视为定义抽象数据类型的可能载体(甚至其一位发明者也如此),它后来成为 ADA 的大部分骨干。这导致数百篇论文中无处不在的栈数据类型例子。温和地说,我们相当惊讶,因为对我们而言,Simula 低语的是更强的东西,不只是重新实现一个弱而临时想法。我从 Simula 得到的是,你现在可以用目标取代绑定和赋值。你最不想要程序员做的是摆弄内部状态,即使以形象方式呈现。相反,对象应呈现为更高层行为的场所,更适合作为动态组件使用。
甚至我们教孩子的方式也反映这种看待对象的方式。不奇怪,这种方法对编程容易度、所需代码大小、设计完整性等有相当影响。不幸的是,今天许多所谓“面向对象编程”只是旧式编程加上更花哨构造。许多程序装满“赋值式”操作,现在由更昂贵的附着过程完成。
面向对象设计的特殊效率从哪来?好问题,因为它可看作把过程应用于数据结构的稍微不同方式。部分效果来自更清晰地表示复杂系统。这里约束和一般性一样有用。四种技术一起用——持久状态、多态、实例化、方法作为对象的目标——解释大部分威力。这些都不要求“面向对象语言”才能用——ALGOL 68 几乎可转向这种风格——OOPL 只是把设计者心思聚焦到富有成果的方向。然而,正确做封装不仅是抽象状态,还要从编程中消除状态导向隐喻。
也许最重要的原则——再次来自操作系统架构——是当你给某人一个结构,很少想让他们拥有无限特权。仅做类型匹配远不够。也没有用让一些对象受保护另一些不受。让它们都成为一等公民并保护全部。
我相信好的 OOP 系统小得多,不仅因为被温和地迫使想更周全设计,也因 OOP 的“每行代码的爆炸力”。对象携带大量意义和意图,其方法暗示它能执行的最强目标种类,其超类可增加比大多数过程作用于数据结构多得多的代码功能调用。赋值语句——即使抽象——表达非常低层目标,需要更多才能完成事情。一般我们不想要程序员摆弄状态,不管是否模拟。实例化对象的能力对代码大小也有相当影响。另一种思考方式:虽然自动存储分配的晚绑定没做程序员做不到的事,但它的存在导致更简单更强大的代码。OOP 是对许多东西的晚绑定策略,它们一起比旧方法论更久地推迟脆弱和规模爆炸。换句话说,人类程序员不是图灵机——编程系统要求越少图灵机技术越好。
Smalltalk 与孩子
现在总结完 1976 年前 Smalltalk 中“成人”活动(我们其实只是半成人),回到 1973 年夏天,我们准备开始儿童实验。我们没人懂与孩子工作,但知道当时在斯坦福 Pat Suppes 处的 Adele Goldberg 和 Steve Weyer 做过不少,我们吸引他们加入。
由于不知如何教孩子(或任何人)面向对象编程,Adele 最初实验模仿 LOGO 海龟图形,得到看似非常相似的结果。也就是说,孩子能让海龟在屏幕上画图,但表面效果之外似乎很少。我当时觉得,既然个人计算的内容是交互工具,这种新作者读写能力的内容应是孩子创造交互工具。过程式海龟图形不是。
然后 Adele 想出一个教 Smalltalk 作为面向对象语言的绝妙方法:“Joe 书”。我相信部分受 Minsky 想法影响:应通过严肃程序的工作例子整体教编程语言。
创建几个 box 类实例并发送消息,最后是简单多进程动画。让孩子猜 box 可能什么样——他们能猜得惊人接近——然后给他们看 box 类如何用 draw、undraw、turn、grow 等方法响应消息。这个想法奇妙之处是能从谦卑的 box 衍生出无数儿童项目。有些最早的是工具!这时我们真正兴奋。例如 12 岁的 Marian Goldeen 的绘画系统是完整工具。几年后,12 岁的 Susan Hamet 的 OOP 插画系统也是(设计像后来的 MacDraw)。还有 15 岁的 Bruce Horn 的音乐乐谱捕获系统和 15 岁的 Steve Putz 的电路设计系统。回头看,这可以叫计算机科学中另一个“早期成功综合征”例子。成功是真实的,但不像我们想的那么普遍,不会像希望的那样强地延伸到未来。孩子选自帕洛阿尔托学校(远非平均背景),我们更兴奋于成功而非困难。部分我们看到的是“黑客现象”:对任何追求,特定 5% 的人会自然跳进去,而约 80% 最终能学会的人发现它根本不自然。
我们隐约感觉到,但继续取得相对成功。我们肯定能看到学习系统机制不是大问题。孩子能自己通过 Adele 的 JOE 书在 ALTO 上蜂拥学会大部分。问题似乎更多是设计。
![]()
1974 年春,我教 20 个 PARC 非程序员成人 Smalltalk 后,问题开始显现。他们能比孩子更快通过初始材料,但就在看似压倒性成功时,他们开始在我觉得不比刚做好的问题难多少的地方崩溃。其中之一是成人想的小数据库系统,像卡片文件或 rolodex。他们连边都摸不到。我很惊讶,因为我“知道”这种项目远低于我们为最终用户工作的神话“两页”。那晚我写出来,第二天给他们看怎么做。但他们仍没人能自己做。后来我坐在房间思考演讲黑板。最后我数了这个小程序中不明显的想法,有 17 个。有些像建筑设计中的拱概念:如果不知道,很难发现。
与读写能力的联系痛苦地清晰。仅学会读和写不够。还有使想法呈现的文学。语言用于读写它们,但到某个点,想法的组织开始主导单纯语言能力。有强大想法在身有助于更好获得更多强大想法。所以我们决定应教设计。Adele 又想出绝妙一招。她决定需要一种中介,介于对问题的模糊想法和实际编写调试使其在 Smalltalk 运行之间。她称中介形式为设计模板。
用这些,孩子可看想模拟的情境,分解成类和消息,不必担心方法如何工作。方法规划可用英语非正式做,这些笔记后来作为注释和写实际代码的指南。这是极好的想法,效果很好。
但不够让我们满意。正如 Adele 指出,如果只有部分孩子成功——且需要孩子和教师最大努力才成功——很难声称成功。真正教学法必须在更不理想环境工作,更稳健。不过,某些成功与没有成功有质的不同。我们想要更多,开始推动继承想法,让新手在专家设计的框架上构建。我们有理由相信可行,因为 Lisa van Stone 能对 SHAZAM(相对专家成人做的 5—6 页 Smalltalk 动画工具)做重大修改。不幸的是,继承——尽管极其强大——对新手(甚至专业人员)非常难处理。
![]()
![]()
从今天回看,我相当确信设计模板方法终究是好的。只是没纵向应用够。意思是现在有大量教新手编程的结果积累。它们都有相似故事,似乎与所用编程语言特征关系不大,而与新手以优秀程序员方式思考的特殊困难关系很大。即使有比当时(和今天)好得多的界面,这很可能实际上更像写作。即对“80%”而言,确实需要多年逐步学习,以建立设计和解题预判所需结构。
问题不是让孩子做事——他们爱做,即使不确定在做什么。这与早期语言学习研究吻合,大量排练不管是否涉及内容。仅仅做似乎有帮助。难的是确定在该孩子发展水平上提出什么想法、应渗透多深。这种困惑在自然语言读写和数学中仍存在,尽管有数百年经验。这是教孩子编程的主要障碍。何时、以何顺序和深度、如何教强大想法?
我们甚至该试着教编程吗?过去 30 年我见过数百名程序员,看不出编程对其一般思考能力或对人类知识开明立场有可辨影响。如果有,相反更真。专家知识常扎根于最初学习环境——大多数隐喻延伸导致误导类比。相当多艺术家、科学家、哲学家在专业外相当迟钝(人们怀疑专业内也是)。我们需要警惕的第一首海妖之歌是承诺有趣追求与有趣思想之间的联系。音乐不在钢琴里,可能从茱莉亚学院毕业却没找到或感受到它。
我也见过少数人,计算为思考人类知识和触及范围提供重要新隐喻。但除计算外还需要别的东西,启蒙才发生。
工具提供路径、语境,几乎是发展启蒙的借口,但没有工具包含或能 dispensing 它。Cesare Pavese 说:要认识世界必须构造它。换句话说,我们不仅为拥有而制造,也为认识而制造。但拥有可在大部分认识未发生时发生。
另一种看法:知识在刚开始学习时处于最无趣状态。表示——无论是标记、典故还是物理控制——挡路(几乎接管为目标),必须费力痛苦地解释。从这里有几条有用路径,两条重要且交织。
第一是流利,部分是通过建立心理结构使表示的解释消失的过程。句子的字母和词被体验为意义而非标记,网球拍或键盘成为身体的延伸。若更进一步,最终成为某种专家——但若没有其他领域深层知识,泛化尝试通常太生硬、不完整。
第二条路径是把知识当作隐喻,照亮其他领域。但没有流利,先验知识更可能占上风,来自这边的隐喻会模糊误导。
“诀窍”,我认为这是博雅教育应做的,是在流利和深度同时与其他流利深层知识建立关系。我们的社会把目标降得太低,满足于“分数提高”,不敢问是否跨过重要门槛。能读药瓶警告或写暑假作文不是读写能力,社会不应如此对待。例如读写能力是能流利阅读并跟上 Paine《常识》的 50 页论证,且能(并乐于)流利写批评或辩护。另一种 20 世纪读写能力是听到一种新致命传染不治之症时,立刻知道灾难性指数关系成立,早期行动最高优先。另一种读写能力会把公民带到个人计算机前,流利无痛地建立疾病系统模拟,用于与进一步信息比较。
在博雅教育层面,我们会期望每种流利之间的联系形成真正强大的隐喻,以其他想法审视想法。
因此,我们许多人想让孩子深入流利理解计算,是因为像文学、数学、科学、音乐和艺术一样,它携带思考情境的特殊方式,与其他知识和其他批判性思考方式对比,增强我们理解世界的能力。
那时我们不知道,15 年后我遗憾地说,这些关键问题仍没有真正有用的答案。但有一些迹象。即使很小的孩子也能理解和使用交互式转换工具。最初的是他们的手!他们容易把这些经验延伸到计算机对象并修改。他们常能想象提议的修改会做什么,对结果不惊讶。两三岁孩子能用 Smalltalk 式界面操作面向对象图形。三年级学生能在几天内学会新系统 50 多个特征——大多是转换工具——包括用户界面。他们能回答只需应用其中一个工具的问题。但极难回答需要两个或更多转换的问题。然而他们能无问题地应用转换序列,向前探索。正是构思和实现需要多次变化的 modest 目标时,他们几乎完全缺乏导航能力。
似乎需要学习的是把转换按二三打包,像学习跳棋这样的策略游戏。朝向目标的“三合一”模糊感觉可为更详细工作做铺垫。这种艺术对大部分人口可能,但对多数人,需要多年逐步学习。
V. 1976—80:第一个现代 Smalltalk(-76),诞生、应用与改进
到 1975 年底,我觉得我们失去平衡——“儿童 Dynabook”想法慢慢暗淡,或被专业需求淹没。1976 年 1 月,我带全组去 Pajaro Dunes 三天外出,提出问题,重置指南针。会议叫“让我们烧掉磁盘包”。没有大喊大叫,组员太喜欢彼此。但我们困扰。我用老格言“没有生物能在自己的废物中生存”恳求真正新鲜开始:与 ALTO 和 Smalltalk 很不同的软硬件系统。我们都同意当前 Smalltalk 的威力不匹配各自抱负水平。我认为需要不同东西,因为看不出 OOP 本身如何解决最终用户问题。其他人,尤其一些研究生,真想要更好更快的 Smalltalk 做更大问题。我想 Dan 觉得更好的 Smalltalk 可成为我想要的不同的系统的载体,但我无法清楚描述。会议不是灾难,我们回到 PARC 仍是朋友同事,但头四年的绝对凝聚力再没重新凝结。我开始设计新小机器和语言,叫 NoteTaker,Dan 开始设计 Smalltalk-76。
我想“烧掉磁盘包”是因为我对媒介和环境有很 McLuhan 的感觉:一旦塑造工具,用他的话说,它们反过来“重塑我们”。如果工具真的很好且直指问题,这当然是好想法。但剑的另一刃同样深——不充分的工具和环境仍会重塑我们的思考,尽管有问题,部分因为我们想要范式指导目标。像 LISP 和 Smalltalk 这样的强范式如此 compelling,它们吃掉自己的幼崽:看这两个系统中的应用,它们像系统本身,而不是新想法。1975 年我看 Smalltalk,看到伟大东西,但没看到最终用户语言,没看到原初“儿童读写计算机媒介”目标的解决方案。我想停下,炸掉一切,从头开始。
NoteTaker 是“笔记本”,几年内可用(几乎)可用的 16K RAM 建造(比 ALTO 的 1K RAM 大改进)。笔记本不能用鼠标(我反正讨厌),平板似乎尴尬(空间不多,笔放下可能够不着),所以我提出嵌入式指点设备,叫“tabmouse”。它是相对指针,有向上传感器,可像鼠标 stroked,也停在你放的地方,但感觉像笔,用缩放仪机制消除 x 和 y 方向恼人的滞后偏差,使鼠标难当笔用。我计划用原本为 Dynabook 指定的慢但高度集成芯片的多处理器架构,想要新字节码解释器,比 Smalltalk-72 更友好简单。

同时 Dan 全面改造 Smalltalk,路线类似。第一件大事是摆脱函数/类二元论,转向完全内涵定义,每段代码都是内在方法。我们从一开始就想这样(大部分代码已那样写)。Adele 和我、Larry Tesler(做桌面出版)、研究生都强烈想要真正继承机制。Dan 必须找到比 Simula 非常僵硬的编译时概念更好的方式。是时候实现“一切皆对象”,包括所有内部“系统”对象如“活动记录”等。我们都同意早期 Smalltalk 的灵活语法太灵活,这种可扩展性不可取。我们喜欢的所有扩展都用各种关键字方案,所以 Dan 想出关键字/运算符组合语法,非常灵活,但允许人和机器无歧义阅读。这允许类 FLEX 机器的字节码编译器和高效解释器,运行比之前直接解释器快达 180 倍。OOZE VM 系统可修改处理新对象,容量与 ALTO 的 RAM 和磁盘匹配。
继承
关于继承说几句。Simula-I 既没有类作为对象,也没有继承。Simula-67 添加后者,作为 ALGOL-60 块结构的推广。这是好想法。但有一些缺点:小的如多线程列表中的名字冲突(现在没人用线程列表),大的如扩展类型结构僵硬、需要限定类型、只有单条继承路径、难以适应交互式开发系统与增量编译和即时变化需求。还有大量问题真超出 Simula 目标范围:与 AI 世界中各种建模和推理有关。例如,不是所有有用问题都能沿静态链回答。有些需要通过动态绑定“部件”(即实例变量)的“继承”或“推理”。多继承也似乎重要,但不同超类中同名方法可能冲突,难以处理。
另一方面,由于动态语言能做静态编译语言难做的事,我决定在 Smalltalk-72 中不把继承作为特征,知道可用 Smalltalk 的 LISP 式灵活性模拟回来。这些 AI 想法的最大贡献者是 Larry Tesler,他在各种早期桌面出版系统中大量使用现在叫“槽继承”的东西。今天这叫“委托式”继承方案。Danny Bobrow 和 Terry Winograd 在此期间设计“基于框架”的 AI 语言 KRL,是“面向对象”的,我相信受早期 Smalltalk 影响。它有一种多继承,叫“视角”,允许对象以非常干净的方式扮演多重角色。许多这些想法几年后进入 PIE,Ira Goldstein 和 Bobrow 对 Smalltalk 的有趣扩展,面向网络和更高层描述。
到 Smalltalk-76 出现时,Dan Ingalls 想出方案,语义类似 Simula,但可增量即时修改,符合紧密交互目标。我不完全激动,因为似乎需要更好的继承理论(现在仍需要)。例如,继承和实例化(一种继承)混淆了语用(如分解代码省空间)和语义(用于太多任务:特化、泛化、物种形成等)。Alan Borning 在 Thinglab 中用多继承方案,实现在 Smalltalk-76 中。但没有全面干净的多继承方案出现,足以超越 Dan 原初的 Simula 式设计。
同时,与 Xerox 的战斗继续。现在约 500 台 ALTO 通过以太网互连,并连到激光打印机和文件服务器(用 ALTO 作控制器)。我写许多备忘录给 Xerox 规划者,试图让他们把个人计算作为主要方向之一。例子:
未来的一种简单愿景——我 1971 年 Pendery 论文的简要更新
1990 年代将有数百万台个人计算机。它们将是今天笔记本大小,有高分辨率平板反射显示,重不到十磅,计算和存储能力是 Alto 的 10—20 倍。称它们为 Dynabook。购买价约当时彩色电视机,尽管大多数机器将由制造商送出,因为他们营销的是个人计算的内容而非容器。
…… Dynabook 虽有相当本地存储并本地做大部分计算,但会花很大比例时间连到各种大型全球信息公用设施,允许与他人交流想法、数据、工作模型,以及组织运作所需的日常闲聊。通信链路将是私人和公共有线及分组无线电。Dynabook 也用作信息公用设施中的服务器。它们有足够能力完全由软件塑造。
这个愿景的要点
- 只需少数硬件类型就能处理系统几乎所有处理活动。
- 个人计算机、通信链路和信息公用设施是 Xerox 未来的三个关键组件。
…… 换句话说,计算机系统的材料是计算机本身,所有内容和功能都在软件中塑造。由此得出两个重要指导:
- 材料:如果硬件计算机材料的设计和开发像 Xerox 开发特殊感光合金那样仔细完整,那么只需一两种计算机设计……这里额外投资会因简化制造和因产量增加降低成本而大大回报。
- 内容:除了能从同种材料连续塑造新内容的奇妙普遍性,软件有三个重要特征:内容功能的复制时间和成本为零;内容功能的开发时间和成本高;内容功能的变更时间和成本可低。
Xerox 必须认真对待这些点,才能在新的信息媒介业务中生存繁荣。如果做到,公司有很好机会,原因包括:Xerox 有财务基础覆盖少数极强大计算机类型和大量软件功能的高开发成本;有营销基础在足够大规模销售这些功能,收回惊人利润;有世界上很大比例最好的软件设计者为其工作。
1976 年,Chuck Thacker 设计 ALTO III,使用新 16K 芯片,能放桌面。它的售价可约等于大型笨重专用“文字处理器”,却能做更多。然而 1976 年 8 月,Xerox 做出重大决定:不把 ALTO III 推向市场。这对我们许多人巨大打击——即使我,从未真正把 ALTO 当成别的,只当通向“真东西”的踏脚石。1992 年,个人计算机和工作站世界市场是 9000 万美元——是大型机和小型机市场的两倍,是 Xerox 1992 年总收入许多倍。这个时代最成功的公司——微软——不是硬件公司,而是软件公司。
Smalltalk 用户界面
几位审稿人让我多说“Smalltalk 风格”重叠窗口用户界面的发展,因为现在世界上有 2000 多万台计算机使用其后代。像样的历史会和本章一样长,迄今没人写。一些想法总结在 [Kay 89]——我再加点。
最终用于 Smalltalk 用户界面的所有元素在六十年代都已存在——作为访问和调用交互系统功能的不同方式。两个主要想法中心是 Lincoln Labs 和 RAND,都由 ARPA 资助。把这些想法巩固成强大理论和长寿范例的大转变,来自 LRG 聚焦孩子。因此我们思考学习是我们想要发生的主要效果之一。早期,这导致用户界面目的 90 度旋转,从“访问功能”转向“用户通过做来学习的环境”。这个新立场现在能回应 Montessori 和 Dewey 的回声,尤其前者,并让我重读 Jerome Bruner 后,超越儿童课程想到“用户界面课程”。
LRG 的特定目标是找到写作的等价物——在媒介中通过做来学习和思考——我们的新“口袋宇宙”。因各种原因,我选定“图标编程”来实现,借鉴六十年代许多 ARPA 项目用的图标表示。我朋友 Nicholas Negroponte,建筑师,极感兴趣环境如何影响人的工作和创造力。他感兴趣把新计算机魔法嵌入熟悉环境。我前世有相当戏剧经验,记得柯勒律治格言:“人们看坏戏剧希望忘记,人们看好戏剧渴望记住。”换句话说,是唤起观众自己智力和经验的能力使戏剧工作。


把所有这些放在一起,我们想要一个显然自由的环境,探索导致期望序列发生(Montessori);允许动觉、图标和符号学习——“用图像做,使符号”(Piaget 和 Bruner);用户从不困在模式中(GRAIL);魔法嵌入熟悉(Negroponte);并作为用户自己智力的放大镜(Coleridge)。如果故事能说我们明确表达后直接走向今天所知设计,那会是好结局。事实上,UI 设计工作在喂 Smalltalk、设计儿童实验、理解图标构造和玩耍之间断断续续发生。尽管曲折,语境几乎迫使好设计出现。当时 PARC 几乎每个人对 UI 有意见,我们的和他们的。不可能给数百个想法和讨论详细功劳。但巩固肯定归功于 Dan Ingalls,他倾听所有人,贡献原创想法,不断为设计做用户测试。我在设定语境、发明重叠窗口等方面有相当多参与,Adele 和我设计大部分实验。此外,Ted Kaehler 和访客 Ron Baecker 做出非常有价值贡献。Dan Halbert 设计了 SmallStar,Xerox Star 产品的原型图标界面。
同时,我让 Doug Fairbairn 对 NoteTaker 感兴趣。他设计了奇妙的“智能总线”,能高效处理慢速多处理器,系统看起来很有希望,尽管 PARC 大多数其他人认为我放弃 ALTO 的快速双极硬件是疯了。但我看不出双极硬件能进笔记本或 Dynabook。另一方面,我讨厌刚出现的 8 位微处理器,因为设计愚蠢天真——没有迹象表明任何设计过软件的人参与。
Smalltalk-76
Dan 在 11 月完成 Smalltalk-76 设计,他、Dave Robson、Ted Kaehler 和 Diana Merry 在仅七个月内从零成功实现系统(包括重写所有现有类定义)。这是如此奇妙的成就,尽管我想从头开始,也被震住。它快、活泼、能处理“大”问题,非常有趣。系统约 50 个类,描述在约 180 页源代码中。包括所有 OS 功能、文件、打印和其他以太网服务、窗口界面、编辑器、图形和绘画系统,以及 Larry Tesler 的两个新贡献:继承层次中静态方法的著名浏览器和运行时调试动态上下文的浏览器。各方面都是我们所有 Smalltalk 想法和渴望整合进一个集成包。此后所有 Smalltalk 都与此概念非常接近。许多方面,正如 Tony Hoare 曾评 Algol,Dan 的 Smalltalk-76 是对其后继者的巨大改进!

这是 Dan 写的两个有风格的 ST-76 类。注意尤其在 Window 类中,代码如何表达为其他对象(或自身)要达到的目标。超类 Window 的主要工作是注意到事件并作为消息分发给子类。例子中,文档窗口(DocWindow 的子类)将处理用户交互效果。Window 类会注意到键盘活动并给自己发消息,被子类方法截获。如果没有方法,字符被丢弃,窗口闪烁。此处找到 DocWindow 方法 keyboard,告诉持有的文档检查它。


1978 年 1 月,Smalltalk-76 首次真正测试。CSL 邀请 Xerox 十大高管到 PARC 参加两天软件研讨会,特别强调复杂性及能做什么。LRG 被要求给他们最终用户编程动手经验,让他们“在两个 1.5 小时会议中做‘真实事情’”。我们立即决定不教他们 Smalltalk-76(我“烧掉磁盘包”观点的加强版),而是在两个月内用 Smalltalk-76 创建丰富系统,专门为成人非专家用户(Dan 观点的王牌)。我们以“Simpula” job shop 模拟模型为起点,决定为通用 job shop 模拟工具建用户界面,高管可将其变成具体动态模拟,通过屏幕上动画图形演出变化状态。我们叫它 Smalltalk SimKit。这是最大努力,人人参与。Adele 成为设计领导,尽管刚生了孩子。我有一个无价记忆:她一边调试 SimKit,一边给 Rachell 喂奶。
许多有趣问题要解决。系统本身直接,但必须与 Smalltalk 本身完全隔离,尤其错误消息。Dave Robson 想出好方案(几乎专家系统)捕捉 Smalltalk 深处的抱怨,翻译成有意义的 SimKit 术语。许多 UI 细节——有些日常,如做新浏览器只能看四个 SimKit 类(Station、Worker、Job、Report);有些更惊人,如我们在约同年龄的十个 PARC 非技术成人上试,发现他们读屏不好。我们三十多岁眼睛习惯的小字体对五十多岁不行。这导致系统的好介绍:鼓励高管通过选择不同字体和大小定制屏幕,副作用是他们无意识地学会用鼠标。
“大日子”早上,Ted Kaehler 决定改 OOZE 虚拟内存系统让它快点。我们都屏息,但设计清晰、实现者自信,它确实工作,高管动手大获成功。第一场约一小时后,一位 15 年前写过几行 FORTRAN 的副总裁终于意识到他在编程,沉思道:“所以终于到这一步了。”十位高管中九位能完成与他们具体兴趣相关的模拟问题。最有趣复杂之一是用实际数字(他记在脑中)做 PC 板生产线,为模型提供初值,闭式数学难解——它揭示生产线平均制造缺陷概率下工人配置的严重缺陷。

当时另一个重要系统是 Alan Borning 的 Thinglab——首次严肃尝试超越 Ivan Sutherland 的 Sketchpad。Alan 设计非常好的方法处理约束,不要求求解者全知(或能解费马大定理)。我们能看出 Smalltalk 的“推”风格最终可被“拉”风格取代,由不同方法所基于值的变化驱动。这是老想法,但 Thinglab 显示面向对象定义如何自动限制事件驱动处理的上下文。我们很快发现“原型”比类更友好,多继承若让方法类通常知道它们应关于什么(受 Pat Winston 二阶模型启发)会服务得好。
同时,NoteTaker 越来越真实、越来越大、越来越慢。此时我希望用的 Western Digital 模拟式芯片显示“扩散软件”迹象,看起来不会真出现。我们开始找可靠东西,即使架构不好。1978 年最佳候选是 Intel 8086,16 位芯片(带许多 8008 和 8080 的不幸残余),但(勉强)够容量做工作——需要三个,一个解释器,一个位图图形,一个 I/O(网络等)。
Dan 一直对 NoteTaker 感兴趣,想看看能否做一版 Smalltalk-76 作为 NoteTaker 系统。为此必须跑在 256K,我们计划的最大 RAM。ALTO 的 NOVA 式模拟“机器码”都不能带过来,也必须放进内存——只有软盘,没有交换内存。这个挑战导致系统设计一些优秀改进。Ted Kaehler 的系统追踪器(可从旧虚拟内存写出新虚拟内存)用来把 Smalltalk-76 克隆到 NoteTaker。索引对象表(早期 Smalltalk-80 所用)首次出现,简化对象访问。尝试连续堆叠上下文以省空间和提速。大部分旧机器码用 Smalltalk 重写,总机器内核减到 6K 字节(不太强的)8086 代码。
所有重新工程产生有趣效果。虽然 8086 的 bitblt 不如 ALTO(许多辅助图形的旧机器码现在在 Smalltalk 中),整体解释器约是 ALTO 版的两倍快(因为并非所有 Smalltalk 字节码解释器都装得进 ALTO 的 4K 微码内存)。各种技巧和调优后,图形显示“基本补偿”(Dan 的话)。主要因为 ALTO 没有足够微码内存容纳所有 Smalltalk 模拟代码——有些必须用模拟“NOVA”代码,强制两层解释。事实上 NoteTaker 工作极好,尽管会压碎任何膝盖。它跳回桌面,看起来可疑地像 miniCOM(和几年后出现的几台计算机)。它真的用电池运行,我们几人曾高兴地把 NoteTaker 带上飞机,在 35000 英尺运行带窗口界面的面向对象系统。
![]()
我们最终造了约 10 台,虽然在许多意义上是工程成功,但制造它们所需又一次挤掉了最初瞄准的真正最终用户。如果 Xerox(和 PARC)整体相信这些较小规模想法,我们本可把更多硅力量放在梦想后面,在七十年代它们首次可能时成功建造。不得不从 Intel 拿错误 CPU、从 HP 拿错误显示,是痛苦失望,因为没有足够公司意志利用内部技术专长。
此时已 1979 年,我们发现自己做许多演示之一,但这次观众非常感兴趣:Steve Jobs、Jef Raskin 和 Apple 其他技术人员。他们开始了叫 Lisa 的项目,但不太确定应是什么样,直到 Jef 对 Steve 说:“你真该来 PARC 看看他们在做什么。”因此,在重叠窗口发明八年多后、ALTO 开始运行六年多后,真正能对这些想法做点什么的人终于看到它们。所用机器是 Dorado,ALTO 的非常快“大哥”,其 Smalltalk 微码大部分由 Bruce Horn 写,他是我们原来的“Smalltalk 孩子”之一,仍只是青少年。Larry Tesler 做演示主要部分,Dan 坐副驾驶,Adele 和我在后排看。演示最好的部分之一是 Steve Jobs 说不喜欢我们用的 blt 式滚动,问能否做平滑连续风格。不到一分钟 Dan 找到相关方法,做了(相对重大)修改,滚动现在连续!这震惊访客,尤其其中程序员,他们从未见过真正强大的增量系统。
Steve 试图从 Xerox(Apple 的少数风险投资方之一)获得或购买技术,但 Xerox 既不放手,也不愿出资源通过资助更好的 NoteTaker 加 Smalltalk 在内部继续开发。
VI. 1980—83:Smalltalk 发布版(-80)
“艺术中最大的罪不是无聊,如通常所想,而是缺乏比例。”——Paul Hindemith
正如 Dan 说:“不继续 NoteTaker 项目的决定增加了广泛发布 Smalltalk 的动力。”但对我不是。此时我既高兴于 Dan 等人实现的 Smalltalk 概念的干净优雅,又难过它比以往更远离孩子——我震惊地意识到,自 Smalltalk-76 首次亮相后,没有孩子用任何 Smalltalk 编程过。Xerox(和 PARC)现在把“工作站”当自身目的——但我仍想要“游戏站”。Dynabook 的浪漫似乎更不可及,悖论地正值各种所需技术开始商业可行——有些不幸如平板显示,被发明它的美国公司放弃给日本。这是“从胜利口中夺回失败”的重大案例。Larry Tesler 决定 Xerox 永远不会“懂”,1980 年 5 月被 Steve Jobs 聘为 Lisa 主要设计者。我同意,有休假,就休假了。
Adele 决定推动新 Smalltalk 的文档和发布过程,可广泛分布,几乎不管目标硬件。只需对 NoteTaker Smalltalk-78 做几处修改就可发布。也许最讽刺的修改是把让 Smalltalk 更可读的定制字体(整个 PARC 文化的标志)改回标准平庸 ASCII 字符。据 Peter Deutsch,这“当时在组内遇到激烈反对,但结果对系统在世界上被接受至关重要。”另一修改是让块更像 lambda 表达式,正如 Peter Deutsch 九年后说:“回顾,这种不同实例化和作用域的增殖可能是个坏主意。”最令人困惑的怪想法——至少对我这个新外来者——是引入元类(其实只是让实例初始化容易一点——比 Smalltalk-76 已相当合理做法的小改进)。Peter 1989 年评论典型而真实:“元类已证明让许多用户困惑,也许权衡下困惑多于价值。”事实上,在他们的 PIE 系统中,Goldstein 和 Bobrow 已在 Smalltalk 中实现“观察者语言”,有点遵循我一直倡导的视点导向方法,某些方面像 KRL 中提出的“视角”。一旦能通过多视角观察实例,甚至像 Class Class 和 Class Object 这样的“半元类”也不必要,因为对象角色和类实例角色只是不同视图,容易处理生命史问题包括实例化。这唾手可得(还有许多其他好想法),但没被采用。我猜 Smalltalk 已进入我在故事开头提到的最后阶段:一种做事方式最终被奉为不灵活信仰结构。
尾声
最后评论。硬件其实只是早期结晶的软件。它在那里让程序方案尽可能高效运行。但硬件太常被呈现为给定,由软件设计者让它显得合理。这导致低层技术和过度优化阻碍程序设计进步。如 Bob Barton 常说:“系统程序员是低级崇拜的高级祭司。”
思考软件进步的一种方式是,许多进步关于寻找晚绑定方法,然后发动运动说服制造商把想法建进硬件。早期硬件有硬连线程序和参数;随机存取内存是晚绑定它们。循环和索引过去用存储中地址修改做;索引寄存器是晚绑定。多年来软件设计者找到晚绑定计算位置的方法——导致基址/界限寄存器、段重定位、页 MMU、迁移进程等。分时被推迟多年因为“低效”——但制造商不愿把 MMU 放机器上,大学只好自己做!递归晚绑定参数到过程,但花多年才把基本栈机制放进 CPU。大多数机器仍不支持动态分配和垃圾回收等。简言之,今天大多数硬件设计只是对垂死架构的重新优化。
从晚绑定视角,OOP 可看作尽可能晚绑定许多东西的综合技术:一组行为中状态和过程的混合、它们的位置、名称、何时为何被调用、用哪个硬件等,更微妙的是 OOP 方案本身使用的策略。包装的艺术是陷阱的艺术。
考虑为完整包装对象而必须高效处理的两个情况。如果 a + b 中 a 和 b 绑定到“3”和“4”,能以 ALU 处理形式,却产生开销,会很糟。操作应全速使用旁视逻辑(最简单方案中一个与门)执行,在不兼容时陷阱。现在所有必须快速发生的基本操作已被包装,不拖慢机器。
第二种情况发生在陷阱判定对象对 ALU 太复杂。现在硬件必须动态找到能处理对象的方法。这非常像索引——对象之一的类被所需方法选择器以稍微更一般方式“索引”。换句话说,方法的虚拟地址是 <类><选择器>。由于今天大多数硬件做某种虚拟地址转换找真实地址——一个陷阱——完全可以把 OOP 分派开销藏在已合理化的 MMU 开销中。
再次,OOP 的整个要点是不必担心对象内部。不同机器、不同语言制造的对象应能互相交谈——将来必须。晚绑定在这里涉及把不兼容性陷阱到兼容方法中。更详细的讨论见 [Popek 1984]。
继续晚绑定隐喻,我们可能期待什么进一步晚绑定方案?Xerox PARC 正在实验的最好晚绑定方案之一是元对象协议工作。想法是语言设计者对实例、变量等内部表示的选择可能不覆盖实现者需要,所以在固定语义内允许实现者给系统策略——例如,对实例槽用哈希查找而非直接索引。这些被高效编译并扩展系统基础实现。这是 Simula、FLEX、CDL、Smalltalk 和 Actors 过去类似方向的直接后裔。
另一个已必要的晚绑定方案是当新对象出现在对象系统中时摆脱直接协议匹配。换句话说,如果有人从世界另一边给你一个对象,它符合你本地协议会很不寻常。某个时候,让它携带更多关于自身的信息会更容易——足以让它的规格被“理解”,并通过更微妙的推理匹配配置进你的混合中。
超越今天所知 OOP 也可通过思考晚绑定来做。Prolog 的伟大想法是它不需要绑定到值就能计算。变量是对象,可建立部分结果网,等最终找到绑定时填入。Eurisko 在试图解决问题时构造其方法——并修改基本策略。不是问题找方法,而是方法找问题——Eurisko 找方法的方法。这被称为“机会主义编程”——我把它看作对更多启蒙的驱动,问题作为过程一部分被解决。
这种更高计算技巧将需要,因为下一个范式转移——普遍网络——将在未来五年发生。对象逐渐成为主动代理,在网络中旅行,为管理者寻找有用信息和工具。从世界另一边带回计算环境的对象不能像今天对象那样通过直接协议匹配配置自己。相反,对象将携带更多自身信息,形式允许推理式对接。规格方面的一些持续工作可转向此任务。
半开玩笑地,我曾把编程语言进步描述为“太阳黑子”理论,重大进步约每 11 年发生。1950 年机器码,1956 年 FORTRAN 作为“更好的旧事物”,若看作“几乎新事物”成为 1961 年 ALGOL-60 先驱。1966 年 SIMULA 是“更好的旧事物”,若看作“几乎新事物”成为 1972 年 Smalltalk 先驱。一切似乎准备再次证实“理论”:1978 年 Eurisko 是“更好的旧事物”,是“几乎新事物”。但 1983 年——和整个十年——来了又去,没有“新事物”。当然这种理论愚蠢——但我认为个人计算的巨大商业化窒息了大学和研究实验室过去做的许多工作,把有才华的孩子吸向实际应用。公司对做自己硬件如此风险厌恶,硬件公司对软件毫无真正理解,结果在许多方面大倒退。
20 世纪的问题是技术变得太“容易”。当做什么都难时,无论好坏,花的时间够多,结果通常好。现在我们可以几乎琐碎地制造东西,尤其在软件中,但大多数设计也琐碎。这是逆向破坏:因为你能制造就制造。加上更不 sophisticated 的买家,你生成类似为青少年设置的剥削市场。对抗方法是用整个人类艺术史作为标准和目标,对自己的设计产生巨大不满。然后诀窍是把不满与自我价值脱钩——否则要么太沮丧,要么太早停在琐碎结果上。

我把早期 Smalltalk 的故事留在 1981 年,当时《Byte》杂志发表一系列关于 Smalltalk-80 的文章,随后 Adele 和 Dave Robson 的书,1983 年系统正式发布。现在程序员容易实现虚拟机,不必重新发明,有些组能滚出自己的基础类镜像。尽管不得不在几乎到处都垂死的硬件架构上运行,Smalltalk 惊人地扩散(部分因在这些机器上的巨大优化努力)。据我所知,它似乎仍是声称面向对象的最广泛使用系统。我难以置信,此后没人提出定性更好、同样简单、优雅、易编程、实用和全面的想法。(遗憾的是我们当时不知道 PROLOG,或反之,后来两种语言的结合相当有趣。)
在公正地为 Dan、Adele 和其他使 Smalltalk 成为可能的人鼓掌时,我们必须同时问:80 年代和 90 年代的 Dan 和 Adele 们在哪里,将带我们到下一阶段?

评论
社区整体弥漫着对 Smalltalk 的怀旧与敬意,对其技术优越性有共识,但对其商业失败原因(人力成本、招聘偏好)感到无奈;分歧在于它究竟是超前的失败者还是持续存活的小众工具。
认为 Smalltalk 技术优越但败给商业与人力成本
- 曾有专业开发者指出,Smalltalk 被 Java 等技术更差的系统替代,因为人事可用一名资深工资雇四五个经验浅者,市场偏好廉价人力而非优良系统,作者并对当下 AI 重演类似易自伤困境感到幸灾乐祸(较多人) > 人事部门宁愿用一份 Smalltalk 高薪雇多名不懂系统的新手,导致优秀语言出局(@mwnorman2)
认为 Smalltalk 仍在实际使用并拥有满意客户
- 有评论提到自 1988 年成立的公司每年发布新版本,客户积极在其上构建且显得开心,说明并未完全消失(少数人)
认为 Smalltalk 提供沉浸式体验且后续语言难及
- 多名开发者回忆使用 Smalltalk 让人“生活在程序里”,相比之后 Java 的笨拙,仅 Ruby 带来同等乐趣,并形成一类永远怀念优越工具的人群(较多人) > 从 Smalltalk 转向 Java 后处处觉得笨重,只有 Ruby 重新点燃了那种喜悦(@jttnr)
认为 Smalltalk 深刻影响了 Objective-C 与苹果生态
- 不少人忽略 Smalltalk 深刻塑造了 NeXTSTEP 与 Objective-C,Xcode 的界面序列化与消息传递机制皆源于此(较多人)
认为 Smalltalk 最初是面向儿童的教育语言
- 反直觉的事实:Smalltalk 起步定位是儿童教育,比 Logo 更早以对象为核心脚手架,影响却深远得多(少数人) > 令人惊讶,Smalltalk 原本是给孩子们设计的教育语言(@chasil)
认为 Smalltalk 语法极美但缺乏硬件支撑
- 有评价称其语法是世界上最美、概念极深,但硬件架构从未给予足够支持,业界曾尝试多种专用处理器均未成(少数人)
有价值的补充
- 历史考据:有社区成员光学字符识别校正了 1992 年 Yoot Saito 对 Alan Kay 的采访,并补全了 Smalltalk 早期历史论文的附录与索引,为研究提供完整资料(@DonHopkins)
- 冷知识:面向对象编程概念可溯至 1950s,实现继承在 Kay 文中更像是偶然决策而非原则设计,数据内存排布影响问题求解难度(@bunderbunder)
- 关联文化:Bret Victor 的个人站点曾发布其令人振奋的编程未来演讲,被社区怀念(@crispyambulance)