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、applyeval,建立一個小型但具有極高生成力的符號核心。其簡單性是「少數表示與規則能生成整個活系統」,而不是「系統只有少量行為」。[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⇏SystemComplexityCoreSize\downarrow \not\Rightarrow SystemComplexity\downarrow

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

本文區分:

SimpleEasyFamiliarSmallShortSimple \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 希望功能不交纏,並以宿主平台與資料導向擴張。


十二、都面對現實邊界

所以三者都證明:

ConceptualSimplicityCompleteSystemSimplicityConceptualSimplicity \neq CompleteSystemSimplicity

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

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

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

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

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


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

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

ProblemSequenceOfWordOperationsProblem \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 並不主張每個使用者任意發明無數組合形式。

他警告:

UnrestrictedCombiningFreedomChaosUnrestrictedCombiningFreedom \Rightarrow Chaos

因此 FP 偏好:


十九、程式代數

Backus 希望:

ProgramEquationAlgebraicEquationProgramEquation \leftrightarrow AlgebraicEquation

程式語言同時是:

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


二十、同一語言內推理

理想狀態為:

P=QP = Q

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

因此:

Programming+Transformation+ProofProgramming + Transformation + Proof

不再被完全分開。


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

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

FP 仍需要:

但它試圖避免:

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


二十二、無顯式遞迴

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

這將責任移至:


二十三、資料作為整體

Backus 希望程式處理:

而不是逐字操作。

因此:

UnitOfThoughtUnitOfThought \uparrow

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

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

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

所以:

StateFrequencyStateSemanticCouplingStateFrequency\downarrow \quad StateSemanticCoupling\downarrow

而不是:

State=0State=0

二十五、Backus 的簡單性

Backus 的簡單性為:

SB=FixedCombiningForms+AlgebraicLaws+NoValueVariables+LargeConceptualUnitsWordAtATimeControlS_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。

這產生:


三十、符號是可操作對象

傳統數值語言主要計算:

NumberNumberNumber\rightarrow Number

LISP 擴張為:

SymbolicExpressionSymbolicExpressionSymbolicExpression \rightarrow SymbolicExpression

程式可:


三十一、函數是遞迴規則

McCarthy 的函數觀包含:

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


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

cond 使分支進入函數定義:

BranchExpressionBranch \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 式變量替換形成直接張力。


三十五、applyeval

1960 年論文中的 Universal S-function:

FormalDefinitionExecutableSemanticsFormalDefinition \rightarrow ExecutableSemantics

三十六、程式即資料

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

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

因此程式可以:


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

McCarthy 的簡單性不是:

所有 Lisp 程式都很短

而是:

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

可表示為:

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

三十八、Reader 與 Printer

統一表示需要:

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


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

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

SymbolicAbstractionMemoryBookkeepingSymbolicAbstraction \rightarrow MemoryBookkeeping

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


四十、互動環境

LISP 很快包含:

小核心因此變成 Live system。


四十一、可延展性

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

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


四十二、生成性代價

SmallCore+Metaprogramming+DynamicRepresentationLargeEmergentLanguageSmallCore + Metaprogramming + DynamicRepresentation \Rightarrow LargeEmergentLanguage

代價包括:


四十三、偶發穩定

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

但因 M-expression 未完成普及:

IntermediateRepresentationSurfaceSyntaxIntermediateRepresentation \rightarrow SurfaceSyntax

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


四十四、符號統一的邊界

統一表示不表示:

Lisp 後代必須持續補充:


四十五、McCarthy 的簡單性

SM=UniformRepresentation+RecursiveCore+ExecutableSemantics+ProgramDataUnityPrimitiveDiversityS_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 是:

ValuetValuet+1Value_t \neq Value_{t+1}

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


五十一、Identity

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

Identity 不等於任何單一 State。


五十二、State

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

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

變化表示:

Value0Value1Value2Value_0 \rightarrow Value_1 \rightarrow Value_2

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


五十三、Reference

Reference 管理:

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


五十四、函數是值轉換

Hickey 型函數主要是:

f:ValueValuef:Value\rightarrow Value

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

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


五十五、計算與提交分離

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

與:

ReferencenewValueReference\leftarrow newValue

是兩項不同責任。

這讓:

更容易。


五十六、Persistent data

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

Persistent data structure 以結構共享使:

UpdateCostFullCopyCostUpdateCost \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 從:

中拆開。

可抽象為:

TransformationCollectionTraversalContextTransformation \neq CollectionTraversalContext

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


六十一、宿主平台槓桿

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

它使用:

因此:

NewSemanticModel+ExistingIndustrialRuntimeNewSemanticModel + ExistingIndustrialRuntime

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

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

所以:

CoreSimplicity+HostComplexityCoreSimplicity + HostComplexity

同時存在。


六十三、克制核心演化

Hickey 與 Clojure Core 長期傾向:

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


六十四、Hickey 的簡單性

SH=SeparationOfConcerns+ImmutableValues+ExplicitStateSemantics+ComposableFunctions+HostLeverageComplectingS_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

組合來自:

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


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

CompositionFreedomPotentialVariationCompositionFreedom\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 不滿意每個微小計算都修改全域機器狀態。

其目標:

ComputationStateTransitionFrequencyComputation \gg StateTransitionFrequency

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

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

因此:

PureFormalCoreEntireOperationalSystemPureFormalCore \neq EntireOperationalSystem

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

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

IdentityStateValueReferenceTimeIdentity \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:核心固定,程式由組合擴張

StableCombinatorsNewProgramsStableCombinators \rightarrow NewPrograms

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


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

SmallCore+ProgramAsData+EvalNewLanguageFormsSmallCore + ProgramAsData + Eval \rightarrow NewLanguageForms

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

ConservativeCore+JVM+Library+Macro+ProtocolEcosystemConservativeCore + 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 不是消除時間,而是讓時間顯性:

IdentitytValuetIdentity \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 認為根本問題是:

ProgrammingWordAtATimeStateManipulationProgramming \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+SeparationUntrackedCoupling\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 語言需可執行定義 applyeval 語義統一 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 系統已包含:

本文因此分開:

FormalCoreOperationalSystemFormalCore \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 制度——語言治理風格比較。