冒號轉入聲明式編程:「由若干規範聲明組成,即『已知這,求解那』,強調『做什麼』而非『怎麼做』。它是人腦思維的抽象,利用數理邏輯或既定規範推理運算。」
聲明式發軔於 AI 研究,主含函數式(將計算描述為數學函數求值)和邏輯式(提供事實規則推導結論)。Lisp 已有半世紀,Prolog 與 C 同齡,但多用於學術研究,「養在深閨人未識」。
C(命令式·迭代):
int factorial(int n) {
int f = 1;
for (; n > 0; --n) f *= n;
return f;
}
Lisp(函數式·遞歸定義):
(defun factorial(n)
(if (= n 0) 1
(* n (factorial(- n 1)))))
Prolog(邏輯式·斷言):
factorial(0,1).
factorial(N,F) :- M is N-1, factorial(M,Fm), F is N * Fm.
句號總結:「C 給出迭代算法,Lisp 描述遞歸定義,Prolog 陳述斷言。」
冒號指出思維定勢:
i = i + 1 合法這簡化代碼、減少調試——多少 bug 源於變量被意外改寫或內存管理不慎?
冒號佐證:調用 doWhat() 不正是聲明「what to do」?「how to do」封裝在函數內,這種聲明式風格提高抽象能力與開發效率,推動語言升級。
逗號疑惑:「聲明式這麼好,為何命令式仍佔多數且流行不減?」
冒號解釋:流行度與擅長領域相關。聲明式擅長 AI、符號處理、數據庫、編譯器;命令式擅長面向用戶、交互性強、事件驅動、業務邏輯千差萬別的應用——大多數軟體屬後者。
屬性導向編程(C# attribute、Java annotation)、數據流式編程(Prograph、SISAL)、約束式編程(Oz、CHIP)、SQL、XSLT、CSS、HTML、XML、SVG、IDL……算上它們,聲明式語言比例極可觀。之前未提,因許多無專門範式名稱,多為領域特定語言(DSL),甚至非圖靈完備。
問號發現 Lisp 遞歸可用 C 實現。冒號寫出 C 遞歸版,解釋:命令式提倡迭代(貼近機器),聲明式提倡遞歸(貼近數學)。聲明式不允許循環變量,迭代著眼微觀過程,遞歸著眼宏觀規律。尾遞歸可優化為迭代,本質是語法糖——循環變量是重新綁定而非重複賦值。
| 範式 | 程序視角 | 輸入 | 輸出 | 設計 | 運行機制 |
|---|---|---|---|---|---|
| 命令式 | 自動機 | 初始狀態 | 最終狀態 | 設計指令 | 命令執行 |
| 函數式 | 數學函數 | 自變量 | 因變量 | 設計函數 | 表達式變換 |
| 邏輯式 | 邏輯證明 | 題設 | 結論 | 設計命題 | 邏輯推理 |
冒號寬慰:「理論性強些,不解處大可不必介懷,撒下的種子總會萌動。休息片刻,廣告後更精彩。」
[1] Prograph 即 Programming in Graphics,可視化 OO 數據流語言。
[2] SISAL 即 Streams and Iteration in a Single Assignment Language,函數式數據流語言。
[3] 約束式編程通過數據約束關係運算,可借助邏輯推理或數學技巧。
[4] 尾遞歸:遞歸調用在最後一步,易轉為迭代優化。
[5] 部分聲明式語言支持迭代,但多用尾遞歸實現,本質是語法糖。