NEO.K / PLDST程式語言設計師風格譜系
編號PLDST-025
版本v1.0
日期2026-07-30
作者Neo.K
狀態公開版/第四部跨設計師正式比較研究

下載 PDF ↓回到論文索引 ↗

Backus、McCarthy 與 Hickey:函數、符號與簡單性的不同道路

摘要

John Backus、John McCarthy 與 Rich Hickey 都曾把函數、組合、符號表示與簡單性置於程式語言設計的中心。然而,若只把三人共同歸入「函數式/Lisp/極簡設計」傳統,會同時誤解三者。

Backus 的後期工作不是一般意義上的 Lambda-calculus 語言推廣,而是試圖建立 Function-level programming:程式由完整函數及固定的 Combining forms 組成,不依賴命名參數、逐值變數、賦值與顯式遞迴。他希望程式語言同時成為程式代數,使程式可像方程式一樣在同一語言內被轉換、證明與求解。[R1][R2][R3]

McCarthy 的核心問題則不是先消除所有命名,而是讓機器能操作符號表達式、邏輯句子與可變大小結構。LISP 透過 S-expression、List、Recursive function、Conditional expression、Lambda、apply 與 eval,建立一個小型但具有極高生成力的符號核心。其簡單性是「少數表示與規則能生成整個活系統」,而不是「系統只有少量行為」。[R4][R5][R6]

Hickey 繼承 Lisp 的 Code-as-data、Macro、REPL 與函數組合,但將「簡單」重新定義為不交纏。Clojure 的重點不是宣稱真實世界沒有狀態,而是區分 Value、Identity、State、Reference 與 Time,讓不可變值、函數變換與受控參照各自承擔不同責任;再透過 Persistent data、宿主 JVM、Protocol、Transducer 與克制演化,把簡單性變成一項長期系統設計紀律。[R7][R8][R9][R10]

本文提出三種簡單性原型:

Backus:Algebraic Transformational SimplicityMcCarthy:Generative Symbolic SimplicityHickey:Decomplective Structural Simplicity\boxed{ \begin{aligned} Backus &: \text{Algebraic Transformational Simplicity}\\ McCarthy &: \text{Generative Symbolic Simplicity}\\ Hickey &: \text{Decomplective Structural Simplicity} \end{aligned} }

三者對「函數」的理解分別是:

Backus:函數是組合與程式代數的基本單位McCarthy:函數是遞迴符號計算與可執行語義的核心Hickey:函數是不可變值之間的可組合轉換\boxed{ \begin{aligned} Backus &: \text{函數是組合與程式代數的基本單位}\\ McCarthy &: \text{函數是遞迴符號計算與可執行語義的核心}\\ Hickey &: \text{函數是不可變值之間的可組合轉換} \end{aligned} }

本文以十四個共同軸比較三人:

  1. 原始問題;
  2. 函數的地位;
  3. 符號與資料;
  4. 命名;
  5. 變數與賦值;
  6. 遞迴;
  7. 組合;
  8. 語言核心;
  9. 語言延展;
  10. 狀態與時間;
  11. 形式推理;
  12. 宿主與實作;
  13. 複雜度配置;
  14. 歷史限制與自我修正。

核心結論是:

三者都追求簡單,但 Backus 希望程式可以被代數化,McCarthy 希望計算可以被符號化,Hickey 希望系統可以被去交纏化。

因此「簡單語言」至少包含三種不同工程政治:

關鍵詞: John Backus、John McCarthy、Rich Hickey、FP、LISP、Clojure、函數級程式設計、符號計算、簡單性、組合、不可變值、程式代數、PLDST


第一部分 比較方法:簡單究竟是什麼

一、不能以功能數量直接衡量簡單

一門語言的核心功能很少,不表示:

因此:

CoreSize↓⇏SystemComplexity↓CoreSize\downarrow \not\Rightarrow SystemComplexity\downarrow

二、簡單、容易、熟悉與小型必須分開

本文區分:

Simple≠Easy≠Familiar≠Small≠ShortSimple \neq Easy \neq Familiar \neq Small \neq Short

其中:


三、簡單性向量

定義:

S(L)=(Score,Scomposition,Srepresentation,Sstate,Sreasoning,Stool,Sevolution)\mathcal{S}(L)= ( S_{\text{core}}, S_{\text{composition}}, S_{\text{representation}}, S_{\text{state}}, S_{\text{reasoning}}, S_{\text{tool}}, S_{\text{evolution}} )

三位設計者優化的分量不同。


四、簡單性不是總量消失

更合理的模型是:

Ctotal=Csurface+Cruntime+Ccompiler+Clibrary+Cstate+Ctool+CgovernanceC_{\text{total}} = C_{\text{surface}} + C_{\text{runtime}} + C_{\text{compiler}} + C_{\text{library}} + C_{\text{state}} + C_{\text{tool}} + C_{\text{governance}}

設計者通常只能重分配,而不能消滅所有複雜度。


五、三種簡單性問題

Backus 問:

能否讓程式由少量可推導的函數組合構成,而不再逐字操縱狀態?

McCarthy 問:

能否用少數符號表示與遞迴規則,建立可自我解釋並持續生長的計算系統?

Hickey 問:

能否把值、身分、狀態、時間、資料處理與執行情境拆開,使每項機制只承擔清楚責任?


六、本文所稱「道路」

「道路」不是線性演進:

Backus → McCarthy → Hickey

事實上 McCarthy 的 LISP 早於 Backus 1977 年的 FP 論述,Hickey 則在數十年後重組 Lisp、函數式與產業平台。

