我的 Lisp 經驗與 GNU Emacs 的開發
Richard Stallman 在 2002 年 10 月 28 日國際 Lisp 會議上的演講稿。
由於我通常的演講都與 Lisp 無關,所以沒有一個適合今天的場合。所以我必須即興發揮。由於我在職業生涯中做了很多與 Lisp 相關的事情,我應該能夠說出一些有趣的事情。
我第一次接觸 Lisp 是在高中時閱讀 Lisp 1.5 手冊。那時我被一種電腦語言可以是那樣的想法震驚了。我第一次有機會使用 Lisp 是在我哈佛大學一年級的時候,我為 PDP-11 寫了一個 Lisp 直譯器。那是一台非常小的機器——它有大約 8k 的記憶體——我設法用一千條指令寫出了直譯器。這為我提供了一些存放少量資料的空間。那是在我看到真正的軟體是什麼樣子,以及它如何完成真正的系統工作之前。
當我開始在麻省理工學院工作後,我開始與 JonL White 一起從事真正的 Lisp 實作。我被人工智慧實驗室聘用,不是 JonL 聘用的,而是 Russ Noftsker 聘用的,考慮到後來發生的事情,這真是諷刺——他一定非常後悔那天。
在 1970 年代,在我的生活因可怕的事件而政治化之前,我只是不斷地為各種程式製作一個又一個擴展,其中大多數與 Lisp 無關。但是,在這過程中,我寫了一個文字編輯器 Emacs。關於 Emacs 有趣的想法是,它有一種程式語言,使用者的編輯命令將用那種直譯式程式語言編寫,這樣你就可以在編輯時將新命令載入到你的編輯器中。你可以編輯你正在使用的程式,然後繼續用它們進行編輯。所以,我們有一個系統,它除了程式設計之外還可以用於其他事情,而且你可以在使用它的同時對它進行程式設計。我不知道它是否是第一個這樣的系統,但它肯定是第一個這樣的編輯器。
建立龐大、複雜的程式以用於自己的編輯,然後與其他人交換它們的精神,助長了我們當時在人工智慧實驗室擁有的自由合作精神。想法是你可以將你擁有的任何程式的副本給任何想要副本的人。我們與任何想使用它們的人共享程式,它們是人類知識。因此,即使沒有有組織的政治思想將我們共享軟體的方式與 Emacs 的設計聯繫起來,我仍然相信它們之間存在聯繫,也許是一種無意識的聯繫。我認為,我們在人工智慧實驗室的生活方式的本質導致了 Emacs 的誕生,並使其成為今天的樣子。
最初的 Emacs 沒有 Lisp。底層語言,非直譯式語言——是 PDP-10 組合語言。我們用它寫的直譯器實際上不是為 Emacs 寫的,而是為TECO寫的。它是我們的文字編輯器,並且是一種極其醜陋的程式語言,簡直醜陋至極。原因是它不是被設計成一種程式語言,而是被設計成一種編輯器和命令語言。有一些命令,例如 5l
,意思是 移動五行
,或者 i
,然後是一個字串,然後是一個 ESC 鍵,以插入該字串。你會輸入一個字串,它是一系列命令,被稱為命令字串。你會用 ESC ESC 結束它,它就會被執行。
嗯,人們希望用程式設計功能擴展這種語言,所以他們添加了一些。例如,最早的功能之一是循環結構,它是 < >
。你會把這些東西放在周圍,它就會循環。還有其他神秘的命令可以用於有條件地退出循環。為了製作 Emacs,我們 [1] 添加了具有名稱的子常式的功能。在此之前,它有點像 Basic,子常式只能使用單個字母作為它們的名稱。這很難用來編寫大型程式,所以我們添加了程式碼,以便它們可以有更長的名稱。實際上,有一些相當複雜的功能;我認為 Lisp 從 TECO 那裡獲得了它的 unwind-protect 功能。
我們開始加入相當複雜的功能,所有這些都帶有你所能想到的最醜陋的語法,但它奏效了——人們仍然能夠用它編寫大型程式。顯而易見的教訓是,像 TECO 這樣的語言,它不是被設計成一種程式語言,是一種錯誤的做法。你用來構建擴展的語言不應該被事後諸葛亮地認為是一種程式語言;它應該被設計成一種程式語言。事實上,我們發現用於此目的的最佳程式語言是 Lisp。
是 Bernie Greenberg 發現了這一點 [2]。他用 Multics MacLisp 寫了一個 Emacs 版本,他用 MacLisp 以直接的方式編寫了他的命令。編輯器本身完全是用 Lisp 寫成的。Multics Emacs 被證明是非常成功的——程式設計新的編輯命令非常方便,以至於他辦公室的秘書們也開始學習如何使用它。他們使用了一本別人寫的手冊,該手冊展示了如何擴展 Emacs,但沒有說這是一種程式設計。因此,秘書們,她們認為自己不會程式設計,並沒有被嚇跑。她們閱讀了手冊,發現她們可以做有用的事情,並且她們學會了程式設計。
因此,Bernie 看到一個應用程式——一個為你做一些有用的事情的程式——它內部有 Lisp,你可以通過重寫 Lisp 程式來擴展它,實際上是一種非常好的讓人們學習程式設計的方式。它讓他們有機會編寫對他們有用的小型程式,這在大多數領域你根本不可能做到。他們可以從自己的實際用途中獲得鼓勵——在最困難的階段——在他們不相信自己可以程式設計之前,直到他們達到程式設計師的程度。
在那時,人們開始想知道他們如何在沒有完整服務 Lisp 實作的平台上獲得類似的東西。Multics MacLisp 有一個編譯器和一個直譯器——它是一個成熟的 Lisp 系統——但是人們想在其他系統上實作類似的東西,而在這些系統上他們還沒有編寫 Lisp 編譯器。好吧,如果你沒有 Lisp 編譯器,你就不能用 Lisp 編寫整個編輯器——它會太慢,特別是重新顯示,如果它必須運行直譯式 Lisp 的話。因此,我們開發了一種混合技術。想法是將 Lisp 直譯器和編輯器的底層部分一起編寫,以便編輯器的某些部分是內建的 Lisp 功能。這些將是我們認為必須最佳化的任何部分。這是一種我們已經在原始 Emacs 中有意識地實踐的技術,因為有一些相當高階的功能,我們用機器語言重新實作了它們,使它們成為 TECO 原語。例如,有一個 TECO 原語用於填充段落(實際上,用於完成填充段落的大部分工作,因為一些不太耗時的部分工作將由 TECO 程式在高階完成)。你可以通過編寫 TECO 程式來完成整個工作,但這太慢了,所以我們通過將其中的一部分放入機器語言中來最佳化它。我們在這裡(在混合技術中)使用了相同的想法,即編輯器的大部分將用 Lisp 編寫,但是某些必須運行特別快的部分將在較低層次編寫。
因此,當我編寫我的第二個 Emacs 實作時,我遵循了相同的設計。底層語言不再是機器語言,而是 C 語言。C 語言是一種好的、高效的語言,適用於在類 Unix 作業系統中運行的可移植程式。有一個 Lisp 直譯器,但是我直接用 C 語言實作了用於特殊用途編輯工作的工具——操作編輯器緩衝區、插入前導文字、讀取和寫入檔案、在螢幕上重新顯示緩衝區、管理編輯器視窗。
現在,這不是第一個用 C 語言編寫並在 Unix 上運行的 Emacs。第一個是由 James Gosling 編寫的,被稱為 GosMacs。他身上發生了一件奇怪的事情。一開始,他似乎受到了原始 Emacs 的共享和合作精神的影響。我首先將原始 Emacs 發佈給麻省理工學院的人們。有人想將它移植到 Twenex 上運行——它最初只在我們在麻省理工學院使用的不相容分時系統上運行。他們將它移植到了 Twenex,這意味著全世界有數百個安裝點可能會使用它。我們開始將它分發給他們,並規定“你必須將你所有的改進發回”,以便我們都能受益。據我所知,從來沒有人試圖強制執行這一點,但據我所知,人們確實合作了。
Gosling 最初似乎也參與了這種精神。他在一本手冊中寫道,他將該程式稱為 Emacs,希望社群中的其他人能夠改進它,直到它配得上這個名字。這是對待社群的正確方法——邀請他們加入並使程式變得更好。但在那之後,他似乎改變了精神,並將其賣給了一家公司。
那時我正在開發 GNU 系統(一個自由軟體類 Unix 作業系統,許多人錯誤地稱之為“Linux”)。沒有在 Unix 上運行的自由軟體 Emacs 編輯器。但是,我確實有一位朋友參與了 Gosling 的 Emacs 的開發。Gosling 通過電子郵件給了他許可,允許他分發他自己的版本。他向我提議我使用那個版本。然後我發現 Gosling 的 Emacs 沒有真正的 Lisp。它有一種被稱為“mocklisp”的程式語言,它在語法上看起來像 Lisp,但沒有 Lisp 的資料結構。因此,程式不是資料,並且缺少 Lisp 的重要元素。它的資料結構是字串、數字和其他一些專門的東西。
我得出結論,我不能使用它,必須全部替換掉,第一步是編寫一個真正的 Lisp 直譯器。我逐漸改編了編輯器的每個部分,使其基於真正的 Lisp 資料結構,而不是特別的資料結構,使編輯器內部的資料結構可以被用戶的 Lisp 程式暴露和操作。
唯一的例外是重新顯示。長期以來,重新顯示有點像一個另一個世界。編輯器會進入重新顯示的世界,事情會以非常特殊的資料結構繼續進行,這些資料結構對於垃圾回收是不安全的,對於中斷是不安全的,而且你不能在那期間運行任何 Lisp 程式。從那以後我們改變了這一點——現在可以在重新顯示期間運行 Lisp 程式碼了。這是一件非常方便的事情。
第二個 Emacs 程式是“自由軟體”,具有現代意義上的術語——它是使軟體自由的明確政治運動的一部分。這場運動的本質是,每個人都應該可以自由地做我們過去在麻省理工學院所做的事情,一起開發軟體,並與任何想與我們合作的人合作。這是自由軟體運動的基礎——我在麻省理工學院人工智慧實驗室的經歷,我所過的生活——致力於人類知識,並且不妨礙任何人進一步使用和進一步傳播人類知識。
當時,你可以製造一台電腦,它的價格範圍與其他非 Lisp 電腦大致相同,但它的 Lisp 運行速度比它們快得多,並且在每次操作中都具有完整的類型檢查。普通電腦通常會迫使你在執行速度和良好的類型檢查之間做出選擇。所以是的,你可以有一個 Lisp 編譯器並快速運行你的程式,但是當它們試圖對一個數字執行 car
操作時,它會得到荒謬的結果,並最終在某個時候崩潰。
Lisp 機器能夠以與其他機器大致相同的速度執行指令,但是每個指令——car
指令都會進行資料類型檢查——所以當你試圖在編譯後的程式中獲取數字的 car
時,它會立即給你一個錯誤。我們製造了這台機器,並為它配備了一個 Lisp 作業系統。它幾乎完全是用 Lisp 編寫的,唯一的例外是用微碼編寫的部分。人們開始對製造它們感興趣,這意味著他們應該創辦一家公司。
關於這家公司應該是什麼樣子,有兩種不同的想法。Greenblatt 想創辦一家他稱之為“駭客”的公司。這意味著它將是一家由駭客經營的公司,並以有利於駭客的方式運營。另一個目標是維持人工智慧實驗室文化 [3]。不幸的是,Greenblatt 沒有任何商業經驗,因此 Lisp 機器組中的其他人表示他們懷疑他是否能夠成功。他們認為他不接受外部投資的計劃行不通。
他為什麼要避免外部投資?因為當一家公司有外部投資者時,他們會取得控制權,並且他們不會讓你持有任何顧忌。最終,如果你有任何顧忌,他們也會把你換掉,不再讓你擔任經理。
所以 Greenblatt 有一個想法,他會找到一個願意預付款購買零件的客戶。他們將製造機器並交付它們;通過這些零件的利潤,他們將能夠為更多的機器購買零件,出售這些機器,然後為更多的機器購買零件,依此類推。小組中的其他人認為這不可能奏效。
然後 Greenblatt 招募了 Russell Noftsker,他就是雇用我的人,他後來離開了人工智慧實驗室並創建了一家成功的公司。人們認為 Russell 有商業天賦。他通過對小組中的其他人說:“讓我們拋棄 Greenblatt,忘記他的想法,我們將創建另一家公司。” 來證明了他的商業天賦。背後捅刀子,顯然是一個真正的商人。那些人決定他們將成立一家名為 Symbolics 的公司。他們將獲得外部投資,沒有顧忌,並盡一切可能獲勝。
但是 Greenblatt 沒有放棄。他和少數忠於他的人決定無論如何都要創辦 Lisp Machines Inc.,並繼續他們的計劃。你知道嗎,他們成功了!他們獲得了第一個客戶並獲得了預付款。他們製造了機器並出售了它們,並製造了更多的機器和更多的機器。他們實際上成功了,即使他們沒有得到小組中大多數人的幫助。Symbolics 也取得了成功的開端,所以你有兩家相互競爭的 Lisp 機器公司。當 Symbolics 看到 LMI 不會一蹶不振時,他們開始尋找摧毀它的方法。
因此,在我們實驗室被拋棄之後,隨之而來的是我們實驗室的“戰爭”。當 Symbolics 挖走了所有的駭客時,拋棄就發生了,除了我和少數在 LMI 兼職工作的人。然後他們援引一條規則,取消了在麻省理工學院兼職工作的人的資格,所以他們不得不完全離開,只剩下我。人工智慧實驗室現在無能為力了。麻省理工學院與這兩家公司達成了非常愚蠢的安排。這是一份三方合約,兩家公司都獲得了 Lisp 機器系統原始碼的使用許可。這些公司被要求讓麻省理工學院使用他們的變更。但合約中並沒有說麻省理工學院有權將它們放入兩家公司都獲得許可的麻省理工學院 Lisp 機器系統中。沒有人預料到人工智慧實驗室的駭客團隊會被消滅,但它確實被消滅了。
因此,Symbolics 提出了一個計劃 [4]。他們對實驗室說:“我們將繼續提供我們的系統變更供您使用,但您不能將其放入麻省理工學院 Lisp 機器系統中。相反,我們將讓您訪問 Symbolics 的 Lisp 機器系統,您可以運行它,但這就是您所能做的。”
實際上,這意味著他們要求我們必須選擇一方,並使用麻省理工學院版本的系統或 Symbolics 版本的系統。我們做出的任何選擇都決定了我們的改進將歸屬哪個系統。如果我們致力於改進 Symbolics 版本,我們將只支持 Symbolics。如果我們使用和改進麻省理工學院版本的系統,我們將做對兩家公司都有利的工作,但 Symbolics 看到我們將支持 LMI,因為我們將幫助他們繼續存在。因此,我們不再被允許保持中立。
直到那時,我還沒有站在任何一家公司的一邊,儘管看到我們的社群和軟體發生了什麼讓我感到痛苦。但是現在,Symbolics 強行提出了這個問題。因此,為了幫助 Lisp Machines Inc. 繼續運營 [5]——我開始複製 Symbolics 對 Lisp 機器系統所做的所有改進。我再次親自編寫了等效的改進(即,程式碼是我自己的)。
過了一段時間 [6],我得出結論,如果我甚至不看他們的程式碼,那將是最好的。當他們發布 beta 公告,其中包含發行說明時,我會看到這些功能是什麼,然後實作它們。到他們發布真正的版本時,我也發布了。
通過這種方式,在兩年內,我阻止了他們消滅 Lisp Machines Incorporated,兩家公司繼續運營。但是,我不想花費多年時間來懲罰某人,只是為了挫敗一項邪惡的行為。我認為他們已經受到了充分的懲罰,因為他們被競爭所困擾,而這種競爭不會消失或即將消失 [7]。與此同時,現在是開始建立一個新的社群來取代被他們的行為和其他人的行為消滅的社群的時候了。
70 年代的 Lisp 社群不僅限於麻省理工學院人工智慧實驗室,駭客也不都在麻省理工學院。Symbolics 發起的戰爭摧毀了麻省理工學院,但當時還發生了其他事件。有人放棄了合作,這些事件共同摧毀了社群,剩下的不多了。
一旦我停止懲罰 Symbolics,我就必須弄清楚接下來該做什麼。我必須製作一個自由作業系統,這是很清楚的——人們可以一起工作和共享的唯一方法是使用自由作業系統。
起初,我考慮製作一個基於 Lisp 的系統,但我意識到這在技術上不是一個好主意。要擁有像 Lisp 機器系統這樣的東西,你需要特殊的微碼。這使得程式能夠以與其他電腦運行其程式一樣快的速度運行,並且仍然獲得類型檢查的好處。如果沒有它,你就會淪為類似於其他機器的 Lisp 編譯器的東西。程式會更快,但不穩定。現在,如果你在分時系統上運行一個程式,那還可以——如果一個程式崩潰了,那不是災難,那是你的程式偶爾會做的事情。但這不適合用來編寫作業系統,所以我拒絕了製作像 Lisp 機器這樣的系統的想法。
我決定改為製作一個類 Unix 作業系統,它將具有 Lisp 實作,可以作為用戶程式運行。核心不會用 Lisp 編寫,但我們會擁有 Lisp。因此,那個作業系統,GNU 作業系統的開發,導致我編寫了 GNU Emacs。在這樣做的過程中,我的目標是製作絕對最小可能的 Lisp 實作。程式的大小是一個巨大的問題。
在 1985 年的那些日子裡,有些人擁有一兆位元組的機器,沒有虛擬記憶體。他們希望能夠使用 GNU Emacs。這意味著我必須盡可能地縮小程式的體積。
例如,當時唯一的循環結構是 while
,它非常簡單。沒有辦法跳出 while
語句,你只需要做一個 catch 和一個 throw,或者測試一個運行循環的變數。這表明我為了保持東西的小體積付出了多大的努力。我們沒有 caar
和 cadr
等等;“盡可能擠出一切”是 GNU Emacs 的精神,是 Emacs Lisp 的精神,從一開始就是如此。
顯然,現在的機器更大了,我們不再那樣做了。我們加入了 caar
和 cadr
等等,我們可能會在不久的將來加入另一個循環結構。我們現在願意在一定程度上擴展它,但我們不想將它擴展到通用 Lisp 的程度。我曾經在 Lisp 機器上實作過 Common Lisp,我對它並不是那麼滿意。我不太喜歡的一件事是關鍵字參數 [8]。它們對我來說似乎不太像 Lisp 風格;我偶爾會使用它,但我會盡量減少使用它的次數。
那不是與 Lisp 相關的 GNU 專案的結束。後來在 1995 年左右,我們正在研究啟動一個圖形桌面專案。很明顯,對於桌面上的程式,我們想要一種程式語言來編寫其中的大部分程式,使其易於擴展,就像編輯器一樣。問題是它應該是什麼。
當時,TCL 正被大力推廣用於此目的。我對 TCL 的評價非常低,基本上是因為它不是 Lisp。它看起來有點像 Lisp,但在語義上它不是,而且它沒有那麼乾淨。然後有人給我看了一個廣告,其中 Sun 試圖聘請某人來開發 TCL,使其成為世界“事實上的標準擴展語言”。我心想,“我們必須阻止這種情況發生。” 因此,我們開始將 Scheme 作為 GNU 的標準可擴展語言。不是 Common Lisp,因為它太大了。想法是我們將有一個 Scheme 直譯器,旨在像 TCL 一樣連結到應用程式中。然後,我們將建議將其作為所有 GNU 程式的首選可擴展性套件。
使用像 Lisp 的版本這樣強大的語言作為你的主要可擴展語言,你可以獲得一個有趣的好處。你可以通過將其他語言翻譯成你的主要語言來實作其他語言。如果你的主要語言是 TCL,你不能很容易地通過將 Lisp 翻譯成 TCL 來實作 Lisp。但是,如果你的主要語言是 Lisp,那麼通過翻譯來實作其他東西並不太困難。我們的想法是,如果每個可擴展的應用程式都支持 Scheme,你可以用 Scheme 編寫一個 TCL 或 Python 或 Perl 的實作,將該程式翻譯成 Scheme。然後你可以將其載入到任何應用程式中,並用你最喜歡的語言自訂它,它也可以與其他自訂一起使用。
只要可擴展語言很弱,用戶就只能使用你提供給他們的語言。這意味著任何給定語言的愛好者都必須競爭應用程式開發人員的選擇——說“請應用程式開發人員,將我的語言放入您的應用程式中,而不是他的語言。” 然後用戶根本沒有選擇——無論他們使用哪個應用程式,都帶有一種語言,他們就被困在 [該語言中]。但是,當你擁有一種可以通過翻譯成其他語言來實作其他語言的強大語言時,那麼你就給了用戶語言選擇權,我們就不必再進行語言戰爭了。這就是我們希望 Guile,我們的 scheme 直譯器,能夠做到的。我們去年夏天有一個人在完成從 Python 到 Scheme 的翻譯器。我不知道它是否完全完成了,但對於任何對這個專案感興趣的人,請聯繫我們。這就是我們為未來制定的計劃。
我一直沒有談論自由軟體,但讓我簡要地告訴你一點那是什麼意思。自由軟體不是指價格;它並不意味著你可以免費獲得它。(你可能為副本付費,或者免費獲得副本。)它意味著你作為用戶擁有自由。最關鍵的是,你可以自由地運行程式,自由地研究它做什麼,自由地更改它以適應你的需求,自由地重新分發其他人的副本,以及自由地發布改進的、擴展的版本。這就是自由軟體的含義。如果你正在使用非自由軟體,你已經失去了關鍵的自由,所以永遠不要那樣做。
GNU 專案的目的是通過提供自由軟體來取代自由踐踏、用戶支配、非自由軟體,從而使人們更容易拒絕它們。對於那些沒有道德勇氣拒絕非自由軟體的人來說,當這意味著一些實際的不便時,我們嘗試做的是提供一個自由的替代方案,以便你可以更輕鬆、更少犧牲實際利益地走向自由。犧牲越少越好。我們希望讓你更容易地生活在自由中,進行合作。
這是一個合作自由的問題。我們習慣於將自由和與社會合作視為對立面。但在這裡它們是同一邊的。有了自由軟體,你可以自由地與其他人合作,也可以自由地幫助自己。使用非自由軟體,有人在支配你並使人們分裂。你不被允許與他們分享,你不能自由地合作或幫助社會,就像你不能自由地幫助自己一樣。分裂和無助是使用非自由軟體的用戶的狀態。
我們已經生產了範圍廣泛的自由軟體。我們做了人們說我們永遠做不到的事情;我們有兩個自由軟體作業系統。我們有很多應用程式,而且顯然我們還有很長的路要走。所以我們需要你的幫助。我想請你自願加入 GNU 專案;幫助我們為更多的工作開發自由軟體。查看 gnu.org/help 以查找有關如何提供幫助的建議。如果你想訂購東西,首頁上有一個連結。如果你想閱讀有關哲學問題的文章,請查看 /philosophy。如果你正在尋找要使用的自由軟體,請查看 /directory,其中現在列出了大約 1900 個套件(這只是所有自由軟體的一小部分)。請編寫更多內容並為我們做出貢獻。我的論文集《自由軟體與自由社會》正在銷售中,可以在 www.gnu.org [9] 購買。駭客愉快!
腳註
- Guy Steele 設計了最初的對稱 Emacs 命令集;然後他和我開始實作 Emacs(基於 TECO),但在一次長時間的聯合開發會議後,Steele 開始逐漸離開,所以我完成了 Emacs。其他人,特別是包括 Eugene C. Cicciarelli 和 Mike McMahon,在稍後也做出了重大貢獻。
- Bernie Greenberg 說 Dan Weinreb 為 Lisp 機器實作的 Emacs 早於 Greenberg 為 Multics 實作的版本。對於這個錯誤,我深感抱歉。
- 正如我所理解的,Greenblatt 的計劃是兼職聘請實驗室人員,以便他們可以繼續在人工智慧實驗室工作。Symbolics 聘請了他們全職,所以他們停止在麻省理工學院工作。
- 這個計劃的背景,我在演講中沒有明確說明,是在最初的時期,無論是在 Symbolics 還是 LMI 的前人工智慧實驗室駭客,都繼續將他們的變更貢獻給麻省理工學院 Lisp 機器系統——即使合約沒有要求這樣做。Symbolics 的計劃是單方面破壞這種合作。
- 並不是我特別關心 LMI 的命運,而是我不希望讓 Symbolics 通過其對人工智慧實驗室的侵略而獲利。
- 這個聲明被誤解為說我從未看過 Symbolics 的程式碼。實際上,它說我一開始確實看過。Symbolics 原始碼在麻省理工學院可以獲得,我有權閱讀它,一開始我就是通過這種方式了解他們的變更的。
但這意味著我必須做出特別的努力來以不同的方式解決每個問題,以避免複製 Symbolics 程式碼。過了一段時間後,我得出結論,最好甚至不要看。這樣我就可以以最好的方式編寫程式碼,而不必擔心 Symbolics 程式碼中可能存在的內容。
- Symbolics 曾一度向麻省理工學院抗議,說我的工作通過挫敗他們的計劃,使 Symbolics 損失了一百萬美元。
- 如果一個非常複雜和重量級的函數採用關鍵字參數,我並不介意。讓我感到困擾的是使像“member”這樣的簡單基本函數使用它們。
- 在 2021 年,這本書可以從 GNU Press 購買。