前言

近期在阅读 Squeak News, 这是第一份致力于 Squeak 的杂志。杂志的前三期连载了对 John Maloney 的采访。

John Maloney

John Maloney 是 Squeak 原始团队的成员。John 的贡献包括 Smalltalk-to-C 翻译器(Squeak 可移植性的关键),Macintosh 虚拟机,Socket,声音和音乐设施,以及 Morphic 用户界面框架。

在加入 Squeak 团队之前,John 在 Sun Microsystems 实验室工作,在那里他和 Randy Smith 为 Self 编程环境建立了第一个版本的 morphic。John 在华盛顿大学获得博士学位,作为 Alan Borning 的学生,他开发了一个用 Smalltalk 编写的快速、基于约束的用户界面工具包(Thinglab II)。

在他研究生生涯的早期,他在 Xerox PARC 的 Smalltalk 小组度过了一个夏天,并在 CMU 做了八个月的实时音乐伴奏工作。

20 世纪 70 年代末,当 John 在麻省理工学院时,他作为合作学生在 DEC 的研究实验室工作。正是在那里,他第一次看到了 Smalltalk 的早期实现,并爱上了这种语言。他至今还保留着一本褪色的《梦想与计划(Dreams and Schemes)》的非法影印本,它最终成为 Smalltalk 蓝皮书的草稿。

John 喜欢文艺复兴时期的音乐。他演奏直笛(recorders),与斯坦福大学早期音乐合唱团一起唱歌,在过去的几年里,他一直在学习演奏 sackbut,一种早期版本的滑动长号。


我将阅读过程中觉得精彩的部分翻译于此,主要作为我自己的笔记,供日后学习和写作参考。

译文

第一期

SN(Squeak News):当你去 Smalltalk 小组的时候,第一印象是什么?我应该叫它 “Smalltalk 小组” 吗?

John:当时它的正式名称是"系统概念组",但你可以直接说 “Smalltalk 组”。 首先,一开始我就被 Smalltalk 的类库压得喘不过气来。 我喜欢这门语言,但很难知道如何开始。 当时我觉得我还不能运行我的程序,因为我不确定它是否能工作。 我一直只用编译型、强类型的语言,如 C、Mesa 和 Modula-2。Smalltalk 小组的人说:“直接运行你的程序吧,最坏的情况是你会得到一个调试器”。 尽管如此,我还是花了至少六个星期的时间才完全克服了第一次运行新代码时的恐惧感,因为在内心深处,我觉得,由于程序没有经过类型检查,它肯定会严重崩溃。 但是,它从未发生过。 如果我有一个 Smalltalk 调试器(debugger),我常常可以解决这个问题并继续前进。 有一天,我获得巨大的解脱。我终于内化了一个想法:我可以运行一个不完整的程序。 我可以测试我的程序的一部分,即使它的其他主要部分还没有开始。停止到处声明类型也是一种巨大的解脱。你常常可以通过改变变量初始化的地方来改变你对数据结构的选择。例如,你可以把一个变量从 OrderedCollection 改成 Set,而不需要改变其他代码。这一个改变可能会对程序的行为或性能产生巨大影响。 如果你不能在几个备选方案中做出决定,把它们都试一遍吧。这太棒了!


SN:然后你与 Smalltalk 失去了一段时间的联系?

John:那个夏天结束后,我回到了华盛顿大学,完成了研究生的下一个阶段,即普通考试。那段时间里,我用三四种不同的语言编程,这是你在读研究生时应该做的。然后我临时请了假,在 CMU 和一位叫 Roger Dannenburg 的教授一起研究计算机音乐。 我在一台 128K 的 Macintosh 上用 C 语言工作。 那时候我初次熟悉了 MIDI、实时控制和音乐的数据结构等东西。我在 CMU 呆了大约 8 个月。当我回到研究生院的时候,我决定教一门计算机音乐的课程。我想使用我刚刚建立的 MIDI 工具,但我希望人们能够比用 C 语言更容易地进行实验的东西来编程,所以我重写了 CMU 系统的基本部分:即一个乐谱表示,一个基于文本的乐谱符号的分析器,以及一个 MIDI 乐谱播放器。我用 ParcPlace Smalltalk 写了所有这些东西,只花了 3 个星期就写完了用 C 语言写了几个月的东西。这是我第一次意识到,至少对我来说,Smalltalk 的生产力是 C 语言的 5 到 10 倍。当我用 C 语言写代码时,我经常被一些愚蠢的错误卡住,导致系统崩溃,比如说一个悬空的指针,我可能要花几天甚至几周的时间才能找到问题所在,这取决于它失败的持续程度。这样的调试既不有趣,也浪费时间。在 Smalltalk 中,你根本就不会被这样的 bug 所困。在堆栈中,很少有人不知道到底是什么地方出了问题,以及为什么会出问题,你很少会在一个错误上停留超过几分钟。最重要的是,你可以很快地对程序进行修改,因为你不需要在很多不同的地方进行修改,比如头文件、程序声明、程序调用、变量声明… 你基本上一改变了对象的创建位置,其他的东西都能适应它。 这些是我在重写 C 语言编写的 MIDI 系统时的一些认识。

在那一刻,我确信我再也不想用那些不如 Smalltalk 出色的东西来编程了。我也基本做到了这一点。我研究生毕业后的第一份工作是在 Sun 实验室的 Self 小组。Self 是一种与 Smalltalk 非常相似的语言。然后我从 Sun 公司去了苹果公司的 Alan Kay 小组,在那里我们开始建立 Squeak。之后,Alan 的整个小组搬到了迪斯尼,继续使用和开发 Squeak。我真的很幸运,不是每个程序员都能在他们选择的语言中编程这么多年的。


SN:你能用几个简短的句子解释一下基于约束的编程吗?

John:在基于约束的编程中,程序员声明变量之间的关系,并让约束求解器强制执行这些关系。这就是约束的含义: 系统始终保持的关系。例如,在一个用户界面中,你可以用约束来处理布局。你可以说 “把这个盒子放在另一个盒子的中心”。然后,如果你移动或调整任何一个盒子的大小,这两个盒子就会被粘在一起,一个在另一个的中间。另一个例子是,一些变量应该总是等于另一个变量的 9/5 倍加 32 的值。这是一种双向的关系,所以如果你改变等式的任何一边,另一边也会被更新以保持约束。约束可以用来建立小型的多向计算器,如华氏/摄氏温度转换器、货币计算器,或偿还抵押贷款的模型。一旦你建立了这样一个计算器,你可以改变任何一个变量,而约束系统会改变其他的变量,以确保所有的约束都得到满足。


John:我们是否可以说,约束就在我们身边?现实世界中的一个例子是,如果我们有一张桌子,桌子上有一盘水果,桌子对盘子有约束作用,盘子对水果也有约束作用,这样水果就会留在盘子里,盘子不会掉到地上,如果你移动桌子,所有东西都会一起移动。这样做对吗?

John:很好的例子。约束对于建立这种物理关系的模型真的很有用。但在做了大量的约束工作后,我得出结论,约束是一种棘手的计算机编程方式。其中一个缺陷是,你可以相当容易地陈述一组没有解决方案的约束。例如,在你的例子中,如果桌子有三英尺高,你就不能增加一个约束,要求碗离地面正好一英尺,因为碗不可能同时离地面一英尺和三英尺。一个相关的问题是如何告诉用户有一个不一致的地方以及原因。有时很难以用户理解的方式告诉他们,因为可能有一长串的约束与两个变量有关。这种间接性使得用户很难看到这两个变量已经耦合在一起了,所以他们对不能在变量之间添加另一个但不一致的约束感到惊讶。帮助用户调试这种情况是很难的。