本文比較的是三種概念路線,而不是單一路線的前後版本。


第二部分 共同基底:三人為何可以比較

七、都拒絕讓機器偶發細節主導語言

Backus 批判 Word-at-a-time、Storage cell、Assignment 與 Jump 對語言的支配。[R1]

McCarthy 建立與 IBM 704 相對獨立的 S-expression 與 Recursive function 表示,使符號問題不必直接映射固定記憶體陣列。[R4]

Hickey 讓值保持不可變,將變化放入明確 Reference semantics,而不是把記憶體位置內容直接等同於事物狀態。[R8]


八、都把函數提高為一級構造

三者都拒絕把函數只視為:

但三者提高函數的方式不同。


九、都追求組合

NewProgram=Combine(ExistingPrograms)NewProgram = Combine(ExistingPrograms)

然而:


十、都把執行系統視為語言的一部分

三者的成果都不能只靠語法:


十一、都不是純粹功能刪除

三者都不是把語言縮小到不能工作。

Backus 希望少量 Combining forms 產生高階程式。

McCarthy 希望小型核心能生成新的語言能力。

Hickey 希望功能不交纏,並以宿主平台與資料導向擴張。


十二、都面對現實邊界

所以三者都證明:

ConceptualSimplicity≠CompleteSystemSimplicityConceptualSimplicity \neq CompleteSystemSimplicity

第三部分 Backus:把程式提升為函數代數

十三、問題不是函數不足,而是程式仍被狀態語法統治

Backus 將傳統語言看成馮紐曼機器的高階複製:

其批判不是「效能太低」,而是:

機器架構同時成為人類思想的瓶頸。


十四、Word-at-a-time 思考

馮紐曼瓶頸不只是 CPU 與 Memory 之間的資料通道,也是一種概念瓶頸:

Problem→SequenceOfWordOperationsProblem \rightarrow SequenceOfWordOperations

人必須把大尺度轉換拆成大量地址、載入、儲存及更新。


十五、Function-level 與 Value-level

Backus 的 FP 特別區分:

在 FP 中:

程式就是函數
新程式由既有函數與固定 Combining forms 建立
不必反覆命名每個輸入值

十六、函數是程式單位

Backus 的函數不是只接受值並回傳值。

它同時是:


十七、Combining forms

Combining forms 可由既有函數建立新函數,例如:

其目標為:

f1,f2,…,fn→ϕgf_1,f_2,\ldots,f_n \xrightarrow{\phi} g

其中 ϕ\phi 本身具有可理解的代數律。


十八、固定組合機制的政治

Backus 並不主張每個使用者任意發明無數組合形式。

他警告:

UnrestrictedCombiningFreedom⇒ChaosUnrestrictedCombiningFreedom \Rightarrow Chaos

因此 FP 偏好:


十九、程式代數

Backus 希望:

ProgramEquation↔AlgebraicEquationProgramEquation \leftrightarrow AlgebraicEquation

程式語言同時是:

而不是另用一套外部邏輯只「談論」程式。[R1]


二十、同一語言內推理

理想狀態為:

P=QP = Q

既表示兩個程式計算同一函數,也允許用代數律把 PP 逐步轉換成 QQ 。

因此:

Programming+Transformation+ProofProgramming + Transformation + Proof

不再被完全分開。


二十一、無命名並非反符號

Backus 反對的是高密度命名與替換機制對程式結構的支配,而不是所有符號。

FP 仍需要:

但它試圖避免:

為每一次值流動建立局部名稱,並讓名稱管理成為主要程式工作。


二十二、無顯式遞迴

許多 FP 程式可透過高階 Combining forms 隱含遞迴行為,而不直接寫自我呼叫。

這將責任移至:


二十三、資料作為整體

Backus 希望程式處理:

而不是逐字操作。

因此:

UnitOfThought↑UnitOfThought \uparrow

二十四、狀態沒有完全消失

Backus 並非否認歷史敏感系統需要狀態。

他提出 Applicative state transition 系統,希望:

所以:

StateFrequency↓StateSemanticCoupling↓StateFrequency\downarrow \quad StateSemanticCoupling\downarrow

而不是:

State=0State=0

二十五、Backus 的簡單性

Backus 的簡單性為:

SB=FixedCombiningForms+AlgebraicLaws+NoValueVariables+LargeConceptualUnits−WordAtATimeControlS_B = FixedCombiningForms + AlgebraicLaws + NoValueVariables + LargeConceptualUnits - WordAtATimeControl

二十六、實作與現實限制

Backus 後來承認:

這使 Backus 的簡單性具有強烈反身性:

他不只批判舊語言,也批判自己方案未完成之處。


二十七、Backus 原型

本文將 Backus 判定為:

Algebraic Transformational Simplifier\boxed{ \text{Algebraic Transformational Simplifier} }

其核心命題:

只有當程式可以由少量函數組合建立,並能在同一語言內推導與轉換,抽象才真正脫離逐字操作。


第四部分 McCarthy:把計算統一為符號遞迴系統

二十八、問題先於簡潔語法

LISP 的原始需求是讓 Advice Taker 操作:

因此 McCarthy 不是先問:

怎樣設計最少語法?

而是問:

什麼表示能讓機器處理任意大小與深度的符號結構?


二十九、S-expression

S-expression 以兩項基本規則建立:

  1. Atom 是 S-expression;
  2. 若 e1,e2e_1,e_2 是 S-expression,則 Pair 也是 S-expression。

這產生:


三十、符號是可操作對象

傳統數值語言主要計算:

Number→NumberNumber\rightarrow Number

LISP 擴張為:

