编程的修炼(中英双语)
編程的修煉(中英雙語)(圖靈獎獲得者EdsgerW. Dijkstra 是每個在計算機領域學習和工作的人都應該了解和尊重的先驅者,本書為他最重要的述著,堪稱編程領域里,經典著作的經典!)
【荷】Edsger W. Dijkstra 著
裘宗燕譯
ISBN 978-7-121-20250-6
2013年7月出版
定價:79.00元
456頁
16開
編輯推薦
本書寫于20世紀70年代中后期,但其對編程技術領域的開發、編程語言發展和程序理論研究的深刻影響持續至今。
內容提要
本書是圖靈獎獲得者Edsger W. Dijkstra在編程領域里的經典著作中的經典。作者基于其敏銳的洞察力和長期的實際編程經驗,對基本順序程序的描述和開發中的許多關鍵問題做了獨到的總結和開發。書中討論了順序程序的本質特征、程序描述和對程序行為(正確性)的推理,并通過一系列從簡單到復雜的程序的思考和開發范例,闡釋了基于嚴格的邏輯推理開發正確可靠程序的過程。
本書寫于20世紀70年代中后期,但其對編程技術領域的開發、編程語言發展和程序理論研究的深刻影響持續至今。本書值得每個關注計算機科學技術的本質,冀求在程序和軟件領域有長遠發展的計算機工作者、教師和學生閱讀。
目錄
序???? IX
前言???????? XI
第0章? 執行抽象????????? 1
第1章? 編程語言的作用???? 13
第2章? 狀態及其特征????????? 19
第3章? 語義的性質???? 29
第4章? 一種編程語言的語義特征???? 47
第5章? 兩個定理????????? 73
第6章? 論完滿終止結構的設計????????? 81
第7章? 再論歐幾里得算法????????? 89
第8章? 幾個小例子的形式化處理???? 101
第9章? 論受限的非確定性????????? 143
第10章? 有關記法的短論:“變量的作用域”????????? 157
第11章? 數組變量?????? 187
第12章? 線性檢索定理?????? 209
第13章? 下一個排列?? 213
第14章? 荷蘭國旗問題?????? 221
第15章? 更新順序文件?????? 233
第16章? 再論歸并?????? 245
第17章? 來自R.W.HAMMING的一個練習??????? 257
第18章? 模式匹配問題?????? 269
第19章? 將一個數寫成兩個平方之和?????? 279
第20章? 大數的最小素因子問題?????? 285
第21章? 最孤立村莊問題?? 297
第22章? 最短子支撐樹問題?????? 307
第23章? 記錄等價類的REM算法????? 321
第24章? 三維空間的凸包問題?? 335
第25章? 有向圖的最大強連通分支?? 383
第26章? 論手冊和實現?????? 401
第27章? 跋?? 417
精彩節摘
第1?章
編程語言的作用
?
?
?
?
?
在“執行抽象”一章中,我非形式化地描述了計算兩個(不太大的)正整數的最大公因子的幾種不同“機器”的設計。其中一部機器采用在紙板上移動石子的方式;另一部機器基于兩個半拉石子,而且它們都在坐標軸上移動;最后一個基于兩個寄存器,每個里面可以保存一個(直至某個上限的)整數值。從物理上說,這三臺“機器”大相徑庭;而從數學上看,它們卻很類似,做出這一論斷的主要原因是,三者都能計算最大公因子,這是三者的共性。由于這三臺機器只不過是同樣一組“游戲規則”中不同的具體實現,而實際上,這組規則才是一個發明的核心,該發明就是大名鼎鼎的“歐幾里得算法”。
在前一章里,歐幾里得算法是用一種相當非形式化的方式描述的。有人會提出,由于與之對應的可能計算的數目如此之大,因此,我們必須要有一個關于其正確性的證明。如果一個算法只是以非形式化的方式給出,它就不容易作為一種形式化處理的對象。為了形式化地處理,我們就需要用某種適當的形式化的記法來做算法的描述。
這樣一種形式化記述技術的可能優勢有許多方面。任何記述技術都蘊涵著一個事實:它所實際表述的任何東西都是它有可能描述的那個對象集合(通常是一個無窮集合)的一個特定成員。我們的記述技術當然應該能給出歐幾里得算法的一個優雅而簡潔的描述,而一旦做好了這件事,也就是把它表示成了一個包含各種算法的巨大的類中的一個成員。而在描述該類中的其他算法時,我們可能期望發現自己所用的記述技術的一些更有趣的應用。對于歐幾里得算法,可能會有人說因為它如此簡單,用一個非形式化的描述就能對付了。形式化記法的威力應該表現在一些沒有它就絕不可能做到的成就方面。
形式化記述技術的第二個優勢是,它使我們有可能將算法作為一種數學對象來研究,算法的形式化描述將成為我們的智力收獲的抓手,使我們能證明一些有關算法類的定理,例如,由于算法所采用的描述而使之共有的一些結構性的性質。
最后,這樣一種記述技術將使我們能毫無歧義地定義算法,這樣,給定了用它描述的一個算法,并給定一組實際參數(輸入),有關與之對應的答案(輸出)應該是什么,將沒有任何疑義或者非確定性。可以斷言,相應的計算完全可以用一部自動機器完成:給它該算法(的形式化描述)和相應的實際參數,它就能產生出相應的答案,完全無須進一步的人工干預。這樣一種能對付這種相互對應的算法和實際參數的自動機器已經造出來了,它就是人們說的“自動計算機”。為能在計算機上自動執行而寫出的算法稱為“程序”,而自20世紀50年代后期以來,用于寫程序的形式化記述技術就被稱為“編程語言”。(與程序的記述技術有關的術語“語言”的引入已受到多方面關注。一方面,現有的語言理論為相關討論提供了一種很自然的框架和一套有用的術語,如“文法”、“語法”、“語義”等。另一方面,我們也必須注意到,與現存的“自然語言”的類似性也造成了許多誤導,因為各種自然語言,無論怎樣做形式化,其弱點和威力都來自它們的非明確性和非精確性。)
從歷史情況看,這最后一個方面,即各種編程語言可以用作指揮現有的自動計算機的媒介,這個事實已經在很長時期里成為它們最重要的屬性。現有的自動計算機執行某種特定語言寫出的程序的效率,也成為評判該語言的質量的最重要標準。這種情況導致了一個令人遺憾的后果:不難看到,現有計算機的許多很反常的特性都被忠實地反映在現有的編程語言里,為此付出的代價是,用這樣一個語言描述的程序是很難用智力去把握的(實際上,即使沒有這種情況,編程的工作也已經非常困難了!)。在下面將要提出的方法中,我們將試著重新考慮這方面的平衡。按我們的認識,寫出的程序需要實際地由一臺計算機執行,這只是由于偶然性而導致的一種實際情況,它不應該居于我們考慮問題的中心。(在最近的一本培養PL/I程序員的教材里,可以看到作者強烈建議盡可能避免過程調用,理由是“因為它們會大大影響程序的效率”。由于過程是PL/I中描述結構的最重要的工具,上述建議實在太可怕了,以至于我完全無法把這本書看作真的能“用于教育”。如果你確信過程是一種有用的概念,而在你的工作環境中,過程機制的實現帶來的開銷卻令人難以忍受,那么應該詛咒的是這些不適當的實現,而不應該是把它們的表現作為一種標準!這方面的權衡確實應該重新做!)
我把一種編程語言看作是一種工作媒介,用于描述(可能非常復雜的)抽象機制。正如在有關“抽象執行”一章里可以看到的,算法最突出的優點就在于對它們能夠做出的論證的簡潔性。我們對于有關機制的信心也是基于這個事實。如果失去了這種簡潔性,算法就失去了其(存在的權利)中很大一部分,因此,我們將把保持這種簡潔性作為始終如一的目標。另外,我們對所有編程語言的選擇也將直面這一目標。
?
?
?
序
在詩歌、音樂、藝術和科學等歷史更為悠久的智力修煉領域,歷史學家們都把頌詞獻給那里最卓越的實踐者,因為他們的成就拓展了其贊美者的體驗和理解,也大大啟迪和提升了其追隨者們的才華。他們的創新基于其在實踐中積累的卓越技藝,并結合了他們對相應領域的基礎理論的敏銳洞見。在很多情況下,他們的影響還由于其廣博的文化積淀,以及他們在表達方式上的力量和透徹性而得到進一步的提升。
在本書中,作者以其習慣的文字風格,詳盡地描述了他對計算機編程的基本性質的激進的新見解。基于這些見解,作者開發了一套編程方法以及與之相適應的記法工具,并用一大批優雅而且高效的實例展示和檢驗了它們。本書將注定成為在計算機編程的智力修煉領域發展中最杰出的成就之一。
C.A.R.Hoare
作者簡介
作者簡介:
艾茲赫爾?戴克斯特拉(Edsger W. Dijkstra,1930年5月11日-2002年8月6日),生于荷蘭鹿特丹,自喻為荷蘭第一個以程序設計作為職業的人。他早年積極推動結構化程序設計,一生致力于將計算(computing)發展為一門科學,在計算機科學技術的諸多領域有開拓性建樹,并由于在程序設計基礎研究中的卓越貢獻獲得1972年圖靈獎。
?
?
譯者簡介:
裘宗燕,北京大學數學學院教授。主要研究興趣是軟件形式化方法和程序設計的理論基礎,也關注程序設計實踐。翻譯過若干相關著作,包括《從規范出發的程序設計》、《B方法》、《編程原本》、《計算機程序的構造和解釋》、《C++語言的設計和演化》等。
媒體評論
在本書中,作者以其習慣的文字風格,詳盡地描述了他對計算機編程的基本性質的激進的新見解。基于這些見解,作者開發了一套編程方法以及與之相適應的記法工具,并用一大批優雅而且高效的實例展示和檢驗了它們。本書將注定成為在計算機編程的智力修煉領域發展中最杰出的成就之一。
C.A.R.Hoare
前言
很長時間以來,我一直想寫一本基本上是按照本書線索的著作,原因是:一方面,我知道程序可以有迷人的形態和深刻的邏輯之美;另一方面,我又不得不接受這樣的事實,即絕大部分程序只是以一種適合機器執行的方式表達,完全沒有什么美感,也不適合人們欣賞。這種不滿意還有第二個原因,那就是各種算法通常總是以一種完成了的產品形式發表,而在設計過程中起著最重要作用的,以及成為證明所完成程序的最終形式的正當性的各種思考的主要部分,通常都完全沒有提及。我最初的想法是以讀者能欣賞到它們的美的方式發表一系列優美的算法。對于如何做這件事,我當時的想法是描述一些實際的和想象中的設計過程,使其中的每個過程最終都得到了一個所需的程序。我在一定程度上實現了最初的想法,作為這本專著的核心部分是一系列的章節,每一章處理并解決一個新問題。而在另一方面,最終寫出的這本書與我早前的期望又有很大不同,由于我特別希望用一種自然而且方便的方式來展現這些內容,因這種追求而強加給自己的任務變成了一種重要的責任。我將永遠為自己完成了這一工作而感到欣慰。
在開始寫一本像本書這樣的著作時,人們立刻會面臨一個問題:“我準備使用哪一種編程語言?”而實際上這并不僅僅是一個有關展示形式的問題!任何工具的一個最重要的(而且也是最難琢磨的)方面,就是它對于被訓練而將使用它的人們的工作習慣的影響,這種影響——無論我們是否喜歡——是對我們的思考習慣的影響。在盡可能地分析了這種影響的各方面情況之后,我得出了一個結論:沒有一個現存的語言,也沒有一個它們的子集適合我的目標。其次,我也知道自
己完全沒有為設計一種新的編程語言做好準備,因此,我曾發誓在隨后的五年里不去做這件事。而且我有一種非常清晰的感覺:這個時期還沒有過去!(但還有一個前提,就是除了其他事情外,這本書必須要寫。)我試著消解這一矛盾的方式是設計了一個適合我的具體目標的小型語言,只做出一些看起來不可能避免,而且其正當性也得到了充分證實的承諾。
這種猶豫和自我強加的約束如果被錯誤地理解,有可能使本書的許多潛在讀者對它感到很失望。那些把編程的困難等同于老練地利用那些精細而花哨的稱為“高級編程語言”的工具,或者(更糟糕的!)“編程系統”的困難的人們注定會對這本書不滿意。如果因為我忽略了所有那些誘人的花哨玩意兒而使他們感到受了騙,我只能回答說:“你真能確定所有那些誘人的花哨玩意兒,以及那些你所謂‘強大的’編程語言的美妙功能確實屬于解集合,而不屬于問題的集合嗎?”我只是希望,即便我用的是一種小型語言,他們也能看看這本書。在做完這件事之后,他們有可能同意,雖然沒有那些誘人的花哨玩意兒,仍然有非常豐富的問題需要討論。因此,是否在一開始就介紹大部分花哨玩意兒,確實是應該質疑的。還有,對于那些明顯是對編程語言的設計有興趣的讀者,我只能表示我的歉意。正如我已經做的那樣,我沒辦法在這個問題上做更明確的事情。但在另一方面,我也希望隨著時間的推移,這一專著會對他們有所啟示,而且能幫助他們避免一些如果沒有讀過它有可能犯的錯誤。
在寫作的過程中——它持續不斷地讓我感到驚喜和激動——逐漸呈現的文本與我初始時頭腦中的想象大不相同。我一開始設想以一種(易理解的)方式去展示程序的開發過程,帶上比我在(引論)課程中更多一點的形式化設施,其中以直觀的方式介紹所使用的語義,有關正確性的論證采用通常的嚴格論述,手工編排,再加上有說服力的文字。在為更形式化的方法建立了必要的基礎后,我得到了兩個驚喜。第一個驚喜就是所謂的“謂詞轉換器”,作為我選用的工具,它提供了一種方法,使我們可以直接定義初始狀態與最終狀態之間的關系,不需要參考在程序實際執行中可能經歷的中間狀態。我對這種情況感到非常欣慰,因為這清晰地區分了程序員的兩個主要關注點:數學的正確性(即程序是否定義了初始狀態與最終狀態之間所需的正確關系——謂詞轉換器是我們研究這一問題的一種形式化工具,研究中不需要考慮實際的計算進程),以及工程上對于效率的關注(現在也很清楚,這件事只與實現有關)。這已經成為一種最有幫助的發現,因為同一個程序正文總是有兩種相當互補的解釋:它可以解釋為一個謂詞轉換器的編碼,這樣做看起來更適合我們的需要;或者解釋為可執行代碼,我寧愿把這種解釋留給機器去做。第二個驚喜是,我能夠想象到的最自然而且最系統化的“謂詞轉換器的編碼”,在被看作“可執行代碼”時,將要求一種非確定性的實現。有一段時間,我對把非確定性引進單道編程感到不寒而栗(我對它給多道編程帶來的復雜性知道得太多了!),直到我認識到,將程序正文解釋為一個謂詞轉換器的編碼有其自身的存在理由。(回顧往事,我們可以看到,過去提出的有關多道編程的許多問題并不是別的什么,只不過是不適當地過分強調了確定性的重要性而帶來的后果。)我最終認識到,應該把非確定性看作正常情況,這樣,確定性將變成一種——并不很有趣的——特例了。
在打好了有關的基礎之后,我將所有的時間都投入了想做的事情上,也就是說,去解決一系列的問題。做這件事使我得到了未曾預料的快樂。與我以前的工作方式相比,形式化的設施使我能更牢固地把握所做的工作。我很高興地發現,明確地關注終止性問題能帶來許多富于啟發性的看法,以至于使我覺得偏向于考慮部分正確性的觀點如此常見是非常令人遺憾的。然而,最大的快樂是,對于大部分我原來做過的問題,這次都得到了更漂亮的解答!這是非常令人鼓舞的事情,我將它看作是一種指示劑,說明我所開發的方法確實提升了我的編程能力。
應該怎樣學習這本專著呢?我能給出的最佳建議就是,一旦看完了問題的描述,就停止閱讀,轉去試著自己解決它。嘗試自己解決問題,是你能自己認識和評價問題的困難程度的唯一方法,它也使你有機會去比較你的解和我給出的解,還給你得到滿足的機會,即看到你給出的解比我給出的更好。還是要先說一下,當你發現這里的內容遠不是非常容易讀的時候,請不要沮喪。研讀過這本專著的人都覺得它的內容通常是很難的(但收獲也同樣很多!)。然而,每次我們分析遇到的困難時,得到的結論都是應該將這種困難“歸咎于”實際討論的問題,而不是有關的文字本身(即它的表達方式)。它的寓意是,一個非平凡的算法本身就是非平凡的,而與論證其設計的正確性的思考相比,在一個編程語言里做出的算法描述是高度緊湊的:不要受到最后的程序正文長度的誤導!我的一個助理給出的建議——這也是我忠實地采納的,因為它可以很有價值——是讓學生分為一些小
組一起學習這本書。(在這里,我必須對書中正文的“困難程度”加一點附帶的說明。我本人科學生涯中的許多年一直在致力于弄清楚程序員的任務,目標是設法使它成為智力上可以管理的工作。從事了多年的這種澄清性的工作之后,我感到好玩,也很吃驚地發現,反復出現的回饋是“我把編程弄得更困難了”。但困難始終在那里,只有將其變為明顯可見的,我們才有希望設計出具有高度信任水平的程序,而不僅僅是做出了一些“胡亂涂抹出的代碼”,即那種基于根本無法得到支持的假設,準備著被第一個反例推翻的程序正文。不用說,本書的任何一個程序都沒有在機器上測試過。)
我還要給讀者解釋為什么我把這里的小型語言弄得這么小,小到沒有包含過程和遞歸。由于任何一點語言擴充都會給這本書增加幾章內容,并因此使它也相應地變得更昂貴,所以對于大部分可能的擴充(例如多道編程),我都不需要更多的解釋。而過程總是在編程中居于核心的地位,遞歸對于計算科學而言也是最受學術界重視的標志,因此,我必須給出一些解釋。
首先,這本專著不是為新手寫的,因此,我期望本書的讀者熟悉這些概念。其次,本書不是某個特殊編程語言的引論教材,缺乏這些結構和使用它們的例子,不會被解釋為我不能或者不希望使用它們,也不會被作為是建議那些有能力使用這些結構的人不要用它們。這里的關鍵是我覺得在傳遞想給出的信息時我并不需要這些結構。我想討論的是應該仔細地分離各種關注,以及為什么從各個方面看這種做法都是設計出高質量程序的最重要的基礎。以這里的小型語言作為一種有節制的工具,對于給出各種非平凡而且非常令人滿意的設計而言,已經能給我們足夠的行動自由了。
前面的解釋雖然已經很充分,但還不是故事的全部。在任何情況下,我都覺得必須把重復結構本身作為語言中的一種結構,因為在我看來,這樣的闡釋是早就應該有的東西。當編程語言誕生時,其賦值語句的“動態”性質看起來與傳統數學的“靜態”性質很不吻合。由于沒有合適的理論,數學家就覺得很不喜歡它。而且,由于重復結構是需要變量賦值的最根本原因,數學家也很不喜歡重復結構。當人們開發出沒有賦值,也沒有重復結構的編程語言——例如,純LISP——時,許多人都大大地松了一口氣。這使他們又可以回到自己熟悉的場地里,看到了一點希望的微光:有可能將編程變成一種具有堅實的而且得到廣泛尊重的數學基礎
的活動。(直到目前,在更偏向于理論的計算科學家中仍然有一種廣泛存在的感覺,認為遞歸程序比基于重復的程序“來得更自然”。)
另一種角度就是為“重復結構”和“給變量賦值”提供一種可靠的而且可用的數學基礎,為此,我們又必須等待另一個十年。這方面研究的成果是,正如在這本專著里闡釋的,一個重復結構的語義可以基于謂詞之間的一個遞歸關系定義,而一個廣義遞歸的語義定義則需要基于謂詞轉換器之間的一個遞歸關系。這一點很清楚地說明,為什么我認為廣義遞歸的復雜性比重復結構高一個數量級。因此,我很害怕看到將下面這樣重復結構的語義
?
定義為調用
?
其中的whiledo是如下定義的遞歸過程(用ALGOL60的語法描述)
?
雖然這樣做不錯,但它卻傷到我了,因為我不喜歡用一把大錘去敲一個雞蛋,無論用大錘做這件事是多么的有效。對于在20世紀60年代涉足這一問題的那一代理論計算科學家來說,上面的定義常常不僅是“自然的那一個”,而且是“真正的那一個”。應該看到下面的事實:如果不訴諸重復的概念,我們甚至無法定義圖靈機能夠做什么。這說明需要重新做一些權衡。
對于沒有參考文獻的問題,我不準備解釋,也不表示歉意。
致謝:下列人士對本書有直接影響,他們或者是提出過本書擬議中的內容的期望,或是請他們為本書(或其中一些部分)寫評論:C. Bron,R.M. Burstall,W.H.J. Feijen,C.A.R. Hoare,D.E. Knuth,M. Rem,J.C. Reynolds,D.T. Ross,C.S. Scholten,G. Seegmüller,N. Wirth和M. Woodger。能寫下對他們的合作的謝意是我的榮幸。我還要特別感謝Burroughs公司為我提供了機會和各方面的便利,感謝我妻子不斷的支持和鼓勵。
EdsgarW. Dijkstra
荷蘭Nuenen
?
總結
以上是生活随笔為你收集整理的编程的修炼(中英双语)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 正月初二
- 下一篇: ByteBuffer详解(大概2333)