Larry Wall 專訪:語言學、Perl 6 的設計和釋出

發表於2015-10-20

Larry Wall 是個相當有趣的人。他是程式語言 Perl 的創造者,這種語言被廣泛的譽為將網際網路粘在一起的膠水,也由於大量地在各種地方使用非字母的符號被嘲笑為‘只寫’語言——以難以閱讀著稱。Larry 本人具有語言學背景,以其介紹 Perl 未來發展的演講“洋蔥的狀態 State of the Onion”而聞名。(LCTT 譯註:“洋蔥的狀態”是 Larry Wall 的年度演講的主題,洋蔥也是 Perl 基金會的標誌。)

在2015年布魯塞爾的 FOSDEM 上,我們趕上了 Larry,問了問他為什麼 Perl 6 花了如此長的時間(Perl 5 的釋出時間是1994年),瞭解當專案中的每個人都各執己見時是多麼的難以管理,以及他的語言學背景自始至終究竟給 Perl 帶來了怎樣的影響。做好準備,讓我們來領略其中的奧妙……

 

Linux Voice:你曾經有過計劃去尋找世界上某個地方的某種不見經傳的語言,然後為它創造書寫的文字,但你從未有機會去實現它。如果你能回到過去,你會去做麼?

Larry Wall:你首先得是個年輕人才能搞得定!做這些事需要投入很大的努力和人力,以至於已經不適合那些上了年紀的人了。健康、活力是其中的一部分,同樣也因為人們在年輕的時候更容易學習一門新的語言,只有在你學會了語言之後你才能寫呀。

我自學了日語十年,由於我的音系學和語音學的訓練我能說的比較流利——但要理解別人的意思對我來說還十分困難。所以到了日本我會問路,但我聽不懂他們的回答!

通常需要一門語言學習得足夠好才能開發一個文字型系,並可以使用這種語言進行少量的交流。在你能夠實際推廣它和用本土人自己的文化教育他們前,那還需要一些年。最後才可以教授本土人如何以他們的文明書寫。

當然如果在語言方面你有幫手 —— 經過別人的提醒我們不再使用“語言線人”來稱呼他們了,那樣顯得我們像是在 CIA 工作的一樣!—— 你可以通過他們的幫助來學習外語。他們不是老師,但他們會以另一種方式來啟發你學習 —— 當然他們也能教你如何說。他們會拿著一根棍子,指著它說“這是一根棍子”,然後丟掉同時說“棒子掉下去了”。然後,你就可以記下一些東西並將其系統化。

大多數讓人們有這樣做的動力是翻譯聖經。但是這只是其中的一方面;另一方面也是為了文化保護。傳教士在這方面臭名昭著,因為人類學家認為人們應該基於自己的文明來做這件事。但有些人註定會改變他們的文化——他們可能是軍隊、或是商業侵入,如可口可樂或者縫紉機,或傳教士。在這三者之間,傳教士相對來講傷害最小的了,如果他們恪守本職的話。

LV:許多文字系統有本可依,相較而言你的發明就像是格林蘭語…

印第安人照搬字母就發明了他們自己的語言,而且沒有在這些字母上施加太多我們給這些字母賦予的涵義,這種做法相當隨性。它們只要能夠表達出人們的所思所想,使交流順暢就行。經常是有些聲調語言Tonal language使用的是西方文字拼寫,並儘可能的使用拉丁文的字元變化,然後用重音符或數字標註出音調。

在你開始學習如何使用語音和語調錶示之後,你也開始變得迷糊——或者你的書寫就不如從前準確。或者你對話的時候像在講英文,但發音開始無法匹配拼寫。

LV:當你在開發 Perl 的時候,你的語言學背景會不會使你認為:“這對程式設計語言真的非常重要”?

LW:我在人們是如何使用語言上想了很多。在現實的語言中,你有一套名詞、動詞和形容詞的體系,並且你知道這些單詞的詞性。在現實的自然語言中,你時常將一個單詞放到不同的位置。我所學的語言學理論也被稱為法位學phoenetic,它解釋了這些在自然語言中工作的原理 —— 也就是有些你當做名詞的東西,有時候你可以將它用作動詞,並且人們總是這樣做。