SymbolicExpression→SymbolicExpressionSymbolicExpression \rightarrow SymbolicExpression

程式可:


三十一、函數是遞迴規則

McCarthy 的函數觀包含:

函數描述符號結構如何被分解與重組。


三十二、條件式成為表達式

cond 使分支進入函數定義:

Branch∈ExpressionBranch \in Expression

計算不必完全分成:

Expression world
Statement world

這一點與 Backus 對傳統語言分裂的批判形成呼應。


三十三、遞迴對齊資料結構

若資料是遞迴樹:

Data=Atom  ∪  Pair(Data,Data)Data = Atom \;\cup\; Pair(Data,Data)

則程式也可遞迴:

Program(Data)=Case(Atom)  ∪  Combine(Program(left),Program(right))Program(Data) = Case(Atom) \;\cup\; Combine(Program(left),Program(right))

問題、資料與控制結構因此互相對齊。


三十四、Lambda 的角色

McCarthy 使用 Lambda 表示:

這與 Backus 後期試圖減少 Lambda 式變量替換形成直接張力。


三十五、apply 與 eval

1960 年論文中的 Universal S-function:

FormalDefinition→ExecutableSemanticsFormalDefinition \rightarrow ExecutableSemantics

三十六、程式即資料

當程式與資料都使用 S-expression:

Representation(program)=Representation(data)Representation(program) = Representation(data)

因此程式可以:


三十七、極小核心是生成器

McCarthy 的簡單性不是:

所有 Lisp 程式都很短

而是:

少量原語可以生成大量語言能力

可表示為:

GenerativePower=ReachableLanguageSpaceCoreMechanismsGenerativePower = \frac{ReachableLanguageSpace}{CoreMechanisms}

三十八、Reader 與 Printer

統一表示需要:

因此括號背後是一整個運行制度。


三十九、GC 的人本與理論價值

若使用者必須手工回收 List node:

SymbolicAbstraction→MemoryBookkeepingSymbolicAbstraction \rightarrow MemoryBookkeeping

GC 把儲存生命週期交給 Runtime,使符號操作保持高階。


四十、互動環境

LISP 很快包含:

小核心因此變成 Live system。


四十一、可延展性

McCarthy 型簡單性允許使用者建立:

簡單性因此帶來權力,而不是只帶來限制。


四十二、生成性代價

SmallCore+Metaprogramming+DynamicRepresentation⇒LargeEmergentLanguageSmallCore + Metaprogramming + DynamicRepresentation \Rightarrow LargeEmergentLanguage

代價包括:


四十三、偶發穩定

McCarthy 原本區分 M-expression 與 S-expression,後者偏向內部表示。

但因 M-expression 未完成普及:

IntermediateRepresentation→SurfaceSyntaxIntermediateRepresentation \rightarrow SurfaceSyntax

Lisp 最具代表性的表面,部分來自歷史偶發,而非完整預定終局。


四十四、符號統一的邊界

統一表示不表示:

Lisp 後代必須持續補充:


四十五、McCarthy 的簡單性

SM=UniformRepresentation+RecursiveCore+ExecutableSemantics+ProgramDataUnity−PrimitiveDiversityS_M = UniformRepresentation + RecursiveCore + ExecutableSemantics + ProgramDataUnity - PrimitiveDiversity

四十六、McCarthy 原型

本文將 McCarthy 判定為:

Generative Symbolic Simplifier\boxed{ \text{Generative Symbolic Simplifier} }

其核心命題:

一個核心若能統一資料、程式與語義,便不必預先內建所有未來能力;使用者可以讓語言從內部繼續生長。


第五部分 Hickey:把交纏拆成值、身分、狀態與時間

四十七、繼承 Lisp,但不複製 Lisp

Clojure 繼承:

但 Hickey 重新選擇:


四十八、Simple 不等於 Easy

〈Simple Made Easy〉區分:

Simple=NotIntertwinedSimple = NotIntertwined Easy=NearToExistingAbilityEasy = NearToExistingAbility

熟悉的物件可變模型可能容易,卻不簡單。

不熟悉的 Persistent value 可能不容易,卻更容易被獨立理解。[R7]


四十九、Complect

Complect 指:

把原本可獨立變化、推理或替換的概念編織成同一件事。

例如:


五十、Value

Value 是:

Valuet≠Valuet+1Value_t \neq Value_{t+1}

新值不是舊值被修改,而是另一個值。


五十一、Identity

Identity 是跨時間指稱同一事物的名稱:

Identity 不等於任何單一 State。


五十二、State

State(identity,t)=ValuetState(identity,t)=Value_t

某 Identity 在時間 tt 關聯一個不可變值。

變化表示:

Value0→Value1→Value2Value_0 \rightarrow Value_1 \rightarrow Value_2

由 Identity 串接,而不是舊值本體被改造成新值。


五十三、Reference

Reference 管理:

Clojure 使用 Ref、Atom、Agent、Var 等不同構造,不讓單一「可變變數」概念承擔所有狀態語義。


五十四、函數是值轉換

Hickey 型函數主要是:

f:Value→Valuef:Value\rightarrow Value

函數可在沒有 Identity 更新的情況下先計算新值。

狀態變化再由明確參照機制提交。


五十五、計算與提交分離

newValue=f(oldValue)newValue=f(oldValue)

與:

Reference←newValueReference\leftarrow newValue

是兩項不同責任。

這讓:

更容易。


五十六、Persistent data

不可變若每次完整複製,成本過高。

Persistent data structure 以結構共享使:

UpdateCost≪FullCopyCostUpdateCost \ll FullCopyCost