一个更大的问题是,对于用户来说,什么是难的,什么是容易解决的约束系统并不明显。例如,对于一个足够普遍的约束系统,你可以表达以下约束问题:

x^n + y^n = z^n, n>2

费马的最后一个定理说,这组约束没有解,但数学家花了 3 个多世纪才证明。 一个约束系统将永远寻找一组能解决这些约束的整数,因为它永远不会用完可以尝试的整数。因此,对于一个通用约束系统来说,它确实很难检测到什么时候它遇到了一个难以解决或不可能解决的问题,然而用户很可能期望约束系统应该能够解决任何可以被表达为一组约束的问题。从某种意义上说,一般的约束性编程设置了用户的期望,但却无法满足它。

我在 Thinglab II 中所做的是 “约束” 约束求解器,即只有某些类型的约束问题你可以指定。然而,在这些问题的子集中,系统可以保证迅速找到一个解决方案,或者迅速发现没有解决方案。由于我对用户互动感兴趣, 即把东西拖来拖去,让系统实时响应,我愿意放弃通用性来获得性能。在我的论文中,我描述了一些有用的用户界面问题,这些问题可以由 Thinglab II 中的有限约束求解器处理。


John:Thinglab 绝对是一个非常酷的系统。它是探索某些特定领域的好东西,因为你可以把约束摆在一起,然后把玩参数。Thinglab 有一些整洁的图形例子。你可以在一组线条上设置一些简单的约束,以创建一个几何图形,然后拖动各种点,观察这个几何图形的形状变化。这很有趣,也很有教育意义。

然而,我认为对于大多数日常问题来说,直接写一个算法解决方案要比尝试使用一般的约束求解器更容易。以排序为例。 你可以写一些约束,指定你要对一个集合的内容进行排序,使每个项目都等于或大于前面的项目,但很难想象一个一般的约束求解器能有效地进行排序。一般的算法可能会在集合的所有排列中寻找满足排序约束的排列,但对于大型集合来说,这将是非常缓慢的。你可以在约束求解器中建立一个排序算法(作为一种特殊情况),但在这种情况下,你还不如直接将排序算法应用于集合。


John:所以这是我认为约束不实用的一个原因。另一个原因是,通常在任何交互式计算机系统中,你可能会有部分程序被写成指令性代码,说 “现在做这个或那个”。将系统中的这些命令式部分与约束系统结合起来是很棘手的,尤其是当约束系统必须触发有副作用的代码时,例如打印或将数据写入文件。 作为论文的一部分,我研究了建立这样一个混合系统,但它很尴尬,因为你需要确切地知道约束系统是如何工作的,这样你才能预测什么时候会调用指令性代码。我的结论是,对于通用编程来说,约束系统的麻烦比它们的价值更大。简而言之,我并不觉得让约束满足成为 Squeak 系统的核心部分有什么价值。 例如,我不想让 Morphic 成为基于约束的系统。 但我很高兴看到 Thinglab 或其他约束系统作为应用程序在 Squeak 之上运行。


SN:你在 Self 中的参与度很高。在 Self 的经历是怎样的?

John:那是一个非常棒的团队,Self 是一种非常有趣的语言。Self 有一个非常复杂的虚拟机。它做了大量的即时优化,远远超过大多数 JIT 编译器所做的,除了 Hot-Spot 虚拟机,Hot-Spot 虚拟机是由一些建立 Self 虚拟机的人创建的。这个故事很有趣。Self 小组的一部分人离开了 Sun,成立了一家名为 Animorphic Systems 的公司。他们为 Smalltalk 和 Java 建立了一个虚拟机,而这个 Java 虚拟机在当时比 Sun 的 Java 虚拟机快 5 到 10 倍。因此,Sun 公司买下了 Animorphic Systems 公司,并让他们所有人投入到 HotSpot VM 的工作中。 Self 虚拟机使用了与 HotSpot 类似的技术来运行 Self,它的性能确实惊人,比大多数 Smalltalk 虚拟机都要好,在一些情况下甚至比 C 还要好。

SN:我记得看到过一些与 C 语言相当的基准测试。

John:有几个例子,Self VM 展开并内联了一个递归程序,而且运行速度比 C 还要快,所以 Self VM 有时具有惊人的性能。另一方面,在日常工作中,Self VM 可能令人沮丧,因为你永远不知道你的程序到底会有多快。原因是你第一次运行一个程序时,虚拟机不一定会优化它。你需要在循环中运行程序几百次,才能开始看到优化的代码性能。但总是有可能再运行一次就会翻转一个计数器,并触发另一个级别的优化,可能会导致另一个系数倍或 2 倍的性能。 因此,很难知道什么时候看到了一个程序的完全优化性能。 这使得调整代码的速度变得很困难,很难说一个给定的变化是使程序变快还是变慢。 为了进行这样的比较,我经常在清除代码缓存后,在一个循环中运行新旧版本的程序,次数相同。但有时相对性能会发生翻转。例如,运行 100 次后,程序 A 可能更快,但运行 200 次后,程序 B 会更快。那么,在最终的应用程序中,哪个程序会给用户带来更好的性能?这几乎是不可能知道的。

Squeak 总体上比 Self 慢,但 Squeak 程序的性能是可预测和可复制的。对 Squeak 程序做一个改变,可以马上知道这个改变是让程序更快还是更慢。也许我专注于性能,但我发现当你做交互式东西的时候,通常会抵达这样一个境地,你需要调整一些东西以使其足够快。在 Squeak 中做这种调整要比在 Self 中容易得多!