你能很好的將任何單詞放在任何位置而進行溝通。我比較喜歡的例子是將一個整句用作為一個形容詞。這句話會是這樣的:“我不喜歡你的[我可以用任何東西來取代這個形容詞的]態度”!

所以自然語言非常靈活,因為聆聽者非常聰明 —— 至少,相對於電腦而言 —— 你相信他們會理解你最想表達的意思,即使存在歧義。當然對電腦而言,你必須保證歧義不大。

“在 Perl 6 中,我們試圖讓電腦更準確的瞭解我們。”

可以說在 Perl 1到5上,我們針對歧義方面處理做得還不夠。有時電腦會在不應該的時候迷惑。在 Perl 6上,我們找了許多方法,使得電腦對你所說的話能更準確的理解,就算使用者並不清楚這底是字串還是數字,電腦也能準確的知道它的型別。我們找到了內部以強型別儲存,而仍然可以無視型別的“以此即彼”的方法。

 

LV:Perl 被視作網際網路上的“膠水glue”語言已久,能將點點滴滴組合在一起。在你看來 Perl 6 的釋出是否符合當前使用者的需要,或者旨在招攬更多新使用者,能使它重獲新生嗎?

LW:最初的設想是為 Perl 程式設計師帶來更好的 Perl。但在看到了 Perl 5 上的不足後,很明顯改掉這些不足會使 Perl 6更易用,就像我在討論中提到過 —— 類似於 托爾金(J. R. R. Tolkien) 在《指環王》前言中談到的適用性一樣。

重點是“簡單的東西應該簡單,而困難的東西應該可以實現”。讓我們回顧一下,在 Perl 2和3之間的那段時間。在 Perl 2上我們不能處理二進位制資料或嵌入的 null 值 —— 只支援 C 語言風格的字串。我曾說過“Perl 只是文字處理語言 —— 在文字處理語言裡你並不需要這些功能”。

但當時發生了一大堆的問題,因為大多數的文字中會包含少量的二進位制資料 —— 如網路地址network addresses及類似的東西。你使用二進位制資料開啟套接字,然後處理文字。所以通過支援二進位制資料,語言的適用性applicability翻了一倍。

這讓我們開始探討在語言中什麼應該簡單。現在的 Perl 中有一條原則,是我們偷師了哈夫曼編碼Huffman coding的做法,它在位編碼系統中為字元采取了不同的尺寸,常用的字元佔用的位數較少,不常用的字元佔用的位數更多。

我們偷師了這種想法並將它作為 Perl 的一般原則,針對常用的或者說常輸入的 —— 這些常用的東西必須簡單或簡潔。不過,另一方面,也顯得更加的不規則irregular。在自然語言中也是這樣的,最常用的動詞實際上往往是最不規則的。

所以在這樣的情況下需要更多的差異存在。我很喜歡的一本書是 Umberto Eco 寫的《探尋完美的語言The Search for the Perfect Language》,說的並不是計算機語言;而是哲學語言,大體的意思是古代的語言也許是完美的,我們應該將它們帶回來。

所有的這類語言錯誤的認為類似的事物其編碼也應該總是類似的。但這並不是我們溝通的方式。如果你的農場中有許多動物,他們都有相近的名字,當你想殺一隻雞的時候說“走,去把 Blerfoo 宰了”,你的真實想法是宰了 Blerfee,但有可能最後死的是一頭牛(LCTT 譯註:這是殺雞用牛刀的意思嗎?哈哈)。

所以在這種時候我們其實更需要好好的將單詞區分開,使溝通訊道的冗餘增加。常用的單詞應該有更多的差異。為了達到更有效的通訊,還有一種自足(LCTT 譯註:self-clocking ,自同步,概念來自電信和電子行業,此處譯為“自足”更能體現涵義)編碼。如果你在一個貨物上看到過 UPC 標籤(條形碼),它就是一個自足編碼,每對“條”和“空”總是以七個列寬為單位,據此你就知道“條”的寬度加起來總是這麼寬。這就是自足。