Runtime 承擔結構複雜度,使用者獲得穩定值語義。


五十七、資料高於物件封裝

Clojure 傾向使用開放資料:

行為多由 Namespace 中函數處理,而不是每種資料都封裝於可變物件。


五十八、函數與資料保持可分離

傳統物件可能將:

Data+Identity+Methods+Mutation+LifecycleData + Identity + Methods + Mutation + Lifecycle

綁成同一單位。

Hickey 偏好:

Data+Functions+ExplicitReferencesData \quad+\quad Functions \quad+\quad ExplicitReferences

五十九、Sequence abstraction

Clojure 的 Sequence 讓多種 Collection 可由共同函數操作。

這保留 McCarthy 式統一操作精神,但不要求所有資料都實際是 List。


六十、Transducer

Transducer 將資料轉換 Algorithm 從:

中拆開。

可抽象為:

Transformation≠CollectionTraversalContextTransformation \neq CollectionTraversalContext

這是 Hickey 去交纏方法的典型後續。


六十一、宿主平台槓桿

Clojure 不建立自己的完整 OS、VM 與 Library 世界。

它使用:

因此:

NewSemanticModel+ExistingIndustrialRuntimeNewSemanticModel + ExistingIndustrialRuntime

六十二、簡單不等於獨立實作

依賴 JVM 會降低 Clojure 自建能力數量,卻引入:

所以:

CoreSimplicity+HostComplexityCoreSimplicity + HostComplexity

同時存在。


六十三、克制核心演化

Hickey 與 Clojure Core 長期傾向:

這使簡單性成為治理准入條件。


六十四、Hickey 的簡單性

SH=SeparationOfConcerns+ImmutableValues+ExplicitStateSemantics+ComposableFunctions+HostLeverage−ComplectingS_H = SeparationOfConcerns + ImmutableValues + ExplicitStateSemantics + ComposableFunctions + HostLeverage - Complecting

六十五、Hickey 原型

本文將 Hickey 判定為:

Decomplective Structural Simplifier\boxed{ \text{Decomplective Structural Simplifier} }

其核心命題:

系統難以理解,往往不是因為功能太多,而是因為本可分離的概念被綁成同一個機制;簡單性首先是解除交纏。


第六部分 第一比較軸:函數究竟是什麼

六十六、Backus:程式本身

Backus 的函數主要是:

他希望避免把注意力放在每個參數名與值替換上。


六十七、McCarthy:遞迴符號規則

McCarthy 的函數主要是:


六十八、Hickey:值之間的轉換

Hickey 的函數主要是:


六十九、三種函數尺度

Backus:ProgramScaleFunctionMcCarthy:SymbolicRecursiveFunctionHickey:ValueTransformationFunction\boxed{ \begin{aligned} Backus &: ProgramScaleFunction\\ McCarthy &: SymbolicRecursiveFunction\\ Hickey &: ValueTransformationFunction \end{aligned} }

七十、函數並非同義詞

把三者都稱為 Functional programming 會掩蓋:


第七部分 第二比較軸:符號與資料

七十一、Backus:降低值名稱支配

Backus 希望程式主要呈現:

符號服務於函數級關係,而不是逐步地址操作。


七十二、McCarthy:符號是計算材料

McCarthy 把 Atom、List 與 S-expression 建立為:

符號在其系統中具有本體中心地位。


七十三、Hickey:從符號中心轉向值中心

Clojure 保留 Symbol 與 S-expression,但更強調:

程式即資料仍重要,但「資訊是值」比「一切都是 List」更中心。


七十四、表示統一程度

RepresentationUnity:McCarthy>Hickey>BackusRepresentationUnity: McCarthy > Hickey > Backus

但這不是優劣排名。

Backus 更關心程式組合,McCarthy 更關心統一符號表示,Hickey 更關心不同資料角色保持清楚。


第八部分 第三比較軸:命名、變數與替換

七十五、Backus:反命名密度

Backus 認為大量變數與 Naming convention:


七十六、McCarthy:命名是遞迴與符號操作資源

LISP 使用:

命名不是應消除的負擔,而是符號計算核心。


七十七、Hickey:區分名稱與值

Clojure 的 Symbol/Var/Value 分開:

這是對 Lisp 命名模型的再結構化。


七十八、命名成本公式

Cname=Creation+Scope+Resolution+Substitution+MutationAmbiguityC_{\text{name}} = Creation + Scope + Resolution + Substitution + MutationAmbiguity

Backus 主要降低 Creation 與 Substitution。

McCarthy 利用 Name 生成語言能力。

Hickey 主要降低 MutationAmbiguity,並以 Namespace 管理 Resolution。


第九部分 第四比較軸:組合

七十九、Backus:固定 Combining forms

g=ϕ(f1,…,fn)g=\phi(f_1,\ldots,f_n)

組合形式數量受限,並具有代數律。


八十、McCarthy:Lambda、List 與 Macro 生長

組合來自:

其可生成空間更開放。


八十一、Hickey:資料、函數、Protocol 與 Transducer

組合來自:

但核心功能加入受到較強治理克制。


八十二、組合自由與推理性

CompositionFreedom↑⇒PotentialVariation↑CompositionFreedom\uparrow \Rightarrow PotentialVariation\uparrow

Backus 以固定形式換取推理。

McCarthy 以開放生成換取延展。

Hickey 以結構分離與保守核心換取長期可理解性。


第十部分 第五比較軸:遞迴

八十三、Backus:把遞迴封裝進組合形式

使用者不必反覆寫:

function calls itself

而以高階結構表示:


八十四、McCarthy:遞迴是語言本體

