如果我告訴大家,這篇文章出自一個只有20歲的小伙,我想很多人都會感到吃驚。至少我是吃了一驚,因為這篇文章涉及到主題聽起來是很有深度的,我本人在20歲時幾乎想都不會想這些事情,更別說研究了。但又過了這麼多年,不知國內的青年們有沒有追趕上西方的步伐,也能出現幾個這樣看起來很有編程天分的人?
我最近看到了《編程改革 》這篇文章,裡面的內容討論到了我們的編程中存在的一個最根本的問題。我同意作者的觀點,但我感覺很多的評論並沒有理解他說的問題,所以,我打算用另外一種方式來說明一下。
我從事編程已經很久,主要是因為我痴迷於解決難題。我非常喜歡研究編程語言,一部分原因是作為一個程序員,我本身是被它們包圍,同時也是因為語言是讓我們成為人類的一個重要因素。
我享受編程這種職業,我喜歡這種能夠從無到有創造出神奇東西的能力,但同時也對我們每天需要處理的這些事情感到失望。下面就是原因:
鏈式(Concatenative),函數式,面向對象的,邏輯式——不管你選擇何種編程模式,他們全都有相同的問題:它們要求你去描述如何做,而不是做什麼。在你能叫得出名字的任何一種語言里,程序是一個對能計算出你想要的東西的處理過程的描述,而不是一個對你想要的東西的描述。誠然,一些語言會比另外一些語言更具有陳述性,但這跟“陳述式 vs 命令式”的問題並不相關——能夠陳述式的表達一個過程的語言仍然是面向過程的,而不是面向結果的。
這才是癥結所在。作為程序員,我們用代碼解決問題。我們應該能夠用代碼來表達我們想要的結果,而不是想要達到這種結果需要的過程。
作者提出的是一種“約束滿足(constraint satisfaction)”式的編程方式。給出一系列的約束條件,你就能夠從中推導出一種能夠滿足它們的演算法。當然,我們必然的會擔心編譯器推導出的這種演算法的正確性和各種性能指標;是否本來可以做到Θ(n log n)級別的,它編譯器卻給出了Θ(n!)?這是一個很合理的擔心,但它只是跟你的描述是否嚴謹有關。
你也知道,對於一個特定的演算法,我們可以通過很多種不同的但卻等效的約束集合來定義。從中進行優選,我們有信心相信,編譯器能夠推導出我們想要的結果。我們的工作應該變成把需求用有效的約束正確的表達出來,讓編譯器去滿足這些約束。
我知道這聽起來很枯燥,我最初也是這種神奇的編程方式的懷疑者。但想一想:任何值得一提的程序其實都是這樣實現的,只是它們是以一種效率低的容易出錯的手工方式。一個程序員拿到一些需求,先整理它們,然後辛苦的把它們轉換成一種合適的處理過程。我們可以省掉這其中的一個步驟。
假設你在編寫一個遊戲。在你的待完成任務清單上的第一個要實現的事情是:通過方向鍵,讓一個遊戲角色可以在屏幕上四處移動。在任何一種語言里,你不得不構造出一大堆不相干的基礎構件來實現這個操作:
所有的這些折騰實際上跟我們想要的東西是沒有關係的。
很多時候,這些工作已經由某個程序庫提供完成了,但這表明一個事實:需要有人去做這些麻煩事。相比較,功能應對式編程很適合做這種事情。你可以準確的表達出你的意思:
這是一個完備的,完全陳述式的,完全面向結果的對一個程序的描述。這些描述都是跟你目前要實現的目標任務是直接相關的,每個描述都是一種約束,在一個RRP(這是一個簡單的約束求解程序,根據實時狀態推導解決方案)系統里,你可以按意願添加或去除這種約束。
Prolog語言就是一個以約束為基礎的編程方式的樣本,而Haskell語言里的FRP庫表現的更好,但這些跟我們能夠做到的比起來更像玩具。
沒有任何理由去說我們不能實現一種更好、更面向結果的語言,或者把目前存在的面向過程的語言變得更像面向結果,為這種編程模式賦予更大的能力。參考一下Swym這篇文章,裡面提到的關鍵字etc就能讓你實現類似的事情:
List.byPairs: [[.1st, .2nd], [.3rd, .4th], etc]; byPairs[1..10] == [[1,2],[3,4],[5,6],[7,8],[9,10]];
當你提供給它一些不同的參數,它能做出更智能的事情:
[1,2,3].byPairs == [[1,2]]; [1,2].byPairs == [[1,2]]; [1].byPairs == [];
這真是讓人興奮,但事情並非到此為止,我們可以把它做的更好。我們實現更多的類似etc和 each 這樣的”魔法“操作符,可以讓一種命令式的語言看起來更像面向結果的語言。
有一段時間,我使用一個叫做Prog的語言工作。你可以把它按照普通的命令式的語言進行編程。但它附帶有一些特殊的語言特徵。這些神奇的語言特徵是通過“radioactive types”實現的,它們是一種中間態的語言行為特徵,只能在解釋器分析期運行,過了此階段,它們就蛻化成普通的語法。舉個例子,對一個枚舉數據結構進行各種操作,可以這樣寫:
which (1..10) > 5 == (6, 7, 8, 9, 10); each (1..5) ** 2 == (1, 4, 9, 16, 25); each (1..3) * each (1..3) == ((1,2,3), (2,4,6), (3,6,9));
在讀了那篇文章和之後的評論后,我激起了再次使用Prog語言的想法——如果有時間的話。我希望能看到更多的關於這方面的文章出現。目前開發的一個具有相似理念的項目消耗了我大量的精力,那是一個能讓非程序員用戶製作出專業質量的互動式媒體的工具。如果你不知道如何編程,你在創建遊戲或其他媒體應用時會受到阻礙。所有的這些幫助創造性的軟體基本上可以歸為兩類:
所以,利用研究人們能如何更好的解決問題,我開發了這樣一個工具,能讓那些心裡有想法、但沒能力把它變成現實的人解決他們的問題。目前為止,我們還有繼續努力。如果你是一個程序員,受到這篇的啟發,想參與做一些事情,請聯繫我evincarofautumn@gmail.com,我會告訴你如何參與進來。
[本文英文原文鏈接:Yep, Programming Is Borked ]
[火星人 ] 評論:也談編程改革已經有364次圍觀