在電子產品中還有另一種自足編碼。在老式的序列傳輸協議中有停止和啟動位,來保持同步。自然語言中也會包含這些。比如說,在寫日語時,不用使用空格。由於書寫方式的原因,他們會在每個片語的開頭使用中文中的漢字字元,然後用音節表syllabary中的字元來結尾。

LV:是平假名,對嗎?

LW: 是的,平假名。所以在這一系統,每個片語的開頭就自然就很重要了。同樣的,在古希臘,大多數的動詞都是搭配好的(declined 或 conjugated),所以它們的標準結尾是一種自足機制。在他們的書寫體系中空格也是可有可無的 —— 引入空格是更近代的發明。

所以在計算機語言上也要如此,有的值也可以自足編碼。在 Perl 上我們重度依賴這種方法,而且在 Perl 6 上相較於前幾代這種依賴更重。當你使用表示式時,你要麼得到的是一個詞,要麼得到的是插值infix操作符。當你想要得到一個詞,你有可能得到的是一個字首操作符,它也在相同的位置;同樣當你想要得到一個插值操作符,你也可能得到的是前一個詞的字尾。

但是反過來。如果編譯器準確的知道它想要什麼,你可以稍微過載overload它們,其它的讓 Perl 來完成。所以在斜線“/”後面是單詞時它會當成正規表示式,而斜線“/”在字串中時視作除法。而我們並不會過載所有東西,因為那隻會使你失去自足冗餘。

多數情況下我們提示的比較好的語法錯誤訊息,是出於發現了一行中出現了兩個關鍵詞,然後我們嘗試找出為什麼一行會出現兩個關鍵字 —— “哦,你一定漏掉了上一行的分號”,所以我們相較於很多其他的按步照班的解析器可以生成更好的錯誤訊息。

 

LV:為什麼 Perl 6 花了15年?當每個人對事物有不同看法時一定十分難於管理,而且正確和錯誤並不是絕對的。

LW:這必須要非常小心地平衡。剛開始會有許多的好的想法 —— 好吧,我並不是說那些全是好的想法。也有很多令人煩惱的地方,就像有361條 RFC [功能建議檔案],而我也許只想要20條。我們需要坐下來,將它們全部看完,並忽略其中的解決方案,因為它們通常流於表象、視野狹隘。幾乎每一條只針對一樣事物,如若我們將它們全部拼湊起來,那簡直是一堆垃圾。

“掌握平衡時需要格外小心。畢竟在剛開始的時候總會有許多的好主意。”

所以我們必須基於人們在使用 Perl 5 時的真實感受重新整理,尋找統一、深層的解決方案。這些 RFC 文件許多都提到了一個事實,就是型別系統的不足。通過引入更條理分明的型別系統,我們可以解決很多問題並且即聰明又緊湊。

同時我們開始關注其他方面:如何統一特徵集並開始重用不同領域的想法,這並不需要它們在下層相同。我們有一種標準的書寫配對pair的方式——好吧,在 Perl 裡面有兩種!但使用冒號書寫配對的方法同樣可以用於基數計數法或是任何進位制的文字編號。同樣也可以用於其他形式的引用quoting。在 Perl 裡我們稱它為“奇妙的一致”。

“做了 Perl 6 的早期實現的朋友們,握著我的手說:“我們真的很需要一位語言的設計者。”

同樣的想法湧現出來,你說“我已經熟悉了語法如何運作,但是我看見它也被用在別處”,所以說視角相同才能找出這種一致。那些提出各種想法和做了 Perl 6 的早期實現的人們回來看我,握著我的手說:“我們真的需要一位語言的設計者。您能作為我們的仁慈獨裁者benevolent dictator嗎?”(LCTT 譯註:Benevolent Dictator For Life,或 BDFL,指開源領袖,通常指對社群爭議擁有最終裁決權的領袖,典故來自 Python 創始人 Guido van Rossum, 具體參考維基條目解釋)。