Recursive function 是 LISP 形式核心之一。

資料與程式都由遞迴規則構成。


八十五、Hickey:遞迴是可用機制,但不必支配日常

Clojure 支援:

日常程式通常由 Library 高階函數承擔遞迴。


八十六、遞迴的三種責任分配

Backus:遞迴下沉到 Combining forms
McCarthy:遞迴顯性成為形式定義
Hickey:遞迴多下沉到資料操作與 Library

第十一部分 第六比較軸:狀態與時間

八十七、Backus:降低狀態耦合

Backus 不滿意每個微小計算都修改全域機器狀態。

其目標:

Computation≫StateTransitionFrequencyComputation \gg StateTransitionFrequency

八十八、McCarthy:形式核心 Applicative,系統很快加入命令能力

1960 年 LISP 核心以函數與 S-expression 描述,但實際系統已包含:

因此:

PureFormalCore≠EntireOperationalSystemPureFormalCore \neq EntireOperationalSystem

八十九、Hickey:狀態重新建模

Hickey 不試圖把狀態藏起來,而是要求:

Identity≠State≠Value≠Reference≠TimeIdentity \neq State \neq Value \neq Reference \neq Time

九十、Backus 與 Hickey 的重要差異

Backus 的主要策略:

讓狀態轉換更少、更大尺度、更鬆耦合。

Hickey 的主要策略:

讓狀態轉換具有明確 Identity、Reference、時間與協調語義。


九十一、McCarthy 的中間位置

McCarthy 提供函數式形式核心,但其真正革命是符號與語言自我表示,而不是完整狀態理論。

後代 Lisp 因此可採:


第十二部分 第七比較軸:形式推理

九十二、Backus:代數轉換

推理理想:

P=P1=P2=⋯=QP = P_1 = P_2 = \cdots = Q

每一步由程式代數律支持。


九十三、McCarthy:遞迴形式與 Universal function

推理理想:

它建立語言的數學與執行連接。


九十四、Hickey:局部可推理性

Hickey 追求:

不是建立完整程式代數,而是降低推理所需同時追蹤的維度。


九十五、三種推理對象

Backus:程式等式McCarthy:符號函數與語言語義Hickey:值、時間與責任邊界\boxed{ \begin{aligned} Backus &: \text{程式等式}\\ McCarthy &: \text{符號函數與語言語義}\\ Hickey &: \text{值、時間與責任邊界} \end{aligned} }

第十三部分 第八比較軸:核心與延展

九十六、Backus:核心固定,程式由組合擴張

StableCombinators→NewProgramsStableCombinators \rightarrow NewPrograms

他反對不斷把特殊功能加入 Framework。


九十七、McCarthy:核心小,語言可由自身擴張

SmallCore+ProgramAsData+Eval→NewLanguageFormsSmallCore + ProgramAsData + Eval \rightarrow NewLanguageForms

九十八、Hickey:核心克制,擴張依靠資料、函數、宿主與 Library

ConservativeCore+JVM+Library+Macro+Protocol→EcosystemConservativeCore + JVM + Library + Macro + Protocol \rightarrow Ecosystem

九十九、延展性的不同治理


第十四部分 第九比較軸:宿主、機器與實作

一百、Backus:尋找非馮紐曼整體系統

Backus 希望:

共同脫離馮紐曼模型。

這是一種高風險整體替代。


一百零一、McCarthy:形式獨立,實作進入 IBM 704

S-expression 與 S-function 被描述為與特定機器獨立。

但實際成功依賴:


一百零二、Hickey:語義重建,宿主不重建

Clojure 主動接受 JVM:


一百零三、替代幅度

SystemReplacement:Backus>McCarthy>HickeySystemReplacement: Backus > McCarthy > Hickey

其中:


第十五部分 複雜度配置

一百零四、Backus 的配置

降低:

增加:


一百零五、McCarthy 的配置

降低:

增加:


一百零六、Hickey 的配置

降低:

增加:


一百零七、三種複雜度搬運

Backus:操作複雜度→組合代數與系統實作McCarthy:表示複雜度→Runtime 與語言內生成Hickey:狀態複雜度→值結構與明確參照\boxed{ \begin{aligned} Backus &: \text{操作複雜度}\rightarrow\text{組合代數與系統實作}\\ McCarthy &: \text{表示複雜度}\rightarrow\text{Runtime 與語言內生成}\\ Hickey &: \text{狀態複雜度}\rightarrow\text{值結構與明確參照} \end{aligned} }

第十六部分 歷史張力:三人並不是和諧同派

一百零八、Backus 對 Lambda 傳統的批評

Backus 認為 Lambda-calculus 型系統雖強大,卻仍帶有:

等複雜性。

這直接區別於 McCarthy。


一百零九、McCarthy 的成功反駁了部分疑慮,也證實部分疑慮

Lisp 的歷史顯示:

同時也顯示:

確實會累積。


一百一十、Hickey 對 Lisp 的選擇性繼承

Hickey 保留:

但拒絕或重構:


一百一十一、Hickey 不是 Backus 的直接完成者

Clojure 並沒有實作 Backus FP 的固定 Function-level algebra。

它仍使用:

所以 Hickey 與 Backus 的共同點是反交纏與重視值轉換,不是語言機制相同。


一百一十二、McCarthy 不是只有歷史中介

McCarthy 提出的核心統一具有獨立方向:

Program=Data=SymbolicExpressionProgram = Data = SymbolicExpression

這一方向既不同於 Backus 的 Program algebra,也不同於 Hickey 的 Value/Identity separation。


第十七部分 反例與去神話