我在使用 Self 时发现了另一件事(David Ungar 可能对此有不同的看法)那就是类(Class)作为一种结构化工具非常有用。在 Self 中,不存在类。每个对象都定义了自己的行为。但是为了在 Self 中建立一个可重用的代码库,我们遵循了一大堆旨在模仿类的惯例。Craig Chambers 和 Dave 为此写了一整篇论文。他们基本上描述了将对象分成像类的方法的集合(称为 “特性(traits)")和类似 Smalltalk 实例的实例变量包的惯例。每个实例都有一个指向 traits 对象的 “父” 指针,它从 traits 对象那里继承行为,traits 对象可以相互继承,就像子类继承其超类一样。

Self 在数学上比 Smalltalk 更优雅,因为它从一套较小的基本机制中导出了 Smalltalk 的一切。在 Smalltalk 中,类/实例的关系是硬性规定的,而在 Self 中,它是被构建出来的。 但是这种优雅也有其缺点。由于用于构建 Self 中等同于 Smalltalk 类库的对象关系只是一个约定俗成的问题,系统工具不能依赖它们。程序员可以自由地编写不遵循惯例的程序。 我想这就是为什么,Self 没有与 Smalltalk 的修改日志和修改集管理器相对应的工具。如果你在语言中加入了 “类” 的概念,这些工具就更容易编写。

David Ungar 会说,Self 缺乏类,这使得人们可以尝试新的编程模式。 作为一个编程语言的研究者,这是一个完全合理的观点。 但我认为,Self 小组很快就发明了与 Smalltalk 的类相似的程序结构约定,这很有说服力。也许 Self 小组受 Smalltalk 的影响太大,以至于他们没有努力寻找替代方案,但我倾向于认为类是人类思考和组织大型对象集合的一种自然方式。我坦率地承认,我总是把我的 Self 代码(包括 Morphic)设计成类。

Self 是一种美丽的语言–小巧、统一、优雅和强大。然而,在使用 Self 工作了四年之后,我得出结论,Smalltalk 是一种对真正的编程更有用的语言,至少对我来说如此。我似乎是以类的方式思考问题的,所以内置的类很好。在语言中定义了类,也意味着编程环境的工具可以依赖于所有的对象都被组织成类,也意味着当你阅读别人的代码时,你不需要弄清楚一些新的、非类的程序组织。而且,正如我所说的,Smalltalk 可预测的虚拟机速度使它更容易调整程序性能。

SN:我本来想问你是否怀念 Self,但我想我现在对这个问题有了答案。

John:我不太想念 Self。我确实怀念 Self 小组。他们是一群伟大的人。我特别喜欢和 Randy Smith 一起工作。 但作为一个日常工具,我更喜欢 Squeak。

第二期

SN:这把我们带到了 Squeak。在 Sun 之后,你加入了苹果公司。你是否直接加入了 Squeak 的工作?

John:那是一段有趣的时期。我加入苹果公司是为了与 Alan Kay 的小组合作开发教育软件。他们刚刚完成了一个名为 “Constructo” 的儿童编程环境,并开始设计下一个系统。然而,在我们能够建立下一个系统之前,我们需要一种语言来建立它 … Alan 小组的每个人都喜欢 Smalltalk,但似乎没有 Smalltalk 的解决方案。然后我们考虑了 Java,它那时刚刚可以用于 Mac。我们尝试了 Mac 上的 alpha Java JDK,但它有很大的问题,性能也不是很好。我们不喜欢原始的 Java ,它没有反射功能,不喜欢它缺乏交互的开发环境,因为儿童的交互编程环境需要这两种设施。

我们花了 3 到 4 个月的时间来研究各种语言选择,同时讨论下一个儿童编程系统的设计。我们用 Smalltalk、Java 和 Codeworks 写代码,并比较代码和创建过程。我甚至用 Smalltalk 写了一个粗糙的 Java 类(Class)文件阅读器和几个字节码的解释器(不是全套的),以便更好地理解 Java 虚拟机。这个实验为决定用 Smalltalk 编写 Squeak VM 铺平了道路。

当时,Alan 的小组里有 4 个程序员。我、Ted Kaehler、Scott Wallace 和一个名叫 Guha 的出色的人工智能程序员(此后不久,他离开苹果去了 Netscape)。有一天,Ted 说:“我的朋友 Dan Ingalls 目前在 Interval Research 工作,他可能愿意离开 Interval 到苹果来。每个人都同意这将是一件好事。Scott 早先在苹果公司与 Dan 共事过,当然,Dan 和 Ted 都曾在施乐 PARC 的 Alan 小组中一起工作过,开发过 Smalltalk 的原始版本。我没有和 Dan 一起工作过,但我知道他是施乐公司所有 Smalltalk 虚拟机的主要实现者,从 Smalltalk-72 到 Smalltalk-80。我还知道,Dan 一直在 Interval 从事一些涉及 Smalltalk 的神秘项目。Alan 说服了 Dan 来加入我们。1996 年 1 月初,我们投身其中,开始实施 Squeak,尽管我们直到后来才开始叫它 Squeak。

有几件事情帮助我们迅速开始了。首先,我们有苹果公司的 Smalltalk image,它基于苹果公司授权的 Xerox Smalltalk-80 image。我们知道,如果我们能够为它写一个解释器,我们就可以使用这个 image。我们还有苹果公司的 Smalltalk 虚拟机,是用 68000 汇编语言编写的,它仍然可以在当时的 Macintoshes 上运行。尽管我们最终想要一个可移植的虚拟机,但现有的苹果虚拟机给了我们一个启动的方法。

我们还有一个完整的 Smalltalk 虚拟机规范,是用 Smalltalk 编写的,取自 Smalltalk-80 的原版书(《Smalltalk: 语言和它的实现》,即所谓的 “蓝皮书”,现在已经绝版了)。实际上,我们有一份网上的代码,是 Self 小组的 Mario Wolczcko 提供的,他在曼彻斯特大学讲授 Smalltalk 虚拟机课程时,曾将其作为学生的参考。所以 Dan 建议,我们应该把蓝皮书中的虚拟机规范作为 Smalltalk 程序运行,接着自动翻译成 C 语言。之后,一旦虚拟机和 Smalltalk-C 翻译器正确无误,我们就可以把虚拟机的 Smalltalk 代码翻译成 C 语言并进行编译,而编译后的虚拟机将和在 Smalltalk 中的工作完全一样,只是速度会快很多。这是 Dan 的一个很酷的想法,我想他以前从来没有以这种方式建立过虚拟机。我一听就说:“这是唯一的办法” 因为我讨厌用 C 语言编程,更不用说用汇编语言了,所以我自愿写 Smalltalk 到 C 的翻译器。

这个疯狂的计划真的成功了!在短短的 3 个月后,我们就有了 Smalltalk 到 C 的翻译器。仅仅 3 个月后,我们就有了第一个工作的 Squeak 虚拟机,而且在这个过程中,Dan 悄悄地将虚拟机从使用对象表的 16 位对象指针更新为 32 位直接对象指针。

我们的 “回到未来(Back to the Future)” 论文描述了启动的过程。实际上, 仅仅六周后, 我们就让系统的某些部分工作了。我们能够在垃圾收集器工作之前测试虚拟机,方法是给虚拟机一大块内存,让它只是运行字节码,直到内存耗尽。这样,当 Ted 还在写垃圾收集器时,Dan 就能发现并修复字节码引擎中的大部分错误。与此同时,我正在开发 Smalltalk 到 C 语言的翻译器,并在小程序上对其进行测试,以确保它能生成正确的代码。当我们把所有的部件凑在一起时,它真的工作了,令人震惊。

实际上,第一个令人震惊的经历是看着苹果 Smalltalk image 被老式苹果 Smalltalk 解释出来。它慢得令人难以置信,但是看到 Smalltalk 的屏幕被画出来,那是一种了不起的刺激。你会说:“哇!它真的把屏幕画成了灰色!。哇! 有一个浏览器出现了!"。5 分钟后,它就把屏幕画好了,你会说 “哇,它成功了!"。如果你真的有耐心,你可以输入 3+4,然后从菜单中选择 “do it”,Squeak 就会真的打印出结果。(对 Smalltalk 虚拟机实现者而言,当你的虚拟机能够启动一个 Smalltalk image,输入并选择 “3+4”,并打印出结果时,你就可以宣布成功了,因为这个过程测验了大部分重要的系统功能)。

在我们得到基本的虚拟机后,我们又花了 6 个月左右的时间来提高其性能。即使在 C 语言中,第一个虚拟机的性能也相当缓慢。我们做了各种各样的事情,从改进垃圾收集器到仔细调整字节码调度。到了九月,我们有了一个足够快的虚拟机,可以做真正的工作。

10 月,Alan 带着整个小组去了迪斯尼。这引发了一些事情。首先,这个决定鼓励我们把 Squeak 作为开放源码放在网上,这样我们在去迪斯尼的时候可以继续工作。我们不想再从头开始了。诚然,在经历了一次过程之后,我确信我们可以更快地重做一遍,但还是要花上三四个月的时间才能回到我们目前所处的位置,这让人沮丧。幸运的是,我们得到了苹果公司高级技术组负责人 Don Norman 的许可,将 Squeak 作为开源免费软件推出,因为他认为 Smalltalk 在苹果公司没有前途。毫无疑问,苹果公司的这一慷慨举动,部分是出于对 Alan Kay 的尊重。

当然,将 Squeak 作为开放源码推出是整个 Squeak 社区的开始。我们根本没有为它做广告。我们没有向 comp.lang.smalltalk 或任何东西发送信息。仅仅过了六个星期,我们就听说 Ian Puimarta 已经把它移植到了 Unix。大约三周后,Andreas Raab 把它移植到了 Windows。突然间,在我们发布第一份代码的两个月后,Squeak 运行在大多数主要平台上: Linux 和 Unix、Mac 和几种版本的 Windows。人们如此迅速地移植了它,真是令人难以置信。他们能这样做的部分原因是 Smalltalk-to-C 翻译器。Squeak 使用 C 作为一种独立于机器的汇编语言。我非常小心地确保翻译器只生成最通用的、最低标准的 ANSI C,并且不使用在所有平台上无法使用的功能。这确实有助于可移植性。除此之外,要把 Squeak 和操作系统连接起来,所需要写的代码量真不多。有一套代码可以参考,有助于你做下一个。所以 Ian 看了 Mac 的代码,然后 Andreas 看了 Unix 的代码。Andreas 说他的移植比较容易,因为从 Unix 到 Windows 并不难,因为它们在 API 层面上比 Mac 和 Unix 更相似。

SN:在移植过程中,他们有没有和你沟通过?

John:没有,这才是最不可思议的事情!Ian 和 Andreas 都没有和你沟通。伊恩和 Andreas 都没有和我们沟通,直到他们完成工作,然后他们才说 “顺便说一下,我移植了一个 Squeak,在这个网站上。” 这真不可思议。他们没有任何文件,也没有问任何问题,他们就这么做完了。我们后来发现,这两个人很有才干,远不是一般的程序员,但尽管如此,不问任何问题就完成了整个事情,似乎是个奇迹。我们意识到拥有开源软件可能是非常强大的,因为我们甚至没有花 5 分钟时间通过电子邮件回答问题,突然这两个移植的虚拟机就出现了。

我们对自己说:“哇!把代码放在互联网上给别人看是完全值得的,因为回报比投入多,而且协同作用是巨大的”。之后,我们从 Squeak 列表中得到的许多贡献仍是如此,往往是在我们不知道人们正在研究一些很酷的东西的情况下。这方面的一个例子是 MathMorphs 系统,它来自于阿根廷,突然在某个时候出现。它有一种完全不同的与计算机交互的方式,作者从来没有问过一个问题,他们就做完了整个事情。Mark Guzdial 的可插拔网络服务器和 Squeak Wiki-Wiki 也是如此,还有很多其他例子。事实上,你们 “Squeak News” 电子杂志就是其中之一。在我看到第一期之前,我不知道你在用 Squeak 为读者创造一个完整的互动体验。

SN:当你们开始开发时,是否预见到了 Squeak 现在的情况?

John:我们,至少是我,从来没有预料到 Squeak 会发展到现在的程度。当我们刚开始开发时,我们并没有计划把它作为开源产品推出。我们确实计划发布用 Squeak 构建的儿童编程环境,但我们并不打算发布 Squeak 本身。这一举措是由于我们从苹果公司转到迪斯尼公司而被迫采取的,这是一件很幸运的事情。即使在我们把 Squeak 作为开源产品推出之后,我想我们中的任何一个人都没有想到 Squeak 会发展成现在这样强大的用户群。对 Dan 来说,这是一个梦想成真的过程。正如他所说,“我们终于在做我们当初在 Smalltalk 上应该做的事情: 把它交给世界”。Dan 可能已经预见一旦 Squeak 成为开放源码,它就会发展出一批忠实的追随者,但我的眼光还不够远,没有看到这点。


SN:如果我们再回到 Sun 实验室和 Self,我们从那里得到的礼物之一是 Morphic。Morphic 是如何在 Self 中出现的?

John:好问题。Morphic 来自于我对拥有一个真正灵活的用户界面工具包的渴望,和 Randy Smith 对创造一个具体的对象世界的渴望的结合。Randy 曾做过一个项目,他称之为 “替代现实工具包(ARK)"。如果你没有看过 ARK 的录像带,或许有一天会看到它。这是一个有着一套物理规律的世界,世界中的所有物体都服从这些规律。例如,ARK 世界可以模拟重力、动量和摩擦。ARK 的录像带显示了一个模拟弹簧上的有质量的物体的奇妙例子。Randy 添加了一个弹力定律,然后用鼠标拉下物体并放手,使其振荡。物体开始上下跳动。ARK 中的有个东西就像一块黑板–它记录了任何笔在它上面画的路径。Randy 将一支笔连接到弹跳的物体上,然后用鼠标将黑板扔到物体和笔下。在这个例子中,他关闭了摩擦力,因此黑板以恒定的速度平稳地滑行,而笔在黑板表面划出正弦波。因此,他通过移动纸而不是笔创造了一个图形,就像一个条形图记录器。这种图形机制是由模拟世界中物体的物理相互作用创造出来的,它之所以能够实现,是因为物理规律被统一应用于所有物体。每次我看到这句话,我都会想:“哇!这真是一种出乎意料的制作图形的方式”。然而,它的出现是一切都一致和统一的结果。

Randy 想在 Self 用户界面上重现这种 ARK 体验的简单和直接。Dave Ungar 对用户界面的方式也有强烈的意见。他的一个小口号是 “不要有副作用的位图”。他的意思是,他非常讨厌在屏幕上看到一些图形实体,却没有办法通过直接点击来访问该实体。例如,Dave 希望能够进入像菜单一样的东西,并在上面做一些特殊的手势来探索它。你应该能够发现它的内容,它的图形属性,以及实现它的代码。你甚至应该能够修改菜单或者通过直接操作将其拆开。在 Smalltalk 的 MVC 框架中,这很难做到。你使用过 MVC 吗?

SN:是的。

John:所以你知道,在 MVC 中探索一个未知的应用程序的方法之一是点击应用程序窗口,把它带到顶部,然后按中断键,调出一个调试器。调试器会显示正在执行的代码,几乎都是最上面那个窗口的活动窗口的控制器的控制循环。我们想超越这一点,能够把每一个用户界面元素作为一个具体的对象来操作,小到菜单中的项目,大到一个按钮上的标签,甚至可能小到标签中的单个字符。(Dave 认为你甚至应该能够拆开一个单独的字符,例如,从一个小写的 “i” 字符中移除点,但我认为这有点过分了。)

Dave 也是用户界面中无处不在的动画的倡导者,这在当时是一个新的想法。他研究了很多卡通动画,他的一个研究生 Bei-Wei Chang 创造了一个漂亮的 Self 编程环境的动画。所以我们把所有这些想法放在一起,想出了 Morphic。

一旦我们对 Morphic 的设计原则达成一致,设计它其实并不难。Randy 是这些设计原则的维护者。他说过这样的话:“事情必须是直接的(direct)",“事情应该是可分解的(decomposable),这样我们就可以把对象拆开,然后在屏幕上把它们组合起来”。我们努力将所有可以在屏幕上显示的东西 “物化”(即 “使之真实”),甚至包括一些通常无形的东西,如布局规则。对复合对象结构的需要使一切都可以被拆开,这导致了 Morphic submorph 的层次。我们希望单个 Morph 能够控制它们如何处理鼠标点击、显示、拖放、布局等。这个愿望迫使我们在通用的 morph traits 对象(相当于 Morph 类的 Self)中定义处理这些事情的可覆盖行为。与 MVC 不同的是,在任何时候只有一个视图的控制器处于活动状态,我们希望多个 morph 可以同时活动。我们通过集中重绘逻辑并使任何想重绘的 morph 只需提交一个破坏请求来实现这一目的。当然,这不是什么火箭科学;这就是许多窗口系统的工作方式。但是集中显示更新逻辑使我们有能力让 morph 一直处于活动状态,并有动画效果。你可以有滴答作响的时钟、弹跳的原子、爬行的小球,以及随着音乐响起而滚动的钢琴卷,所有这些都是在你的浏览器(browsers)和检查器(inspectors)保持自身更新的情况下进行的。

SN:我正想问你的灵感。所以,这就是你如何想出一个如此不同的用户界面概念的原因!

John:这是 Randy、Dave 和我合作的结果。例如,让所有东西都 “活(alive)” 起来,并且能够持续更新,这是 Morphic 的一个引人注目的地方。从技术上讲,这些特性来自于集中显示的更新机制和 “步进(step)” 机制的结合,后者允许每个 morph 有自己的 “心跳”。但这些只是达到目的的手段;重要的是,我们把 “无处不在的动画” 作为设计目标之一。morphic 的其他方面也是如此。例如,通过直接操作将 morph 拆开的能力,就来自于 “物化一切” 的设计原则。

SN:第一次实现 Morphic 很困难吗?花了多长时间?

John:只花了三个月,并不是很困难。Morphic 是将设计原则合理地直接映射到有效的数据结构和算法上。有一些棘手的部分,比如使布局有效,解决事件通过 submorph 层次的确切方式。但是大部分的实现是非常直接的。

Morphic 的 Self 的一个大的未知数是效率。它的速度必须足够快,才能以合理的帧率制作动画,否则就无法实现我们的目标: 无处不在的动画。Self 在 Solaris 上运行,所以我们用 X-Windows 来显示,以避免对硬件细节的依赖。幸运的是,我们做到了,而且使用 X 有一个可爱的副作用,因为 X-Windows 被设计为通过网络工作,我们实际上可以让 Morphic 屏幕在不同的机器上,而不是在 Self 虚拟机上运行。从这里开始,扩展 Morphic 以处理多个 X-Window 显示器和多个输入流只是一个很短的步骤。这给了我们一个多用户版本的 Morphic,我们称之为 “Kansas”,因为它是一个有几个人的大型共享空间。Squeak 的 “Nebraska” 是 Lex Spoon 编写的 Kansas 的 Squeak 实现,只是在 Squeak 中做起来比较困难,因为 Lex 必须自己实现远程 X 显示机制。

第三期

SN: 将 Morphic 从 Self 移植到 Squeak,Morphic 在 Squeak 中是一个明显的事情吗?

John:我们在 Self 中使用 Morphic 的经验证明,Morphic 灵活而强大。它让我们建立了在其他用户界面框架下难以建立的用户界面。它使模拟和动画变得容易,并鼓励我们建立 “活的(lively)” 界面,其中有许多对象是同时活动的。从一开始我就知道,如果我有机会的话,我就会用 Squeak 重新创建 Morphic。而我得到了这个机会。在我们得到了 Squeak 虚拟机并对它进行了一些调整之后,很明显我们需要一个框架来开始建立用户界面,特别是为儿童编程系统。那是在我们开始建立 Squeak VM 的一年后。1 月份,我开始在 Squeak 中实现 Morphic,到 3 月,它已经相当完整并且运行良好,到 4 月,我们在它的基础上建立了一个儿童编程系统的雏形。对我来说,那是一个相当高效的编程过程。

第二次做同样的事情比较容易,因为你清楚地知道你要去哪里。在 Squeak 中建立 Morphic 的时间没有第一次在 Self 中建立它的时间长。然而,与我从 C 语言到 Smalltalk 的经验不同,在 Squeak 中构建 Morphic 并没有比从 Self 到 Squeak 快五倍;它只是快了两倍。因此,我不认为实现的速度快是因为 Squeak 环境比 Self 环境更有生产力。我认为主要原因是我知道设计是什么,知道它应该如何工作,甚至知道以什么顺序来实现东西。


SN:Morphic 中是否有你希望以不同方式完成的部分,它们在 Squeak 中是否以不同方式完成?

John: 嗯,有一个设计选择让 Randy 和我争论了很久。争论的焦点是每个 morph 是否应该为其 submorphs 定义一个新的坐标系。也就是说,当你在一个 morph 层次中嵌套 morphs 时,每个 morph 的边界框的原点对于它的所有 submorphs 是否应该是 0@0 ?我认为这肯定是正确的,因为要移动一个有几十个或几百个 submorphs 的大型复合 morph,你只需要改变最上面一个 morph 的位置。由于层次结构中所有其他 morphs 的位置都是相对于它们的所有者(owner)而言的,所以你不需要做其他事情。如果每个 morph 的边界都是全局坐标,那么移动复合 morph 就需要更新层次结构中每个 morph 的边界框。我的论点是,移动 morphs 很常见,必须要有足够的效率,所以我们应该使用相对坐标。

Randy 则认为全局坐标系统会更容易被人们理解。你不需要为了计算 morphs 之间的空间关系而在参考系之间进行转换。我们来来回回地讨论,但我们最终在 Self 版本中按照我的方式(相对坐标)做了。然而,Randy 是对的。相对坐标确实变得很复杂,而且很难操作。例如,如果你想知道不同 morph 层次中的两个 submorphs 是否重叠,你必须首先将它们的边界框转换为全局坐标。另一个例子是,当你把鼠标按下的事件顺着 morph 层次传递时,你必须不断地把事件坐标转换为每个 morph 的局部坐标空间,以查看哪个 submorph 被击中。由于 Self 版本中的相对坐标使事情变得不必要的复杂,我决定在 Squeak 实现中使用全局坐标。因此,Morphic 的原始 Squeak 版本有一个单一的全局坐标系统,它简单而美丽。不幸的是,在我建立 Squeak Morphic 之后不久,Dan Ingalls 就实现了 WarpBlt,它支持任意图像的有效缩放和旋转。事实上,我并不确定时间,Dan 可能更早实现了 WarpBlt,但我并没有预料到它会被如何使用。总之,一旦我们有了 WarpBlt,我们就意识到我们可以缩放和旋转任何 morph,于是我们引入了 TransformMorph。不幸的是,TransformMorph 重新引入了多个坐标系。在计算空间关系或将事件向下传递给 morph 层次时,你必须对矩形和点进行所有这些变换。除此之外,使用 TransformMorph 会在 morph 层次中增加一个 morph,而这个 morph 在逻辑上根本就不是 morph 结构的一部分;它只是用来旋转或缩放 morph 的外观。如果缩放和旋转只是每个 morph 的属性,那就更好了。

所以现在回想起来,我觉得我两次都搞错了。如果我知道我们要引入 TransformMorphs,我就会坚持原来的 Self 概念,即每个 morph 定义它自己的坐标系,同时扩展到允许旋转和平移。任何 Morph 都可以被赋予一个任意的变换矩阵,用于平移、旋转和缩放。任何从事三维图形的人一开始都会这样做。

SN:所以你没料到,演示 Morphic 的人所做的第一件事就是将浏览器倾斜!这是一个令人印象深刻的演示,尤其是倾斜的浏览器仍然可以工作!


SN:你如何看待 Morphic 的现状?你认为它是一个完整的作品,还是仍然处于快速发展之中,并且在未来可能会发生变化。如果是这样,在哪些方面?

John:很难说会发生什么。就我而言,虽然 Morphic 仍在发展,但它已经足够好,可以完成很多东西。鉴于我目前在迪斯尼的工作,我个人不会对它做出更多的贡献。我之前建议的每个 morph 都有自己的 transform,Andreas Raab 非常有兴趣推动 Morphic 完成它。他已经使某些东西更加统一了,比如说布局行为。最初,只有几种特殊的 morph 可以进行布局。Andreas 把布局算法推到了 Morph 类中,这样任何一个 morph 都可以使用几种不同的策略来布局它的 submorphs。我想他心里还有几个这样的重构想法。这个特别的想法没什么负面影响。大多数 morph 继续工作,因为它们一直在工作。有一两个选择器改变了名称,所以如果你从旧的图像中导入 morph 代码,你可能需要改变几个选择器的名称,但基本上新的布局功能只是旧的超集。我认为 Andreas 对于重新划分现有的功能还有一些其他的想法。Andreas 说,Morphic 试图同时做两件事:一个图形对象框架和一个应用程序框架。Morphic 并不是真的想成为一个应用框架,但事实证明,通过实现 Morph 的子类来建立许多应用是很方便的。但是 Andreas 希望看到应用逻辑被分离到自己的应用对象中,就像应用逻辑被分离到 MVC 范式中的模型对象中一样。

SN:这也是我的感觉。

John:我同意。有了一个应用程序框架,一个应用程序将有一个 morph 作为视图,但它本身不是一个 morph。这个框架将支持同一应用对象的多个视图。一个简单的例子是,在一个视图中可以有一个数字参数的输入框视图,而另一个视图则以滑块的形式呈现同一个参数。这将是非常有用的,但我不认为我将是推动它的人。

SN:但我相信你仍然会对 Morphic 的发展方向有很大的影响。

John:嗯,作为一个务虚的哲学家,我可能会有影响,但我不会写很多代码,因为我现在正在为迪斯尼做项目。我也怀疑 Morphic 在接下来的几个月里会发生根本性的变化,因为 Squeak 小组的其他成员目前正专注于 Alan Kay 所说的 “终端用户编程” 和 “全(omni)用户编程”。你可能已经听说过 Squeakland.org 网站了。

SN:是的。我访问过并玩过那里的例子,我印象非常深刻。

John:我们正试图教育者和非程序员这些学习者周围建立一个新的社区。我们 Squeakland.org 的主要受众是小学教师和孩子。我们正试图为这个社区建立一个软件环境。这是我们现在的主要目标,我们正在改进 Morphic 和 Squeak 系统以支持这一目标。如果没有必要,我们可能不会对 Morphic 做太大的改变。当然,在我们的小组中,总是有个人灵感的迸发。所以,如果某天晚上 Andreas 突然有灵感要给 Morphic 增加一个应用框架,他可能就会潜心去做,不管这是不是一个官方目标,我们都会为他的做法感到高兴。在 Alan 的小组里,人们有很大的自由来选择自己的目标,这使得我们很难预测到底什么时候会发生。

Andreas 很想做的另一件事是将 Morphic 与三维世界合并,也只有他能做到。他的博士学位是在 3-D 图形方面,他真的很出色。如你所知,Andreas 负责支持 Alice 界面的底层 3-D 系统,他还实现了 Flash 渲染引擎。他绝对是我们的图形大师,所以把 Morphic 带入 3-D 空间将需要他的帮助以使其高效。如果 Morphic 能够存在于一个三维世界中,那就太好了,但是当你近距离观察 morph 时,它们将和目前的二维系统一样有效。然而,退一步,你可能会发现,那些 morph 被贴在一个房间的墙上,有一些门户通向其他房间,而这些房间的墙上都贴着 morph。我们目前认为的项目(projects)可能成为三维世界中的房间。

SN:那将是非常酷的。

John:事实上,我们已经做了一些这方面的实验,而且非常酷。Andreas 做了三维世界,你可以把任何任意的 morph 放在任何墙壁上作为纹理。这甚至适用于有动画的 morph。此外,他将鼠标点击映射回 morph,所以你可以将一个 Squeak 浏览器放在墙上并与之互动。做这个实验并不要求改变 Morphic 本身。因此,我们也许可以通过对当前 Morphic 的简单扩展来实现无处不在的三维,或者我们需要将 Morphic 的渲染结构与一般的三维渲染引擎结合起来。

SN:这是我想问的一个问题,因为在即将出版的 Squeak 书籍中,在你关于 Morphic 的章节里,你提到了这个问题,并告诉大家。“今天的二维 morph 在三维环境中可能会变成一些不寻常的平面物体”。

John:我指的正是我刚才描述的实验。顺便说一句,我们也可以在当前的二维 morph 世界中显示三维物体。你见过我们让 Alice 兔子在浏览器上跑的例子吗?这个例子是在 Alice 工作区。获得这种效果出乎意料的简单;你只需在 3-D 的 Alice 世界中关闭背景,你就可以得到作为独立 morph 的 3-D 对象。它仍然是一个三维物体,所以你可以旋转它,缩放它,或应用其他三维操作。

SN:这是兔子演示的最后一部分,兔子在 2D 表面漂浮着。

John:正是如此。你可以通过改变它的比例和它在前后 Morph 排序中的位置,使兔子看起来向用户移动或远离用户。它可以在变小(较远)时走到其他 morph 的后面,然后在变大(较近)时走到这些 morph 的前面。当你认为你是在一个平面世界中,而突然有一个三维物体开始在其中跑来跑去时,这很令人吃惊。这是另一个例子,说明 Morphic 允许改变你对正常计算机界面的期望。


SN:顺便说一下,每当 “Squeak 是如何被命名的” 这个问题出现时,答案似乎是 “我们永远不会知道”。这个答案还是一样吗?

John:我想这个问题的答案将永远是个谜。事实上,我不能确定,因为 Alan 从未完全解释过这个名字。一种猜测是,这个名字与团队从苹果转到迪斯尼有关系,因为我们在那个时候开始使用 Squeak 这个名字。但也可能有其他答案,比如 “我们想要一个以’S’开头的词,但不是 Smalltalk”,或者 “我们想要一个简短、容易发音、听起来友好、对儿童有吸引力的词”。或者也许是小啮齿动物的声音,正如 Tim 的 Squeak 标志似乎暗示的那样。在任何情况下,人们似乎都喜欢这个名字。

SN:这是个非常可爱的名字。

John:我同意。它听起来没有威胁性。在这个意义上,它就像 Java。我认为 Java 是一种编程语言的好名字。它很友好,如果你像我一样喜欢咖啡,听到这个名字会让你感觉很好。而且,Sun 公司想出了一个可爱的图标,即热气腾腾的咖啡杯。我认为名字比我们大多数工程类型的人愿意承认的更重要。


SN:我很高兴能给你带来启发,因为我一直被你的工作所启发。

John:是的,好的程序员不断交换好的想法。我认为对我的启发是,意识到一个相当简单的底层引擎可以捕捉大部分的导航和互动逻辑。一旦你建立了这个引擎,艺术家们就可以快速创建大量的内容,而不需要太多的程序员参与。我们花了几个月的时间来建立内容。不管怎么说,测试得到了很好的评价。大约有 600 名客人试用了这个设备。他们中的大多数人非常喜欢它,并给了我们非常好的反馈。


John:在测试的第一周,我们更新了无数次软件。能够根据客人的反馈对软件进行修改是非常有价值的。实际上,我们在进行过程中改进了软件,因此能够获得更多有用的数据。Squeak 使之成为可能;在大多数其他语言中,我不敢在这样的测试中增加功能,但 Squeak 允许我们非常积极地进行。

有一天,Squeak 的内置调试设施变得非常有价值。那天,一些设备神秘地发生了故障,而另一些则工作得很好。这个问题没有明显的模式。然而,使用 Squeak 调试器(幸运的是我们没有把它从图像中剥离出来)我们发现所有的故障单元都在读取一个特定的媒体文件时出了错,而且总是在同一个文件位置。我们推断,所有的问题都是由复制主文件集时的一个错误引起的,这个错误在更新所有故障设备的 Compact Flash 卡时都被复制了。我们在启动程序中增加了一些文件完整性检查,改进了我们复制 Compact Flash 卡的过程,并且再也没有出现过问题。如果没有 Squeak 调试器,我们就不知道哪里出了问题,可能会有整整两周被问题所困。


SN:对于那些对 Squeak 或 Smalltalk 一无所知的人,你会如何回答 “什么是 Squeak?” 这个问题?

John:对我来说,一个答案是,Squeak 是在计算机上实现我的想法的最有效工具。我发现它是一种可塑性极强的媒介,可用于构建用户界面、交互式用户体验、模拟,以及用计算机进行几乎所有类型的探索。我的兴趣集中在那些有用户界面组件或媒体组件的东西上。但是,即使对于数据计算,我也发现 Squeak 是我使用过的最自然和最强大的工具。


SN:你见过的对 Squeak 最有趣或创新的使用是什么?

John:有很多。MathMorphs 的东西很有创意。文字转语音的东西让人惊讶和意外,特别是 “唱歌的脸(singing faces)"。许多有用的 Squeak 应用并不令人惊讶,因为我才到最终会有人创造它们。(我对它们十分感激!)例如,许多媒体类型的事物,如 JPEG 和 MPEG。我希望我们最终能够以各种标准格式读取、写入和展示图片、动画和声音。我对 Flash 和 3-D 支持感到惊讶,因为这些东西很难在合理的性能下完成。一些专业程序员的工具,如 Unit 测试框架和异常处理机制也没有让我吃惊,尽管它们很有用,而且实现起来也很费劲。

有一个应用让我很惊讶,我与实现它有一些关系,那就是通过 FFT 和 SpectrumAnalyzerMorph 使用 Squeak 进行实时声音分析。Andreas 最初做了 FFT,作为建立一个插件的例子,Dan 后来实现了声谱,而我把它打包成了一个 morph。对我来说,令人惊讶的是,像 Squeak 这样的解释性语言可以支持像在声音发生时更新频谱的图形显示这样计算密集型的东西。我曾经拿着一台笔记本电脑坐在外面,观看鸟类歌曲的声谱图。以这种方式使用,Squeak 成为探索自然世界的工具。就像望远镜或显微镜一样,它揭示了我们的感官无法观察到的东西。它让你以一种新的方式来看待熟悉的事物,我对此感到很兴奋。令人震惊的是,这其中的每一部分都是用 Squeak 编写和测试的。有一个非常小的代码(FFT 本身的代码)必须要用一种能让它在短时间内完成的方式来编写。

必须以允许它被翻译成 C 语言并编译成插件的方式来编写。但这一过程是相当机械的,而且在 Squeak 中调试了 FFT 代码后,该插件第一次就能工作,所以你永远不必使用 C 语言调试器。

SN:实际上我很惊讶它的易用性。 我正在查看声波图 morph,我只是通过查看代码来剪切和粘贴,我能够制作一个会倾听你的 morph,当你吹口哨时,这个 morph 会根据你的音高选择一个方向来响应吹口哨,开始四处走动。 我花了大约 10 分钟,也许更少。

John:哇! 这很酷! 这肯定是对 Squeak 的一种创新使用!

SN:这都要归功于你的工作。因为当你看它的时候很容易理解,没有什么可迷惑的。


SN:你认为有必要建立一个稳定的 Squeak 吗?

John:当然。由于我最近在迪斯尼的产品开发中使用 Squeak,因此我认为确实需要一个强大的、不经常更改的 Squeak,并且当它确实发生变化时,你知道发生了什么变化以及这些变化可能会如何影响你的代码。在我看来,如果某个组织或公司能够承担起维护稳定的 Squeak 的任务,那将是非常棒的。但我不认为这是 Squeak Central 会做的事情,因为我认为有两个议程是相互矛盾的。一个议程涉及不断创新,尝试新事物,并可能打破旧事物。Alan 称这为 “蓝色平面(blue plane)"。但同样重要的是,打磨、记录和扩展已经存在的东西,这就是稳定的 Squeak 的作用。Alan 把这称为 “粉色平面(pink plane)"。两个平面都很重要,但你不能同时在两个平面上工作。如果你不得不担心保持所有旧事物的工作,那就很难创新。它使你的速度太慢,你会失去灵感的线索。几年来,Squeak Central 一直在试图在蓝色和粉色平面之间妥协。

支持粉色平面的东西是一个沉重的负担,特别是对监督大部分的 Dan 来说。我们有大量的贡献和修复,仅仅测试它们,确保它们不会破坏任何东西,并验证它们与其他贡献的一致性,就是一项全职工作了。这还不包括编写任何文档或发布说明,维护我们的网站…我认为,如果有其他人接管这些职责,对 Squeak Central 以及 Squeak 社区都有好处。这将使 Squeak Central 和 Squeak 社区中具有类似倾向的成员能够专注于蓝色平面。好的蓝色平面想法可能会被纳入稳定的 Squeak 版本,但只有在它们被证实之后。有了一个更稳定的系统,文档就更值得写了,因为它不会那么快过时。例如,就在我为 Squeak 的 “蓝色” 书写了 Morphic 一章后,一些布局协议发生了变化。这一章在书出版前 6 个月就已经过时了! 我怀疑那本书的许多其他章节也是如此。一个稳定的 Squeak 的好处是,你可以写一本关于它的书,它至少可以在一两年内保持最新。

尽管 Squeak 邮件列表中的一些人可能会担心,如果其他团队决定出版稳定版的 Squeak,Squeak Central 会被冒犯,但我认为我们都看到了其优点。特别是 Dan,他已经对分叉稳定版 Squeak 的问题进行了很多思考。当然也有一些潜在的坏处,但我认为 Dan 已经确定,其好处远远超过风险。Dan 一直在寻找方法使两个分叉之间的协同作用最大化。我自己的看法是,有两个分支,一个是稳定的,一个是创新的,这是一个相当好的主意。如果 Squeak 分裂成很多小版本,我们可能会失去社区感,但我认为我们可以处理两个有明确目的的分支。


SN:简单说一下,Squeak 许可证被讨论过几次。你认为 Squeak 是否有可能采用另一种许可证?你认为这有可能吗?

John:我不确定这是否可能,因为苹果的名字在原始版权上。我认为我们必须回到苹果公司,以获得改变许可证的许可。然而,尽管我可能没有听到所有的论点,但我不认为 Squeak 的许可是过分的限制。也许你可以告诉我如何改变它。

SN:一个是字体问题,我个人认为这已经不是一个大问题了,因为更换字体很容易,而且有替代品。另一个是对某些国家的出口限制 这使得 Squeak 许可证与开放系统许可证不兼容。我想这是最大的障碍之一。

John:嗯,我们已经努力避免用任何不能赠送的知识产权来束缚 Squeak。实际上,我们得到了苹果公司的许可,可以在 Squeak 中分发一套字体–那些默认的文本风格的字体。(我认为它来自旧的 Apple Times 位图字体。)但是,正如你所说的,我们总是可以用公共领域的字体和你自己创造的字体来取代所有的字体。实际上,Squeak 携带自己的字体是非常有用的,因为它使 Squeak 独立于底层操作系统的字体。任何对 X-Windows 应用程序进行过编程的人都知道,不同的 X 服务器有不同的字体集,你不能依赖于任何特定的字体可用。另外,由于 Squeak 的字体是内置的,即使你把它移植到没有操作系统的平台上,它的文本引擎也能工作;Squeak 在字体方面是自足的。

关于出口限制,我的理解是,这些限制适用于包括某些类型的加密的软件,如 RSA 公钥加密算法。Squeak 的数字签名代码可能属于出口限制的范围,尽管它实际上并不做一般的加密。然而,大多数应用程序不需要数字签名,所以如果有必要,你可以删除这些类。我相信只做数字签名的软件,特别是基于 DSA 标准的软件,是不受出口管制的。但这可能是一个有争议的问题,因为我相信美国政府大约在一年前放松了对加密软件的出口限制,所以我认为对真正的加密软件来说甚至不会有问题。当然,任何出口基于 Squeak 的产品的人都需要检查当前的法规。

我知道有一些人声称 Squeak 的许可证与其他一些开源许可证 “不兼容”,比如 Gnu 许可证。我一直不明白这有什么大惊小怪的。Squeak 许可证与 Gnu 许可证不同,但我认为这是件好事。例如,Gnu 许可证规定,使用 Gnu 软件创建的软件不能出售,而 Squeak 许可证并不阻止某人出售使用 Squeak 构建的软件,也不要求他们将其应用程序代码开源。如果你是一个软件开发者,这是一件非常好的事情。Squeak 许可证还规定,对 Squeak 虚拟机或核心类的改进必须公开,但不包括运行在其上的应用程序代码。其目的是鼓励对 Squeak 平台的改进反馈到 Squeak 代码库中。大多数开发者应该非常乐意这样做,因为这使得他们自己的代码更容易管理。

我们一直小心翼翼地避免包括任何会使 Squeak 受 Gnu 许可证强制 “开放和自由” 规则影响的代码。例如,我们最近添加了一个 MPEG 插件,它使用了一些最初在 Gnu 许可证下发布的开放源代码,但我们得到了作者的许可,可以根据 Squeak 许可证的条款发布这些代码。


SN:你对 Squeak 在未来 5 年的发展有何看法?

John:我希望我们能看到更多的 Squeak 书籍,我希望看到 Squeak 社区发展成为像 Linux、Perl 和 Python 社区一样的重要力量。我希望这种增长是缓慢而稳定的,有更多的文档和更好的支持,使它变得更加合法(legitimate)。现在迪斯尼内部在 Squeak 方面的困难之一是,虽然 Squeak 被接受用于原型设计,但许多人对使用它来最终部署应用程序持怀疑态度。主要原因是 Squeak 被视为一种不寻常的、晦涩难懂的语言,因此很难找到程序员来维护用 Squeak 编写的应用程序。如果几年后,Squeak 被认为和 Python 或 Perl 一样合法,即使不是 Java 或 C++ 但也不错。我认为,只有当更多的正式组织接管它的支持和文档时,它才会发生。

我期待着看到 Squeak 被用于多媒体、多模式的用户体验中,并有更多的处理能力可用。鉴于 Squeak 现在能做的事情很多,我认为在探索新型媒体和人机交互方面有巨大的机会。


SN:还有最后一个问题。sackbut 的演奏情况如何?

John:我不得不承认,当你四十多岁的时候,学习一种铜管乐器是很难的。小时候可能更容易学习,因为你有更多的自由时间,而且不那么自我批评。 不过,虽然进展不是很快,但我已经取得了足够的进展,继续努力也很有趣。


SN:你对音乐的兴趣反映在 Squeak 中吗?

John:肯定是的。Squeak 中的大部分声音和 MIDI 东西都是我做的,我希望我能在这方面做出更多贡献。我一直在帮助来自阿根廷的 Juan Manuel Vuletich 创建一些采样乐器的紧凑和可自由分发的版本。Squeak 有一个相当不错的采样乐器播放器,但 Squeak 中心以外的大多数人都没有听说过它,因为采样库的许可问题使我们无法分发它们。然而,即使我们可以分发我们目前的库,它们也是如此之大,只有严肃的音乐家或有 DSL 线路的人愿意花时间去下载它们。Juan Manuel 和我希望创建一个更紧凑的声音库,并获得分发它的许可。这将为 Squeak 提供一个很好的管弦乐器的调色板。


SN:John,非常感谢你的时间。

John:不客气。谢谢你给我一个机会来表达我对 Squeak 的想法和意见。


John 有很多 “喜欢的” Squeak 表达方式,这里介绍其中的四个。

第一个表达式在你试图调试或理解某段代码时很有用,当你不想用中断点来中断执行,你可以使用:

self beep (译者注: Beeper beep)

来提供音频验证,以证明某段代码已经到达。不要把它放在一个内部循环中!这可以从一个分叉的、高优先级的进程中使用,在那里,“停止” 可能太具破坏性了。例如,我们可以在一个网络服务器中使用哔哔声来验证是否收到了请求。

哔哔声也可以用来判断一个程序的连续阶段所花费的时间–在各阶段之间放置哔哔声,你可以从哔哔声之间的时间来判断哪个阶段花费的时间最长。显然,这只有在程序的时间尺度合适时才有效。

当你想要更多的信息时,你可以用以下方法显示一个短字符串:

<expression> printString asParagraph display

当然,把字符串写到 Transcript 上也可以,但 Transcript 滚动起来很慢,有时你想看一些频繁更新的值,而又不至于太慢,或者你可能不想用 Transcript 窗口消耗屏幕空间。

该表达式:

<collection> asSet asArray sort

当你想在某个集合中找到唯一的值,并进行排序,以便你能看到分布情况时,这个表达式很有用。例如,你可以将它应用于一个字符串,以快速查看哪些字母出现在该字符串中。

'the quick brown fox jumped over the lazy dog' asSet asArray sort

缺少哪个字母?

最后,在处理音频时,你可以使用:

<expression> viewSamples

来 “看到” 通过播放一些声音而产生的采样。比如说

(SampledSound soundNamed: 'motor') viewSamples