所以我是語言的設計者,但總是聽到:“不要管具體實現implementation!我們目睹了你對 Perl 5 做的那些,我們不想歷史重演!”真是讓我忍俊不禁,因為他們作為起步的核心和原先 Perl 5 的內部結構上幾乎別無二致,也許這就是為什麼一些早期的實現做的並不好的原因。

因為我們仍然在摸索我們的整個設計,其實現在做了許多 VM (虛擬機器)該做什麼和不該做什麼的假設,所以最終這個東西就像物件導向的組合語言一樣。類似的問題在伊始階段無處不在。然後 Pugs 這傢伙走過來說:“用用看 Haskell 吧,它能讓你們清醒的認識自己正在幹什麼,讓我們用它來弄清楚下層的語義模型semantic model。”

因此,我們明確了其中的一些語義模型,但更重要的是,我們開始建立符合那些語義模型的測試套件。在這之後,Parrot VM 繼續進行開發,並且出現了另一個實現 Niecza ,它基於 .Net,是由一個年輕的傢伙搞出來的。他很聰明,實現了 Perl 6 的一個很大的子集。不過他還是一個人幹,並沒有找到什麼好方法讓別人介入他的專案。

同時 Parrot 專案變得過於龐大,以至於任何人都不能真正的深入掌控它,並且很難重構。同時,開發 Rakudo 的人們覺得我們可能需要在更多平臺上執行它,而不只是在 Parrot VM 上。 於是他們發明了所謂的可移植層 NQP ,即 “Not Quite Perl”。他們一開始將它移植到 JVM(Java虛擬機器)上執行,與此同時,他們還祕密的開發了一個叫做 MoarVM 的 VM ,它去年才剛剛為人知曉。

無論 MoarVM 還是 JVM 在迴歸測試regression test中表現得十分接近 —— 在許多方面 Parrot 算是尾隨其後。這樣不挑剔 VM 真的很棒,我們也能開始考慮將 NQP 發揚光大。谷歌夏季編碼大賽Google Summer of Code project的目標就是針對 JavaScript 的 NQP,這應該靠譜,因為 MoarVM 也同樣使用 Node.js 作為日常處理。

我們可能要將今年餘下的時光投在 MoarVM 上,直到 6.0 釋出,方可休息片刻。

 

LV:去年英國,政府開展程式設計年活動Year of Code,來激發年輕人對程式設計的興趣。針對活動的建議五花八門——類似為了讓人們準確的認識到記憶體的使用你是否應該從低階語言開始講授,或是一門高階語言。你對此作何看法?

LW:到現在為止,Python 社群在低階方面的教學工作做得比我們要好。我們也很想在這一方面做點什麼,這也是我們有蝴蝶 logo 的部分原因,以此來吸引七歲大小的女孩子!

“到現在為止,Python 社群在低階方面的教學工作做得比我們要好。”

我們認為將 Perl 6 作為第一門語言來學習是可行的。一大堆的將 Perl 5 作為第一門語言學習的人讓我們吃驚。你知道,在 Perl 5 中有許多相當大的概念,如閉包,詞法範圍,和一些你通常在函數語言程式設計中見到的特性。甚至在 Perl 6 中更是如此。

Perl 6 花了這麼長時間的部分原因是我們嘗試去堅持將近 50 種互不相同的原則,在設計語言的最後對於“哪點是最重要的規則”這個問題還是懸而未決。有太多的問題需要討論。有時我們做出了決定,並已經工作了一段時間,才發現這個決定並不很正確。

之前我們並未針對併發程式設計或指定很多東西,直到 Jonathan Worthington 的出現,他非常巧妙的權衡了各個方面。他結合了一些其他語言諸如 Go 和 C# 的想法,將併發原語寫的非常好。可組合性Composability是一個語言至關重要的一部分。

有很多的程式設計系統的併發和並行寫的並不好 —— 比如執行緒和鎖,不良的操作方式有很多。所以在我看來,額外花點時間看一下 Go 或者 C# 這種高階原語的開發是很值得的 —— 那是一種關鍵字上的矛盾 —— 寫的相當棒。

相關文章