一百一十三、Backus 不等於現代函數式語言總代表

Backus FP:

不能把 Haskell、ML、Scheme、Clojure 全部直接回寫為其方案。


一百一十四、McCarthy 不等於 Lisp 所有成果

LISP 是多人系統:

eval 成為 Interpreter 的實作洞見尤其不能只歸於 McCarthy。


一百一十五、Hickey 的簡單不表示 Clojure 容易

Clojure 仍要求理解:

簡單性是結構目標,不是入門成本保證。


一百一十六、小核心不等於小生態

SmallLanguageKernel+Time+Users+Libraries=LargeOperationalSystemSmallLanguageKernel + Time + Users + Libraries = LargeOperationalSystem

Lisp 與 Clojure 都證明核心與實際工作環境必須分開評估。


一百一十七、不可變不等於沒有時間

Hickey 不是消除時間,而是讓時間顯性:

Identity→tValuetIdentity \xrightarrow{t} Value_t

Backus 也承認歷史敏感系統需要某種狀態轉換。


一百一十八、形式優雅不能自動處理外部世界

都需要額外模型。

三人的簡單性方案都必須在此接受壓力測試。


第十八部分 PLDST 十四軸比較矩陣

一百一十九、比較矩陣

軸 Backus McCarthy Hickey
原始問題 擺脫逐字狀態控制 操作符號與形式知識 拆開值、身分、狀態與時間
函數地位 完整程式與代數單位 遞迴符號函數與語義 不可變值之間的轉換
符號地位 降低值命名支配 計算的基本材料 保留 Lisp Symbol,但轉向值與資料
命名態度 減少命名與替換 命名、Lambda、Symbol 為核心 區分 Symbol、Var、Binding、Value
變數/賦值 強烈批判 形式核心弱化,實際系統納入 Local binding 與明確 Reference 分離
遞迴 多封裝進 Combining forms 核心形式 多由 Library/Sequence/Reduce 承擔
組合 固定 Combining forms Lambda、List、eval、Macro Function、Data、Protocol、Transducer
核心 小且固定 小且生成性高 小而克制,宿主槓桿大
延展 組合既有函數 語言內生成新形式 Library、Macro、Protocol、JVM
狀態 降低頻率與語義耦合 核心 Applicative,系統混合 Value/Identity/Reference 明確分離
形式推理 程式代數 遞迴函數與可執行語義 局部可推理與責任分離
宿主策略 傾向整體替代 形式獨立、落地 IBM 704 JVM 共生
主要優勢 可轉換、可推導、大尺度思考 統一表示、自我延展、活系統 並發可推理、資訊穩定、實用生態
主要風險 I/O/完整系統不足 方言、動態、安全、工具 學習、宿主複雜度、集中治理

一百二十、三種目標函數

Backus:

JB=αAalgebra+βCcomposition+γUlarge-unit−λVvalue-variable−μSstate-couplingJ_B = \alpha A_{\text{algebra}} + \beta C_{\text{composition}} + \gamma U_{\text{large-unit}} - \lambda V_{\text{value-variable}} - \mu S_{\text{state-coupling}}

McCarthy:

JM=αUrepresentation+βGgenerativity+γEexecutable-semantics−λPprimitive-diversityJ_M = \alpha U_{\text{representation}} + \beta G_{\text{generativity}} + \gamma E_{\text{executable-semantics}} - \lambda P_{\text{primitive-diversity}}

Hickey:

JH=αDdecomplecting+βVimmutability+γRexplicit-state+δHhost-leverage−λIintertwiningJ_H = \alpha D_{\text{decomplecting}} + \beta V_{\text{immutability}} + \gamma R_{\text{explicit-state}} + \delta H_{\text{host-leverage}} - \lambda I_{\text{intertwining}}

這些是本文分析模型,不是三人提出的量化公式。


第十九部分 對新語言設計的實際啟示

一百二十一、先回答你要的是哪種簡單

新語言應明確選擇:

代數可推導?
核心少且生成力高?
責任不交纏?
入門熟悉?
表面短?
工具容易?
生態一致?

不能用「簡單」一詞同時代替全部目標。


一百二十二、建立簡單性負擔表

每個設計決策應記錄:

刪除了什麼概念?
複雜度被搬到哪一層?
使用者還要理解什麼?
Runtime 新增什麼責任?
Tooling 能否恢復隱藏資訊?
是否增加語言內生成權力?
是否增加狀態或時間歧義?
是否形成新的治理瓶頸?

一百二十三、建立函數尺度標記

語言文件應說明函數主要被用作:

否則「支援函數式」資訊不足。


一百二十四、建立符號權力邊界

若程式與資料統一,必須設計:

McCarthy 的生成性必須配合現代邊界。


一百二十五、建立狀態頻率與狀態語義雙指標

Backus 提醒我們降低:

Frequency(StateTransition)Frequency(StateTransition)

Hickey 提醒我們明確:

Semantics(StateTransition)Semantics(StateTransition)

兩者缺一不可。


一百二十六、固定組合與開放延展需分層

可以設計:

核心層:少量固定、可推導組合
語言層:受限 Macro/Protocol
程式庫層:開放組合
應用層:領域 DSL

這是三人路線可互補之處。


一百二十七、宿主不是免費午餐

使用既有 Runtime 可節省:

但必須公開宿主洩漏:


一百二十八、不要把簡單性道德化

複雜需求有時真的需要:

簡單性不是把所有複雜需求稱為錯誤,而是讓複雜度具有可辨識位置。


第二十部分 統一結論

一百二十九、三人共同反對的是什麼

三者共同反對:

