冒號(hào)課堂§2.1:命令范式
冒號(hào)課堂
第二課 重要范式(1)
課前導(dǎo)讀
這一課討論了五個(gè)最重要的編程范式:命令式、函數(shù)式、邏輯式、對(duì)象式和并發(fā)式。這些只是入門性的介紹,讀者領(lǐng)會(huì)其精神即可,細(xì)節(jié)上不必過于在意。
本課共分四節(jié)——
1.命令范式
2.聲明范式
3.對(duì)象范式
4.并發(fā)范式
2.1命令范式——一切行動(dòng)聽指揮
人生最偉大的目標(biāo)是行動(dòng) ——《洛克菲勒的忠告》
關(guān)鍵詞:編程范式,命令式,結(jié)構(gòu)化編程,流程圖
摘要:命令式編程簡(jiǎn)談
?提問
- 什么是命令式編程?它為什么是最常見的編程范式?
- 什么是結(jié)構(gòu)化編程?結(jié)構(gòu)化編程的主要思想是什么?
:講解
第二課伊始,冒號(hào)開門見山:“首先介紹一下最原始也是我們最熟悉的編程范式:命令式編程(imperative programming)。用命令式編寫的程序由命令序列組成,即一系列祈使句:‘先做這,再做那’,強(qiáng)調(diào)‘怎么做’。更學(xué)術(shù)點(diǎn)說,命令式編程是電腦——準(zhǔn)確地講,是馮·諾伊曼機(jī)(von Neumann machine)——運(yùn)行機(jī)制的抽象,即依序從內(nèi)存中獲取指令和數(shù)據(jù)然后去執(zhí)行。從范式的角度看,其世界觀是:程序是由若干行動(dòng)指令組成的有序列表;其方法論是:用變量來儲(chǔ)存數(shù)據(jù),用語句來執(zhí)行指令。”
逗號(hào)小聲嘟囔著:“我們用的編程語言不都是命令式的嗎?”
“應(yīng)該說絕大多數(shù)語言是命令式的,但非命令式的語言也是存在的。關(guān)于后者,我們稍后再議。” 冒號(hào)糾正道,“這也在情理之中。語言的演化是漸進(jìn)的,大多數(shù)語言追根溯源是匯編語言的升級(jí),而作為與機(jī)器語言一一對(duì)應(yīng)的匯編語言自然是命令式的,因而這種范式最為傳統(tǒng)和普及。”
不料問號(hào)竟窮追不舍:“為什么機(jī)器語言就一定得是命令式呢?”
“我很欣賞你這種打破砂鍋問到底的精神,不過你可以問到底,我卻不敢保證能答到底哦。”冒號(hào)有些逗趣地說。
問號(hào)略帶靦腆地笑了。
“從理論上而言,完全可以有非命令式的機(jī)器語言存在,前提是計(jì)算機(jī)采用了特殊的硬件實(shí)現(xiàn),比如非馮·諾伊曼結(jié)構(gòu)的數(shù)據(jù)流機(jī)(dataflow machine)和歸約機(jī)(reduction machine)。但這類計(jì)算機(jī)并未流行于市,相應(yīng)的機(jī)器語言自然罕見了[1]。”冒號(hào)還是給出了理由。
引號(hào)問:“命令式編程與人們常說的過程式編程是一回事嗎?”
“嚴(yán)格說來,過程式編程(procedural programming)是指引入了過程(procedure)、函數(shù)(function)或子程序(subroutine/subprogram)的命令式編程。但由于現(xiàn)代的命令式語言均具備此特征,故二者往往不加區(qū)分。”冒號(hào)回應(yīng)道。
句號(hào)認(rèn)為:“由于常用的語言基本上都是命令式的,其思想也與計(jì)算機(jī)的運(yùn)行機(jī)制相符,一切對(duì)我們來說,似乎都是自然而然的事。”
“單純的命令式思想的確很樸素,毋庸贅述。” 冒號(hào)承認(rèn),“但有必要提一下結(jié)構(gòu)化編程(structured programming或簡(jiǎn)稱SP),它是在過程式編程的基礎(chǔ)上發(fā)展起來的。其本質(zhì)是一種編程原則,提倡代碼應(yīng)具有清晰的邏輯結(jié)構(gòu),以保證程序易于讀寫、測(cè)試、維護(hù)和優(yōu)化。Pascal正是遵循結(jié)構(gòu)化編程原則而設(shè)計(jì)的一種教學(xué)語言。為直觀起見,我們用圖來表現(xiàn)程序的結(jié)構(gòu)化特征——”
“這是一個(gè)流程圖(flowchart),或稱程序框圖,它描述了一個(gè)簡(jiǎn)單程序:用戶從標(biāo)準(zhǔn)輸入中鍵入算術(shù)表達(dá)式,程序打印出結(jié)果,如此循環(huán)往復(fù),直到用戶輸入字符‘q’為止。”冒號(hào)解釋道,“若以純粹的結(jié)構(gòu)化編程的標(biāo)準(zhǔn)來衡量,該流程圖并未達(dá)標(biāo)。”
嘆號(hào)有些驚訝:“這個(gè)圖不是再清晰不過了嗎?”
“根據(jù)結(jié)構(gòu)化定理(structured program theorem)[2],任何程序都可用順序(concatenation)、選擇(selection)和循環(huán)(repetition)等三種基本控制結(jié)構(gòu)來表示。”冒號(hào)畫了幾幅圖——
冒號(hào)指點(diǎn)著黑板:“結(jié)構(gòu)化編程就是在三種基本結(jié)構(gòu)的基礎(chǔ)上進(jìn)行嵌套組合。如果將每個(gè)基本結(jié)構(gòu)看作基本電器元件,編程就是將這些元件組裝成復(fù)雜的電路。請(qǐng)注意,所有基本元件都滿足‘單入口、單出口’(single entry, single exit,簡(jiǎn)稱SESE)的原則,這使得電路井井有條,不會(huì)串線纏繞。”
引號(hào)已經(jīng)看出:“上面的流程圖無法用基本結(jié)構(gòu)來組合,所以不是標(biāo)準(zhǔn)的結(jié)構(gòu)化程序。”
冒號(hào)提出要求:“你能改造一下嗎?”
引號(hào)走上講臺(tái),在前圖的基礎(chǔ)上作了些許調(diào)整——
“嗯,不錯(cuò)。這下流程圖可以拆解為基本結(jié)構(gòu)了。”冒號(hào)表示認(rèn)可,“二者的區(qū)別在于前者利用了break語句,在循環(huán)途中退出,后者通過引入quit標(biāo)志(flag)保證了循環(huán)的完整性。”
逗號(hào)的臉上寫下一個(gè)大大的問號(hào):“難道連break語句都不能用嗎?”
“break語句只是在循環(huán)體內(nèi)部的跳轉(zhuǎn),合理地使用它能簡(jiǎn)化代碼,不致影響整體結(jié)構(gòu),大可不必拘泥于教條。但goto語句可以跳到程序過程中的任一點(diǎn),造成靜態(tài)程序(static program)與動(dòng)態(tài)進(jìn)程(dynamic process)之間的差異,影響程序可讀性,是要竭力避免的[3]。”冒號(hào)如是說道,“結(jié)構(gòu)化編程的思想包括兩方面。在微觀上,主張循規(guī)守矩,采用順序、選擇和循環(huán)三種邏輯結(jié)構(gòu),摒棄或限制goto語句[4],以避免雜亂無章的代碼。在宏觀上,主張分而治之(divide and conquer),采用‘自頂向下(top-down)’ [5] 的設(shè)計(jì),通過模塊化將一個(gè)較為復(fù)雜的系統(tǒng)分解為若干相對(duì)簡(jiǎn)單的子系統(tǒng),每個(gè)子系統(tǒng)可以獨(dú)立地進(jìn)一步分解,直到容易編碼實(shí)現(xiàn)為止。這兩方面是互為因果、互為保障的——由基本結(jié)構(gòu)拼裝而成的系統(tǒng)一定是模塊清晰、層次分明的;反之,系統(tǒng)逐步分解到最后,一定會(huì)演化成基本結(jié)構(gòu)。”
嘆號(hào)產(chǎn)生一個(gè)想法:“能從程序的流程圖上看出結(jié)構(gòu)化編程與非結(jié)構(gòu)化編程之間的區(qū)別嗎?”
“一個(gè)按結(jié)構(gòu)化編程思想設(shè)計(jì)的流程圖,每個(gè)模塊大小適中、模塊之間關(guān)系簡(jiǎn)明、模塊內(nèi)部線路清晰,單從視覺上就會(huì)給人一種美感。相反,如果采用非結(jié)構(gòu)化的設(shè)計(jì),流程圖往往結(jié)構(gòu)如雜草般松散紊亂、脈絡(luò)如迷宮般錯(cuò)綜復(fù)雜、箭頭如線頭般剪不斷理還亂,情節(jié)嚴(yán)重的會(huì)導(dǎo)致讀者頭暈?zāi)垦D酥磷タ裢卵?#8221;冒號(hào)極盡夸張之能事。
眾人掩口失聲。
,插語
[1] 數(shù)據(jù)流機(jī)支持?jǐn)?shù)據(jù)流式語言,歸約機(jī)支持函數(shù)式語言。
[2] 見參考文獻(xiàn)【1】
[3] 1967年,E.W. Dijkstra 在其著名論文“Goto statement considered harmful”中指出goto語句的危害性,主張廢除這種用法。
[4] 1974年,Donald Knuth在論文“Structured Programming with Goto Statements”中認(rèn)為goto語句仍有其合理性,應(yīng)該限制而不是完全摒棄。
[5] 也稱“自頂向下、逐步求精”。
。總結(jié)
· 命令式編程通過一系列改變程序狀態(tài)的指令來完成計(jì)算,聲明式編程只描述程序應(yīng)該完成的任務(wù)。命令式編程模擬電腦運(yùn)算,是行動(dòng)導(dǎo)向的,關(guān)鍵在于定義解法,即“怎么做”,因而算法是顯性而目標(biāo)是隱性的;聲明式編程模擬人腦思維,是目標(biāo)驅(qū)動(dòng)的,關(guān)鍵在于描述問題,即“做什么”,因而目標(biāo)是顯性而算法是隱性的。
· 結(jié)構(gòu)化編程是過程式編程的一種原則,其主要思想是:提倡在宏觀上采用‘自頂向下’的設(shè)計(jì),微觀上采用順序、選擇和循環(huán)的邏輯結(jié)構(gòu),摒棄或限制goto語句,以保證程序結(jié)構(gòu)清晰、易于調(diào)試和維護(hù)。
“”參考
[1] Corrado B?hm,Giuseppe Jacopini.Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules. Communications of the ACM,1966,9(5):366–371.
[2] Ravi Sethi.Programming Languages: Concepts & Constructs(英文版第2版).北京:機(jī)械工業(yè)出版社,2002.59-77
posted on 2008-11-03 23:16 鄭暉 閱讀(2910) 評(píng)論(2) 編輯 收藏 所屬分類: 冒號(hào)課堂