PART 2
This commit is contained in:
Xingyu Wang 2022-06-07 10:37:57 +08:00
parent 059afb872e
commit 6ece58ee8f

View File

@ -46,7 +46,7 @@ Simula I 没有“<ruby>车站<rt>stations</rt></ruby>”和“<ruby>乘客<rt>c
>
> 计算机中的每条记录都必须属于数量有限但互不重合的记录类型中的一类;程序员可以根据需要声明尽可能多的记录类型,并借助标识符为各个类型命名。记录类型的命名可能是普通词汇,比如“牛”、“桌子”以及“房子”,同时,归属于这些类型的记录分别代表一头“牛”、一张“桌子”以及一座“房子”。
霍尔在这片论文中并未提到子类的概念,但是达尔由衷地感谢霍尔,是他引导了两人发现了这一概念。[^9] 尼加德和达尔注意到 Simula I 的过程通常具有相同的元素,所以引入父类来执行共同元素就会非常方便。这也强化了“过程”这一概念本身可以用作父类的可能性,也就是说,并非每种类型都必须用作只有单个操作规程的过程。这就是 Simula 语言迈向通用化的第二次飞跃此时Simula 67 真正成为了通用编程语言。正是如此变化让尼加德和达尔短暂地萌生了给 Simula 改名的想法,想让人们意识到 Simula 不仅仅可以用作模拟。[10][13] 不过,考虑到 “Simula”这个名字的知名度已经很高了另取名字恐怕会带来不小的麻烦。
霍尔在这片论文中并未提到子类的概念,但是达尔由衷地感谢霍尔,是他引导了两人发现了这一概念。[^9] 尼加德和达尔注意到 Simula I 的过程通常具有相同的元素,所以引入父类来执行共同元素就会非常方便。这也强化了“过程”这一概念本身可以用作父类的可能性,也就是说,并非每种类型都必须用作只有单个操作规程的过程。这就是 Simula 语言迈向通用化的第二次飞跃此时Simula 67 真正成为了通用编程语言。正是如此变化让尼加德和达尔短暂地萌生了给 Simula 改名的想法,想让人们意识到 Simula 不仅仅可以用作模拟。[^10] 不过,考虑到 “Simula”这个名字的知名度已经很高了另取名字恐怕会带来不小的麻烦。
1967 年,尼加德和达尔与 <ruby>控制数据公司<rt>Control Data</rt></ruby> 签署协议着手开发Simula 的新版本Simula 67。同年六月份的一场会议中来自控制数据公司、奥斯陆大学以及挪威计算机中心的代表与尼加德和达尔两人会面意在为这门新语言制定标准与规范。最终会议发布了 [《Simula 67 通用基础语言》][14],确定了该语言的发展方向。
@ -59,106 +59,95 @@ Simula 67 编译器的开发由若干家供应商负责。<ruby>Simula 用户协
cim 编译器遵循 1986 年修订后的 Simula 标准,基本上也就是 Simula 67 版本。你可以用它编写类、子类以及虚拟方法,就像是在使用 Simula 67 一样。所以,用 Python 或 Ruby 轻松写出短短几行面向对象的程序,你照样也可以用 cim 写出来:
```
! dogs.sim ;
! dogs.sim ;
Begin
Class Dog;
! The cim compiler requires virtual procedures to be fully specified ;
Virtual: Procedure bark Is Procedure bark;;
Begin
Class Dog;
! The cim compiler requires virtual procedures to be fully specified ;
Virtual: Procedure bark Is Procedure bark;;
Procedure bark;
Begin
Procedure bark;
Begin
OutText("Woof!");
OutImage; ! Outputs a newline ;
End;
OutText("Woof!");
OutImage; ! Outputs a newline ;
End;
Dog Class Chihuahua; ! Chihuahua is "prefixed" by Dog ;
Begin
Procedure bark;
Begin
OutText("Yap yap yap yap yap yap");
OutImage;
End;
End;
Ref (Dog) d;
d :- new Chihuahua; ! :- is the reference assignment operator ;
d.bark;
End;
Dog Class Chihuahua; ! Chihuahua is "prefixed" by Dog ;
Begin
Procedure bark;
Begin
OutText("Yap yap yap yap yap yap");
OutImage;
End;
End;
Ref (Dog) d;
d :- new Chihuahua; ! :- is the reference assignment operator ;
d.bark;
End;
```
你可以按照下面代码执行程序的编译与运行:
```
$ cim dogs.sim
Compiling dogs.sim:
gcc -g -O2 -c dogs.c
gcc -g -O2 -o dogs dogs.o -L/usr/local/lib -lcim
$ ./dogs
Yap yap yap yap yap yap
$ cim dogs.sim
Compiling dogs.sim:
gcc -g -O2 -c dogs.c
gcc -g -O2 -o dogs dogs.o -L/usr/local/lib -lcim
$ ./dogs
Yap yap yap yap yap yap
```
你可能会注意到cim 先将 Simula 语言编译为 C 语言,然后传递给 C 语言编译器。)
这就是 1967 年的面向对象程序设计,除了语法方面的不同,和 2019 年的面向对象程序设计并无本质区别。如果你同意我的这一观点,你也就懂得了为什么人们会认为 Simula 在历史上是那么的重要。
不过,我更想介绍一下 Simula I 的核心概念——过程模型。Simula 67保留了过程模型,不过只有在使用 <ruby>`过程`类<rt>Process class</rt></ruby><ruby>`模拟`块<rt>Simulation block</rt></ruby> 的时候才能调用。
不过,我更想介绍一下 Simula I 的核心概念——过程模型。Simula 67 保留了过程模型,不过只有在使用 `Process` 类 和 `Simulation` 的时候才能调用。
为了表现出过程是如何运行的,我决定对下述场景进行模拟。想象一下,有这么一座村庄,村庄的旁边有条小河边,小河里有很多的鱼。但是,村里的村民却只有一条鱼竿。有些村民胃口很大,每隔一个小时就饿了。他们一饿,就会拿着鱼竿去钓鱼。如果一位村民正在等鱼竿,另一位村民自然也用不了。这样一来,村民们就会为了钓鱼排起长长的队伍。假如村民要等五、六分钟才能钓到一条鱼,那么这样等下去,村民们的身体状况就会变得越来越差。再假如,一位村民已经到了骨瘦如柴的地步,最后他可能就会饿死。
为了表现出过程是如何运行的,我决定模拟下述场景。想象一下,有这么一座住满了村民的村庄,村庄的旁边有条小河边,小河里有很多的鱼。但是,村里的村民却只有一条鱼竿。村民胃口很大,每隔一个小时就饿了。他们一饿,就会拿着鱼竿去钓鱼。如果一位村民正在等鱼竿,另一位村民自然也用不了。这样一来,村民们就会为了钓鱼排起长长的队伍。假如村民要等五、六分钟才能钓到一条鱼,那么这样等下去,村民们的身体状况就会变得越来越差。再假如,一位村民已经到了骨瘦如柴的地步,最后他可能就会饿死。
这个例子多少有些奇怪,虽然我也不说不出来为什么我脑袋里最先想到的是这样的故事,但是就这样吧。我们把村民们当作 Simula 的各个过程,观察在一天的模拟时间内有着四个村民的村庄里会发生什么。
这个例子多少有些奇怪,虽然我也不说不出来为什么我脑袋里最先想到的是这样的故事,但是就这样吧。我们把村民们当作 Simula 的各个过程,观察在有着四个村民的村庄里,一天的模拟时间内会发生什么。
完整程序可以通过此处 [GitHub Gist][17] 的链接获取。
我把输出结果的最后几行放在了下面。我们来看看一天里最后几个小时发生了什么:
```
1299.45: 王五饿了,要了鱼竿。
1299.45: 王五正在钓鱼。
1311.39: 王五钓到了一条鱼。
1328.96: 赵六饿了,要了鱼竿。
1328.96: 赵六正在钓鱼。
1331.25: 李四饿了,要了鱼竿。
1340.44: 赵六钓到了一条鱼。
1340.44: 李四饿着肚子等着鱼竿。
1340.44: 李四在等鱼竿的时候饿死了。
1369.21: 王五饿了,要了鱼竿。
1369.21: 王五正在钓鱼。
1379.33: 王五钓到了一条鱼。
1409.59: 赵六饿了,要了鱼竿。
1409.59: 赵六正在钓鱼。
1419.98: 赵六钓到了一条鱼。
1427.53: 王五饿了,要了鱼竿。
1427.53: 王五正在钓鱼。
1437.52: 王五钓到了一条鱼。
1299.45: 王五饿了,要了鱼竿。
1299.45: 王五正在钓鱼。
1311.39: 王五钓到了一条鱼。
1328.96: 赵六饿了,要了鱼竿。
1328.96: 赵六正在钓鱼。
1331.25: 李四饿了,要了鱼竿。
1340.44: 赵六钓到了一条鱼。
1340.44: 李四饿着肚子等着鱼竿。
1340.44: 李四在等鱼竿的时候饿死了。
1369.21: 王五饿了,要了鱼竿。
1369.21: 王五正在钓鱼。
1379.33: 王五钓到了一条鱼。
1409.59: 赵六饿了,要了鱼竿。
1409.59: 赵六正在钓鱼。
1419.98: 赵六钓到了一条鱼。
1427.53: 王五饿了,要了鱼竿。
1427.53: 王五正在钓鱼。
1437.52: 王五钓到了一条鱼。
```
李四最后饿死了但是他比张三要长寿因为张三还没到上午7点就死了。赵六和王五现在一定过得很好因为需要鱼竿的就只剩下他们两个了。
可怜的李四最后饿死了,但是他比张三要长寿,因为张三还没到上午 7 点就饿死了。赵六和王五现在一定过得很好,因为需要鱼竿的就只剩下他们两个了。
这里,我要说明,这个程序最重要的部分只是创建了过程(四个村民),并让它们运行下去。各个过程操作对象(鱼竿)的方式与我们今天对对象的操作方式相同。但是程序的主体部分并没有调用任何方法,也没有修改过程的任何属性。过程本身具有内部状态,但是这种内部状态的改变只有过程自身才能做到。
在这个程序中,仍然有一些字段发生了变化,这类程序设计无法直接解决纯函数式编程所能解决的问题。但是正如克罗达尔所注意到的那样,“这一机制引导进行模拟的程序员为底层系统建立模型,生成一系列过程,每个过程表示了系统内的自然事件顺序。”[12][18] 先把影响其他对象的nouns 对象和 actors 对象放在一边,我们先来想一想运行中的过程。我们可以将程序的总控制权交予 Simula 的事件通知系统,克罗达尔称其为 <ruby>时间管理器<rt>time manager</rt><ruby>。因此,尽管我们仍然在适当地改变过程,但是没有任何过程可以假设其他过程的状态。每个过程只能间接地与其他过程进行交互。
在这个程序中,仍然有一些字段发生了变化,这类程序设计无法直接解决纯函数式编程所能解决的问题。但是正如克罗达尔所注意到的那样,“这一机制引导进行模拟的程序员为底层系统建立模型,生成一系列过程,每个过程表示了系统内的自然事件顺序。”[^12] 我们不是主要从名词或行动者(对其他对象做事的对象)的角度来思考正在进行的过程。我们可以将程序的总控制权交予 Simula 的事件通知系统,克罗达尔称其为 <ruby>时间管理器<rt>time manager</rt><ruby>。因此,尽管我们仍然在适当地改变过程,但是没有任何过程可以假设其他过程的状态。每个过程只能间接地与其他过程进行交互。
这种模式如何用以编写编译器、HTTP 服务器以及其他内容,尚且无法确定。(另外,如果你在 Unity 游戏引擎上编写过游戏,就会发现两者十分相似。)不得不承认,尽管我们有了“时间管理器”,我们还是无法实现希基在解释有必要搞清楚程序中的时间概念时所提出的设想。(我认为,希基想要的类似于 [<ruby>阿达·洛芙莱斯<rt>Ada Lovelace</rt></ruby> 用于区分一个变量随时间变化产生的不同数值的上标符号][19]。尽管如此我们可以发现面向对象程序设计前期的设计方式与我们今天所习惯的面向对象程序设计并非完全一致我觉得这一点很有意思。我们可能会理所当然地认为面向对象程序设计的方式千篇一律即程序就是对事件的一长串记录某个对象以特定顺序对其他对象产生作用。Simula I 的过程系统表明,面向对象程序设计的方式不止一种。仔细想一下,函数式语言或许是更好的设计方式,但是 Simula I 的发展告诉我们,现代面向对象程序设计被取代也很正常。
这种模式如何用以编写编译器、HTTP 服务器以及其他内容,尚且无法确定。(另外,如果你在 Unity 游戏引擎上编写过游戏,就会发现两者十分相似。)我也承认,尽管我们有了“时间管理器”,但这可能并不完全是希基的意思,他说我们在程序中需要一个明确的时间概念。(我认为,希基想要的类似于 [<ruby>阿达·洛芙莱斯<rt>Ada Lovelace</rt></ruby> 用于区分一个变量随时间变化产生的不同数值的上标符号][19]。尽管如此我们可以发现面向对象程序设计前期的设计方式与我们今天所习惯的面向对象程序设计并非完全一致我觉得这一点很有意思。我们可能会理所当然地认为面向对象程序设计的方式千篇一律即程序就是对事件的一长串记录某个对象以特定顺序对其他对象产生作用。Simula I 的过程系统表明,面向对象程序设计的方式不止一种。仔细想一下,函数式语言或许是更好的设计方式,但是 Simula I 的发展告诉我们,现代面向对象程序设计被取代也很正常。
_如果你喜欢这篇文章欢迎关注推特 [@TwoBitHistory][20],也可通过 [RSS feed][21] 订阅获取最新文章每四周更新一篇。_
_TwoBitHistory 文章回顾……_
> 嗨,大家好!很遗憾,我最近没有时间写新文章,但是我刚刚更新了我的 RSS 记录,整合了目前为止我私下对一些关键人物的采访,比如 Ramanathan Guha 和 Dan Libby。<https://t.co/WYPhvpTGqB>
>
> — TwoBitHistory (@TwoBitHistory) [December 18, 2018][22]
[^1]: Jan Rune Holmevik, “The History of Simula,” accessed January 31, 2019, <http://campus.hesge.ch/daehne/2004-2005/langages/simula.htm>. 
[^2]: Ole-Johan Dahl and Kristen Nygaard, “SIMULA—An ALGOL-Based Simulation Langauge,” Communications of the ACM 9, no. 9 (September 1966): 671, accessed January 31, 2019, [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.95.384&amp;rep=rep1&amp;type=pdf][24]. 
[^3]: Stein Krogdahl, “The Birth of Simula,” 2, accessed January 31, 2019, <http://heim.ifi.uio.no/~steinkr/papers/HiNC1-webversion-simula.pdf>. 
[^4]: ibid. 
[^4]: 出处同上。 
[^5]: Ole-Johan Dahl and Kristen Nygaard, “The Development of the Simula Languages,” ACM SIGPLAN Notices 13, no. 8 (August 1978): 248, accessed January 31, 2019, <https://hannemyr.com/cache/knojd_acm78.pdf>. 
[^6]: Dahl and Nygaard (1966), 676. 
[^7]: Dahl and Nygaard (1978), 257.