讓使用者在沒有必要時,替機器、表示或歷史偶發支付重複認知成本。


一百三十、三人的分歧

Backus 認為根本問題是:

Programming≈WordAtATimeStateManipulationProgramming \approx WordAtATimeStateManipulation

McCarthy 認為根本機會是:

Programs can manipulate Programs as symbolsPrograms \text{ can manipulate } Programs \text{ as symbols}

Hickey 認為根本問題是:

Concepts are complectedConcepts \text{ are complected}

一百三十一、三種簡單性憲法

Backus:

語言應以少量固定函數組合建立程式,並具有可用於程式轉換與證明的代數。

McCarthy:

語言應以統一符號表示與遞迴語義形成小型生成核心,使程式能操作並延展自身語言。

Hickey:

語言應把值、身分、狀態、時間與處理情境分離,讓必要變化具有明確邊界。


一百三十二、三種複雜度政治

Backus:限制組合語彙,以換取代數推理McCarthy:統一表示語彙,以換取生成能力Hickey:分離責任語彙,以換取結構理解\boxed{ \begin{aligned} Backus &: \text{限制組合語彙,以換取代數推理}\\ McCarthy &: \text{統一表示語彙,以換取生成能力}\\ Hickey &: \text{分離責任語彙,以換取結構理解} \end{aligned} }

一百三十三、三者可否混合

可以,但不是簡單相加。

例如一門新語言可同時採:

但會產生衝突:


一百三十四、最終 PLDST 判定

John Backus:Algebraic Transformational SimplifierJohn McCarthy:Generative Symbolic SimplifierRich Hickey:Decomplective Structural Simplifier\boxed{ \begin{aligned} John\ Backus &: \text{Algebraic Transformational Simplifier}\\ John\ McCarthy &: \text{Generative Symbolic Simplifier}\\ Rich\ Hickey &: \text{Decomplective Structural Simplifier} \end{aligned} }

一百三十五、本文最後命題

簡單性不是「沒有東西」,而是決定哪些東西應該被固定、哪些東西可以生成,以及哪些東西絕不能被交纏。

因此:

Simplicity=Constraint+Generativity+Separation−UntrackedCoupling\boxed{ Simplicity = Constraint + Generativity + Separation - UntrackedCoupling }

Backus、McCarthy 與 Hickey 分別把其中一項推向極致:

這三條道路共同構成 PLDST 對「簡單性」最重要的比較基礎。


附錄 A PLDST 比較卡

比較組:John Backus/John McCarthy/Rich Hickey
主要語言/系統:FP/LISP/Clojure
共同命題:以函數與高階表示降低命令式偶發負擔

Backus:
核心問題=逐字狀態與命名支配
核心策略=Function-level、Combining forms、Program algebra
簡單性=固定組合與可推導轉換
複雜度去向=代數基礎、實作、I/O 與狀態整合
主要限制=完整系統與外部世界

McCarthy:
核心問題=符號知識與可變結構的計算
核心策略=S-expression、Recursion、Lambda、eval
簡單性=小型生成核心與統一表示
複雜度去向=Runtime、GC、Macro、方言與治理
主要限制=動態、安全、工具、分支

Hickey:
核心問題=值、身分、狀態、時間與情境交纏
核心策略=Immutable value、Reference semantics、Function、Host JVM
簡單性=解除交纏與責任分離
複雜度去向=Persistent structure、JVM、工具、學習與治理
主要限制=宿主洩漏、動態工具、集中演化

核心比較:
Backus=代數轉換型簡單性
McCarthy=生成符號型簡單性
Hickey=去交纏結構型簡單性

歸因信心:高

附錄 B 設計決策語料

人物 問題 決策 簡單性類型 複雜度去向 PLDST 標記
Backus 逐字控制支配程式 Function-level programming 代數/尺度 FP system B-F
Backus 程式難以同語言轉換 Program algebra 可推導 Algebra foundation B-A
Backus 自由組合可能混亂 固定 Combining forms 約束型 核心選擇 B-C
Backus 歷史系統仍需狀態 Applicative state transition 鬆耦合 State model B-S
McCarthy 符號結構長度不固定 List/S-expression 表示統一 GC/Runtime M-S
McCarthy 符號函數需遞迴 Conditional/Lambda/Label 生成核心 Dynamic execution M-R
McCarthy 語言需可執行定義 apply/eval 語義統一 Interpreter/Safety M-E
McCarthy 程式需操作程式 Program as data 延展型 Macro/Dialect M-P
Hickey 值與狀態被混同 Immutable values 去交纏 Persistent structure H-V
Hickey Identity 與更新規則混同 Ref/Atom/Agent/Var 責任分離 Runtime semantics H-I
Hickey Algorithm 綁定 Collection context Transducer 情境分離 Library abstraction H-T
Hickey 新語言重建成本過高 JVM symbiosis 宿主槓桿 Interop complexity H-J

附錄 C 來源與參考文獻

[R1] John Backus, “Can Programming Be Liberated from the von Neumann Style? A Functional Style and Its Algebra of Programs,” Communications of the ACM 21(8), 1978.
— 馮紐曼瓶頸、Function-level programming、Combining forms、Program algebra、Applicative state transition。

[R2] Grady Booch, “Oral History of John Backus,” Computer History Museum, 2006.
— Backus 對 FP 起源、I/O 困難、完整系統限制及後期自我評價的直接敘述。

[R3] Computer History Museum Software Preservation Group, “History of John Backus’s Functional Programming Project.”
— FP、FL、FFP、文件與實作歷史保存。

