面向?qū)ο蠛秃瘮?shù)式編程詳談
Alan Kay是當(dāng)今世界計算機(jī)領(lǐng)域最重要的人物之一,他因面向?qū)ο?a target='_blank' class='arckwlink_none'>編程方面的貢獻(xiàn)和設(shè)計Smalltalk語言獲得了2003年圖靈獎。同時,他也是個人計算機(jī)(PC),圖形用戶界面(GUI)的先驅(qū)。今天我們使用的C/C++或Java語言都或多或少從Smalltalk汲取過養(yǎng)分。
他所研究的領(lǐng)域遠(yuǎn)超計算機(jī),總能從更高層次看問題,他的想法又總是很宏大,也許你一開始并不理解他在說什么,但回頭看總會有新收獲,他的每篇文章和每個演講都令人深受啟發(fā)。
他講話風(fēng)趣且深刻,似乎隨口說的一句話就能放進(jìn)名言庫里,你肯定聽過這句話:“預(yù)測未來的最好方法就是創(chuàng)造未來——The best way to predict future is to invent it”。
理解“對象”的歷程
關(guān)于“對象”(object)的理解,我經(jīng)歷了幾個不同階段。
第一階段是50年前,在ARPA研究生院的開始幾周,我的幾種專業(yè)背景,數(shù)學(xué)、分子生物學(xué)、系統(tǒng)和程序設(shè)計等,與Sketchpad、Simula和ARPAnet這些東西產(chǎn)生了碰撞。這使我觀察到,既然一臺計算機(jī)可以分解成多臺虛擬計算機(jī),相互間持續(xù)通信,于是你便可以:
完全保留表達(dá)式的威力;
隨時為任何可建模的東西建模;
無限地伸縮,而不限于已有的分解計算機(jī)的方式。
我喜歡這些。分時運(yùn)行的“進(jìn)程”已是這種虛擬機(jī)的體現(xiàn),但因為開銷太大還缺少實際的通用性(那就尋找方法消除這些開銷……)。
盡管可以為任何事物(包括數(shù)據(jù)結(jié)構(gòu))建模,對我來說這還遠(yuǎn)遠(yuǎn)不夠。真正了不起的是為極端的可伸縮性需求提供松耦合的封裝和消息機(jī)制(以一種類似生物和生態(tài)系統(tǒng)的方式)。
第二個階段包括在“Lisp世界”中摻入Lisp本身,McCarthy關(guān)于機(jī)器人和時態(tài)邏輯的思想,在ARPA(尤其是在MIT)進(jìn)行的AI工作,以及Carl Hewitt的PLANNER語言。有一種思想:對象可以像服務(wù)器一樣,且可以是面向目標(biāo)的,使用PLANNER類型的目標(biāo)作為接口語言。
第三階段是Parc的一系列Smalltalks,試圖在Parc的Alto系統(tǒng)(128K內(nèi)存,一半用于顯示設(shè)備)所能實現(xiàn)的和未來必然需要的功能之間尋找一種實用的平衡。這項工作是與Dan Ingalls和組里其他一些天才的同事合作完成的。理想主義的小宇宙一直讓我不爽,但從實用角度結(jié)果不錯。
第四階段(也是在Parc)是重新深入探討時態(tài)邏輯和“世界線”(world-line)思想(后面細(xì)說)。
第五階段是再次嚴(yán)肅地思考可伸縮性并重新審視“協(xié)作語言”(比如Gelernter的Linda),將它們看作以通用的發(fā)布和描述方式進(jìn)行描述匹配,從而實現(xiàn)松耦合的一種方法。我仍然喜歡這種思想,并希望看它發(fā)展到對象可以真正“協(xié)商意義”的程度。
McCarthy的時態(tài)邏輯:“時間中的真正函數(shù)”
我對這一切的思考方式大部分都可追溯到上世紀(jì)50年代的John McCarthy。John是一位出色的數(shù)學(xué)家和邏輯學(xué)家。他希望自己能做嚴(yán)密一致的邏輯推理——同時希望他的程序和機(jī)器人也能做到。機(jī)器人是個關(guān)鍵:因為他想讓機(jī)器人有時在費(fèi)城,有時在紐約。按常規(guī)邏輯這會有問題,然而John針對“事實”成立時能表現(xiàn)“時幀”(time frame)的所有事實額外添加了一個參數(shù),從而修正了這一問題。這就創(chuàng)建了一種簡單的時態(tài)邏輯,將“事實集合”顯現(xiàn)為世界線的層層堆棧。
這很容易泛化為“變量”、“數(shù)據(jù)”、“對象”……的世界線。從個體角度來看,值的“歷史”替換了“值”,從系統(tǒng)角度來看,整個系統(tǒng)被表示為每當(dāng)系統(tǒng)處于兩次計算之間時它所處的穩(wěn)定狀態(tài)。Simula后來采用了這一思想的一個弱化但卻實用的版本。
應(yīng)當(dāng)提一下Christopher Strachey(編者注:1916年-1965年,生于英國英格蘭倫敦漢普斯敦,計算機(jī)科學(xué)家。他是指稱語義最早的提出者之一,也是編程語言設(shè)計的先驅(qū),發(fā)展了編程語言CPL)——Lisp和McCarthy的偉大粉絲,他認(rèn)識到通過始終使用(來自前一時幀的)舊值來產(chǎn)生新值并安裝在新的時幀中,很多種編程模型都可以統(tǒng)一起來且更加安全。認(rèn)識到這一點(diǎn)是因為他首先觀察到Lisp中“尾遞歸”是多么干凈利落,然后又看到這樣的尾遞歸寫成某種循環(huán)的形式更易理解:循環(huán)中包含類似賦值的語句,其中右邊從時間t中取值,被賦值的變量則存在于時間t+1中(且這樣的賦值只允許一次)。這就統(tǒng)一了函數(shù)式編程和同時模擬時間和狀態(tài)的“類命令式”編程。
也要提一下Ashcroft和Wadge設(shè)計的Lucid語言(編者注:一種數(shù)據(jù)流語言,用于非馮模型編程),該語言擴(kuò)展了Strachey的許多思想。
另外,數(shù)據(jù)庫中的“原子事務(wù)”也值得一看,思想很類似,只是粒度更粗——從來沒有破壞什么,也不用競爭條件,新的版本以一種非破壞性的方式創(chuàng)建出來。其中有了版本的歷史。
“時間是個好主意”,這是關(guān)鍵的一點(diǎn)——我們想要它,想用安全、合理的方式處理它——而這些方式中絕大部分(如果不是全部的話)都可以是處于穩(wěn)定世界線狀態(tài)序列之間的純函數(shù)式事務(wù)。
“剛剛計算來的穩(wěn)定狀態(tài)”非常有用。它再也不會改變——因此它代表了系統(tǒng)模擬中的一個“版本”——且可以在產(chǎn)生下一個穩(wěn)定狀態(tài)的函數(shù)式轉(zhuǎn)換中充當(dāng)源數(shù)值。它還可以充當(dāng)數(shù)據(jù)源,為那一刻的世界創(chuàng)建視覺效果。歷史信息則可用于調(diào)試、撤消、回滾等需要。
在這種模型中,“穩(wěn)定狀態(tài)之間時間并不存在”:“時鐘”只在新狀態(tài)完成時走表。就程序而言,CPU本身并不充當(dāng)時鐘。對于具有內(nèi)在、干凈時間模型的確定性關(guān)系,這種思想帶來一種非常簡易的處理方式。
出于很多理由(但沒有一個好的)這種維持安全的方法在上世紀(jì)60年代輸給了在命令式編程中使用競爭條件,然后再通過可怕的、可能導(dǎo)致死鎖的信號量來保護(hù)它們的做法。
某些時候,任何了解Lisp且對對象間的消息傳遞感興趣的人都必然“運(yùn)用”并注意到一種對象(一個lambda的“東西”,可以是一個閉包)可以捆綁到一組參數(shù)上(看起來有點(diǎn)像消息)。如果一個人知道Lisp 1.5是如何基于新式的延遲綁定參數(shù)求值來實現(xiàn)的,理解還會更深入。這里指的是FEXPR,而不是EXPR——未求值的表達(dá)式可作為參數(shù)傳遞,之后再求值。這使得不太優(yōu)雅的“特殊形式”四處充斥,它們本來可以寫成漂亮的惰式函數(shù)。
使用前述的時態(tài)建模,可以松掉“求值-應(yīng)用”的耦合,通過安全的消息傳遞來獲得時間層之間的函數(shù)式關(guān)系。于是,由于我一直喜歡從系統(tǒng)模擬的視角看待計算,我便把“對象”和“函數(shù)”看作兩種互補(bǔ)的思想,它們并不沖突。
術(shù)語一旦成為宗教或更加嚴(yán)格的選擇與風(fēng)格,便會失去它們的意義。這里說的自然是“面向?qū)ο蟆焙汀昂瘮?shù)式編程”這兩個術(shù)語。我不會將“函數(shù)式編程”的一般概念跟任何特定語言等同起來。我堅持認(rèn)為“函數(shù)思想”是一種可靠的映射。類似的,我也不會把“面向?qū)ο蟆钡囊话愀拍钔魏翁囟ㄕZ言等同起來。如今這兩個術(shù)語被“殖民”了,意思也變了。
還有一個大問題是“對象”和“抽象數(shù)據(jù)類型”的混淆,以及對“數(shù)據(jù)”和“賦值語句”的固執(zhí)。如果真正強(qiáng)化了封裝,對象就可以根據(jù)需要處理設(shè)計參數(shù)(包括保存歷史信息)。
分布式環(huán)境中的對象
有朋友問我現(xiàn)在如何理解分布式環(huán)境中的對象和系統(tǒng)模擬的,是否依然認(rèn)為有可能構(gòu)造一種系統(tǒng),它既有互聯(lián)網(wǎng)那樣可以有機(jī)增長的規(guī)模,又有類似于虛擬時間的良好的、可預(yù)測的語義?
好問題。這里面有好幾組問題及其權(quán)衡關(guān)系。二十世紀(jì)70年代Dave Reed(編者注:美國計算機(jī)科學(xué)家,UDP協(xié)議設(shè)計者)最初思考的是面向整個互聯(lián)網(wǎng)的操作系統(tǒng)應(yīng)具有什么樣子。在他提出的許多有趣想法中,其中之一是通過由虛擬時間(pseudo-time)組織起來的分布式克隆計算來處理長延時和海量潛在用戶的問題,然后慢速的互聯(lián)網(wǎng)僅用于輸入和偏差同步。這就是我們本世紀(jì)00年代早期在Croquet中實現(xiàn)的東西,那時互聯(lián)網(wǎng)上一次典型的、還算不錯的ping來回大約80到100毫秒。這已經(jīng)好到可以無需任何服務(wù)器而創(chuàng)建《魔獸世界》這樣的大規(guī)模并行游戲(甚至飛行仿真游戲)了,只要有玩家正在用著的那些機(jī)器就夠了(分布式)。后來的版本做得更多更全面。
插一句,去掉實時圖形和交互的Croquet便自動提供了一種分布式的面向?qū)ο髷?shù)據(jù)庫。虛擬時間是背后的大理念,保護(hù)著數(shù)據(jù)庫中的分布式原子事務(wù)。
而且多年來人們一直在討論。它能否實現(xiàn)?需要在哪些領(lǐng)域做多少工作?等等。
我們在Parc做過的與對象有關(guān)的工作就是ARPA/Parc社區(qū)中發(fā)生的網(wǎng)絡(luò)思維的一部分,它最終產(chǎn)生了思考更高層網(wǎng)絡(luò)實體的傾向。“網(wǎng)絡(luò)層實體”的一個相當(dāng)不錯的、過渡性的實現(xiàn)是Gerry Popek在Parc花了一年時間思考“網(wǎng)終系統(tǒng)應(yīng)有的樣子”之后,和他在UCLA的團(tuán)隊一起完成的LOCUS系統(tǒng)。那是建立在異構(gòu)機(jī)器類型之上的一種遷移式的負(fù)載平衡思想,與虛擬時間概念形成高度的互補(bǔ)。
我希望看到富有才華的團(tuán)隊把第二個問題再過一篇。對可伸縮規(guī)模的適應(yīng)性很難事先預(yù)測,最好實際去實現(xiàn)它。對于虛擬時間,如果你了解它卻不使用它,任何情況下我都覺得有點(diǎn)瘋狂,而如果不了解它,那就有點(diǎn)業(yè)余了。在這兩者之間,則是以各種“不二法門”為特征的宗教(而這跟任何科學(xué)都背道而馳)。
非常好我支持^.^
(0) 0%
不好我反對
(0) 0%