[R4] John McCarthy, “Recursive Functions of Symbolic Expressions and Their Computation by Machine, Part I,” Communications of the ACM 3(4), 1960.
— S-expression、S-function、Conditional、Lambda、apply、Interpreter、List structure 與 GC。

[R5] John McCarthy, “History of Lisp,” HOPL I, 1978/1979.
— LISP 問題形成、M-expression/S-expression、eval 實作與歷史歸因。

[R6] John McCarthy et al., LISP 1.5 Programmer’s Manual, MIT Press, 1962.
— Interpreter、Compiler、Reader/Printer、GC、實作團隊與早期系統。

[R7] Rich Hickey, “Simple Made Easy,” Strange Loop, 2011.
— Simple/Easy、Complect、Composition 與結構簡單性。

[R8] Rich Hickey, “Values and Change: Clojure’s Approach to Identity and State,” Clojure official site.
— Value、Identity、State、Reference、Time、STM 與 Agent。

[R9] Rich Hickey, “A History of Clojure,” Proceedings of the ACM on Programming Languages, HOPL IV, 2020.
— Clojure 形成、JVM、設計目標、Persistent data、Concurrency 與取捨。

[R10] Clojure official Rationale、Functional Programming、Development 與 Reference 文件。
— Dynamic compiled language、Persistent collection、Sequence、Host interop、克制演化與現行語義。

[R11] PLDST-011, John Backus:從 FORTRAN 到函數級程式設計的自我反省.
— 本系列前置個案研究。

[R12] PLDST-012, John McCarthy:極小核心、符號計算與語言可延展性.
— 本系列前置個案研究。

[R13] PLDST-021, Rich Hickey:價值、身分與簡單性的分離.
— 本系列前置個案研究。

資料查核日期: 2026-07-30。


附錄 D PLDST 比較標記

[B-F] Backus: function-level programming
[B-C] Backus: fixed combining forms
[B-A] Backus: algebra of programs
[B-V] Backus: anti word-at-a-time
[B-S] Backus: loose state coupling
[B-R] Backus: reflexive revision

[M-S] McCarthy: symbolic representation
[M-R] McCarthy: recursive core
[M-L] McCarthy: lambda and naming
[M-E] McCarthy: executable semantics
[M-P] McCarthy: program-data unity
[M-G] McCarthy: generative extensibility

[H-S] Hickey: simple-not-easy
[H-D] Hickey: decomplecting
[H-V] Hickey: immutable values
[H-I] Hickey: identity-state separation
[H-T] Hickey: transducer/context separation
[H-J] Hickey: JVM host leverage
[H-C] Hickey: conservative core evolution

[C-F] comparative function model
[C-S] comparative simplicity model
[C-R] representation politics
[C-T] time-state allocation
[C-X] extension governance
[C-B] complexity burden

附錄 E 第二輪史實、概念與比較校對紀錄

E.1 Backus FP 不是一般 Lambda 語言

重新核對圖靈獎演講:

因此本文使用:

Function-level programming

而沒有把 Backus 簡化成「現代純函數語言倡議者」。


E.2 Backus 沒有否認所有狀態

圖靈獎演講提出 Applicative state transition 系統,承認歷史敏感計算需要狀態轉換。

其要求是:

狀態轉換不應與每一個微小計算緊密耦合

而不是所有系統永遠無狀態。


E.3 Backus 對 FP 的後期修正

口述歷史明確指出:

本文因此沒有把 FP 描述成已完成的通用替代。


E.4 McCarthy 核心與實際 LISP 系統分開

1960 論文的形式核心以 S-function 與遞迴定義為主,但早期 LISP 系統已包含:

本文因此分開:

FormalCore≠OperationalSystemFormalCore \neq OperationalSystem

E.5 eval 歸因

McCarthy 提出 Universal function 的形式;Steve Russell 看出並實作其 Interpreter 意義;其他團隊成員建立 GC、Compiler、Reader/Printer 及系統。

本文不把整套 LISP 實作歸於 McCarthy 個人。


E.6 S-expression 的歷史偶發

McCarthy 原計畫以 M-expression 作外部語法、S-expression 作內部表示。

M-expression 沒有完成普及,使 S-expression 成為主要表面。

本文將其標記為:

事故性穩定

而非完全預定設計終局。


E.7 Hickey 的 Simple 定義

〈Simple Made Easy〉的 Simple 主要指:

它不等同:


E.8 Clojure 沒有宣稱完全純函數

官方資料明確稱 Clojure predominantly functional/impure,並提供 Ref、Atom、Agent、Var 及 Java interop。

本文使用:

函數式優先+明確變化邊界

而不是「完全純函數語言」。


E.9 Value 與 Identity

官方 Identity/State 文件明確區分:

本文的形式化為分析重述,不是官方原始數學公式。


E.10 三種 Simplifier 是本文原型

下列名稱不是三位設計者自稱:

Algebraic Transformational Simplifier
Generative Symbolic Simplifier
Decomplective Structural Simplifier

其用途是把「簡單性」分解成可比較的設計風格。


附錄 F 與下一篇的銜接

PLDST-025 比較三種簡單性:

代數轉換
符號生成
結構去交纏

PLDST-026 將從設計內容轉向設計權力:

當語言由個人創始者、仁慈獨裁者、核心團隊、標準委員會或 RFC 社群治理時,誰有權定義「這仍是同一門語言」?

下一篇預定為:

PLDST-026:個人設計者、仁慈獨裁者與 RFC 制度——語言治理風格比較。

原始檔

這篇論文的 Markdown 原始檔,與上方頁面和 PDF 由同一份來源產生。

下載 Markdown ↓