[備份] ◇ FORTH 之哲學

18 views
Skip to first unread message

letoh

unread,
Apr 3, 2011, 8:16:26 AM4/3/11
to 符式協會
[備份] ◇ FORTH 之哲學

Thinking FORTH 目前可以由網路上取得
http://thinking-forth.sourceforge.net/


====


◇ FORTH 之哲學


william@nctu_cis 註: 下文係節譯自 Leo Brodie 的名著 "Thinking FORTH" 第一章。
=================== ======-------^^^^^^^^^^--------
^^^^^^^^^^^^^^^^---------

發信人: ajax...@csie.nctu (ajax), 信區: programming
標 題: FORTH 之哲學
發信站: 交大資工鳳凰城資訊站 (Mon Nov 7 15:10:18 1994)
轉信站: cis_nctu!news.cis.nctu!news.cc.nctu!news.csie.nctu!bbsroute!
phoenix

======================
$$ FORTH 之哲學 $$
======================


FORTH 是一種電腦語言,也是作業系統。但這不是全部,他也可以說是一種哲
學的體現。這哲學通常不是除了 FORTH 之外另有所指,既不優於 FORTH ,也不在
討論 FORTH 之外,另外被描述,甚至就稱為 "FORTH" 。 這個哲學是什麼呢 ? 如
何用他來解決問題呢? 在解答這些問題之前,讓我們往回退一百步,探討一下這些
年中,由電腦科學家改進的一些主要的哲學。在探討這些進步的軌跡之後,我們將
要把這些程式原則和 FORTH 作一比較與對照。


+--------------------------------------------+
| 淺說軟體優雅性之發展 |
| (An armchair history of software elegance) |
+--------------------------------------------+

在程式的史前時代,電腦如恐龍一般,只有一些天才可以寫出可正確執行的程
式,這也是少是引起眾人讚嘆的原因。當電腦變得更普遍後,這種讚嘆也就消失了
,而經理人員從程式人員及程式需索更多。當硬體的成本持續地降低,相對的,軟
體的成本增加了,對程式的要求,不再滿足於正確無誤的執行,同時也要求能迅速
開發及容易維護。一種新的需求開始與正確性被同樣的重視,而此被忽視的品質即
是 " 優雅性 " (elegance) 。 在本節中,我們將概略地敘述關於寫出更優美的程
式的工具與技術的歷史。


可記憶性 (memorability)
=======================

最早的電腦程式看起來有點像這樣:

00110101
11010011
11011001

程式師由設定一排排的開關來輸入程式, 若對應的位數是 "1" 就設為 "on"
,若是 "0" 就設為 "off" ,這些值代表電腦的 " 機器指令 " ,每個指令指使電
腦做一些動作,如 " 將暫存器 A 的內容移到暫存器 B" 或 " 將暫存器 C 的內容
加到暫存器 A的內容中 " 。
這確實有點令人厭煩乏味,厭煩為發明之母,一些聰明的程式師想到電腦本身
可以提供一些幫助。所以他們寫一個程式來將易記的縮寫轉換成難記的數位碼。新
的語言看起來有點像這樣:

MOV B,A
ADD C,A
JMC REC1

這個轉換程式稱為 Assembler ,這個新的語言稱為組合語言。 根據組合指令
與機器指令一對一的對應關係,每一個指令組合成適當的對應位元組,但是程式師
比較容易記住名字,因新的指令稱為記憶碼 (mnemonics) 。


能力(power)
===========

組合語言程式的特性是機器按照程式師輸入的一條一條指令順序執行,事實上
,程式師發現他們在程式中,常常有一些相同作用的程式片段一再重覆,若有一個
名字可以代替這些相同的程式片段不是很美妙嗎!
"macro assembler" 正符合這需求, macro assembler 是一個更複雜的組合
語言, 不只認得一般的指令, 還可定義特殊的巨集,每一個巨集可由 assembler
展開成對應的五到十個機器指令,就好像程式師一個一個指令寫下來一樣。


抽象化(abstraction)
===================

高階語言的發明是一個重要的進步。這同樣是個轉換程式,但具有更強的能力
。高階語言使得程式師可以寫出像下面像代數式的程式:

X = Y(456/A) - 2

感謝高階語言的發明,不只是怪才可以寫程式,工程師也可以開始寫程式了。
BASIC 與 FORTRAN 是一個高階語言的例子。
由於高階語言的每一個指令都可以編譯成數十個指令,很顯然,高階語言比組
合語言更強,但其中更大的意義是,高階語言消弭了原始程式與產生的機器指令之
間的線性對應。
實際的指令是根據原始程式的 " 陳述 (statement)" 產生, 每個陳述都視為
一整體。如 + 與 = 的運算元本身並無意義,只是一個複雜符號中的一部份,其意
義需視語意與運算元的所在位置而定。
此種原始程式與目標碼間,非線性及語意相關的對應關係,普遍的被認為是程
式方法論的一項極重要的發展。但是我們將看到此種方式,只是使自由受到限制而
已。


可管理性(manageability)
=======================

大部份的程式都不是只按著程式中指令的順序從頭執行到結尾,還包括一些不
同的條件測試,然後根據測試結果跳躍 (branch) 至適當的程式部份,也包括迴圈
(looping) 可以一再地重覆程式中的相同部份,通常加上測試條件來跳出迴圈。
組合語言與高階語言都提供跳躍與迴圈的功能,在組合語言中,可以用 "jump
instructions" 在一些高階語言中可以用 "GO TO" 命令。當以任意的方式使用這
些功能時,程式看起來會像圖 1-1 所示一樣的混亂。
此種方式在 FORTRAN 與 BASIC 中仍廣為使用,得忍受著難寫及要修改時又難
以更動的痛苦。在這一類通心麵條式的程式中,不可能測試程式中的單獨一部份,
或瞭解為何程式不按預期的方式執行。
通心麵條式的程式的困境引起流程圖發現。流程圖是一些框和連線所構成的圖
畫,代表程式的進行,流程圖被用來幫助程式師瞭解撰寫中的程式。不幸的是,程
式師必須以手動的方式來作程式與流程圖之間的轉換,有許多程式師發現舊式的流
程圖沒多大用處。


模組化(modularity)
==================

結構化程式的發明造成一個重大的進展,結構化程式方法是基於一個大問題若
分成一些較小的問題較容易解決的想法。每一個小片段稱為一個模組 (module) 。
程式由模組構成,而模組又可由一些較小的模組構成。
結構化程式強調控制流程侷限於一個模組內,避免了通心麵條式的程式。一個
跳躍指令不能由一個模組中跳至另一個模組。
例如, 圖 1-2 是一個 "Make Breakfast" 模組的結構化圖形,由四個子模組
構成。每一個子模組中代表另一層次的複雜度,無須在這一層中表示出來。
在這模組中有一個判斷的分支來決定 "cold cereal" 模組或 "eggs" 模組,
不過流程控制保持在外層的模組。
結構化程式有三個前題:
1. 每個程式由一個線性順序自我包含 (self-contained) 的函式 (function)
描述,亦即模組,而且每一個模組只能有一個進入點及離開點。
2. 每一個模組由一個或多個函式構成, 而且每一個函式只能有一個進入點及
離開點,且函式本身也可用一個模組來描述。
3. 一個模組內包含:
a. 運算或其他模組
b. 判斷結構(IF THEN statements)
c. 迴圈結構
" 一個進入與一個離開 " 的構想是使一個模組可以拔出來,修改其內部,再插
回去,而不用牽涉程式中其他的部份。 也就是說每一個部份可以單獨測試,這只有
在真正瞭解一個模組開始的所在以及離開的所在才有可能。
在 "Make Breakfast" 的程式中只可以要 "fix cereal" 或 "make eggs" ,不
能兩樣都要, 並且都得 "clean up" ( 我認識一些程式師為了避免這最後一個模組
要每三個月搬一次家 ) 。
結構化程式最初只是被當作一個設計的方法, 模組只是在想像中加上標示,存
在程式師或設計者的腦海中, 並非真正的原始程式, 當結構化程式設計法用在像
BASIC 這樣的非結構化語言上,設計出來的程式有點像圖 1-3 中的一樣。


可寫性(writeability)
====================

結構化程式語言是推動使用結構化程式的一個突破, 這一類語言的指令中即包
括了控制結構,使寫出來的程式看起來就很有結構。 Niklaus Wirth 為了教導學生
結構化程式所發明的 Pascal 正是這一類語言。
圖1-4所示的是這一類語言使得可以寫出"Make Breakfast"的程式。
結構化程式語言包括了像 IF 及 THEN 一類的控制結構運算元, 可確保流程控
制的模組性。 正如你所見,標示對可讀性是很重要的,因為在一個模組中的所指令
都直接寫出來,而不是以一個名字作參考 ( 如 "MAKE-CEREAL") ,一個完成程式可
以有十頁之多,而 ELSE 可能在第五頁。


由上開始設計(designing from the top)
====================================

要如何來設計這些模組? " 由上而下設計 "(top-down design) 的方法論宣稱
,應該由最一般化且整體的模組開始設計,然後往下直到實際又瑣碎的模組。
提倡由上而下設計的擁護者, 由試圖更正已經完成的程式,即修補程式的痛苦
經驗,使他們瞭解由於缺少計劃將浪費許多時間,修補程式無異於亡羊補牢。
所以他們提出一般所公認的由上而下設計法的基本原則:

"不要寫出程式碼直到已經詳盡的做好所有的規劃。"

因為程式一經完成, 就很難修改,在由上而下的設計法中,在初步設計階段的
任何疏失, 應該在實際撰寫程式碼層次的模組之前找出來,否則可能使花費大量人
力所完成程式無法使用。


副程式(subroutine)
==================

在這之前所討論的模組只被當作一個抽象的標示, 但是所有的高階程式語言,
都俱有設計實際包括程式碼的模組的技術, 即一些獨立的具名稱的單元,且可被另
一段的程式叫用。 視不同的高階語言以與不同的設計方式,這些獨立的單元被稱為
副程式 (subroutine) ,程序 (procedure) ,或函式 (function) 。
假設我們將"MAKE-CEREAL"寫成一個副程式,看起來可能像這樣:

procedure make-cereal
get clean bowl
open cereal box
pour cereal
open milk
pour milk
get spoon
end

同樣的,我們可以寫出 "MAKE-EGGS" 及 "CLEANUP" 的副程式。 然後在程式別
的地方定義 "MAKE-BREAKFAST" 成一個簡單的副程式來呼叫這些副程式,

procedure make-breakfast
var h: boolean (indicates hurried)
test for hurried
if h = true then
call make-cereal
else
call make-eggs
end
call cleanup
end

"call make-cereal" 的字句會使得叫 "make-cereal" 的副程式被執行, 當副
程式執行完之後,控制交回到呼叫的副程式,由 call 之後的指令繼續執行。 副程
式遵循結構化程式的原則。
正如你所見, 呼叫副程式的效果就好像副程式的碼是完整地寫在呼叫的模組中
,但又不像 macro assembler 所產生的碼,副程式可以被編譯在記憶體中別的地方
, 並且只是被參考而已,無需被編譯到主程式的目的碼 (object code) 中 ( 見圖
1-5) 。
在這些年中, 電腦科學家更強烈地支持用許多小的副程式來代替連續的長串程
式。 副程式可以個別完成及測試,如此可以比較容易地重覆使用已經完成的程式,
而且也較容將一整個程式分解成數個部份交由不同的程式師完成。 較短的程式較容
易思考並且較容易驗證其正確性。
當副程式被編譯在記憶體中的不同位置並且被參考, 在一個程式中可以呼叫同
一個副程式好幾次,可以節省因為重覆的程式碼所浪費的記憶空間。 因此適當地使
用副程式可以減小程式的體積。
不幸的是, 使用副程式必須忍受執行時間的增加,問題出在處理暫存器內容的
負擔, 在跳到副程式之前要將暫存器的內容保留起來,回來之後要恢復其內容,縱
使所浪費的時間難以察覺,但與副程式之間傳遞參數也要相當的程式碼來完成。
另一方面, 呼叫副程式的方式也很繁瑣,特別是如何傳遞參數,要個別測試時
,需要特別寫一段的測試程式來呼叫他們。
基於這些理由, 電腦科學家建議適度地使用副程式,事實上,副程式一般都相
當長,其原始碼多在半頁到一整頁之間。


持續精煉法(successive refinement)
=================================

" 持續精煉法 " 是一種頗為倚重副程式的方法,這個構想是在開始時,先用自
然的程序 (procedure) 或資料結構名稱寫出程式的骨幹,然後寫出每一個命名的程
序的說明, 重覆此步驟,使說明越來越詳盡,直到這個程序只能用電腦語言本身來
寫。
在每一個步驟中,程式師必須決定要使用何種演算法 (algorithm) 與資料結構
,而且決定演算法時,配合的資料結構也要同時決定。
假如一個方法不能完成時,程式師儘可往回退到所需的步驟,再重新做一次。
關於持續精煉法, 必須注意的是: 在最低階的單元完成之前,程式的任何部份
都無法實際地執行,也就是說在程式完全的設計好之前,無法進行測試。
同時也要注意: 持續精煉法強迫設計者在進行到更詳細的下一層之前必須完成
控制結構的所有細節。


結構化設計(structured design)
=============================

1970 年代的中期,電腦業嚐試了前面敘述的所有辦法,但仍難合意。為因應改
變而使程式仍能運作所做的軟體維護, 其成本超過軟體總成本的一半,有些估計甚
至高達百分之九十!
每個人都同意, 錯誤通常可以回溯到程式的分析不完全或不成熟的設計,而結
構化設計法本身一點都沒有問題。 當計劃案延遲,不完全,或不正確時,設計者即
歸咎於無法預測的意外。
學者們的回答自然是更強調設計,"下次再考慮得更詳細些"。
大約在此時期, 興起另一種由一篇叫 " 結構化設計法 (Strctured Design) "
所敘述的新想法。其主要的原則如下面的文章片段所描述:

在評估不同的設計時,建議以單純性作為減少除錯與修正時間的主要考量
。將一個系統分解成個別的單元,可使單純性提高,分解的方式是每個單
元應該很容易地考慮,建構 (implement) , 修改,與變更,並且對系統
其他單元的影響最小。

藉著將問題分成簡單的模組,期望程式可以比較容易撰寫,變更,及瞭解。
但何謂模組,要根據什麼做分解呢? " 結構化設計 " 中描繪出三項模組設計的
因素。


功能強健性(functional strength)
===============================
第一項因素有時稱為功 " 功能強健性 " , 用來評量在同一個模組中所有陳述
(statement) 的功能的一致性。 假若在同一個模組中的所有陳述可以看成是在完成
一個工作,則這些陳述為功能性聚合。
要辨一個模組中的所有陳述是否為功能性限制, 可以考慮下述的問題: 第一,
是否可用一句話來敘述其目的,若否則此模組可能不是功能性限制。 其次考慮下列
四個關於此模組的問題:

1. 這個敘述是否冗長?
2. 是否用到時間的字眼,如 "首先","其次","然後" 等?
3. 動詞之後接的是不是一般或非特定的受詞?
4. 是否用到類似 "initialize" 的字眼,而其中隱含在同一時間內要完成
的許多不同功能。

若有任何一個問題的答案為 "yes",則其為較功能性聚合 (functional
binding) 之凝聚性差的聚合。較弱形式的聚合 (binding) 包括:

巧合聚合(coincidental binding): 這些陳述只是碰巧出現在同一個模組中。
邏輯聚合(logical binding): 模組中有數個相關的功能,需要一個旗號或參數
來決定要執行那一個特殊的功能。
暫時聚合(temporal binding): 模組中包括一堆要同時執行的陳述,但是沒
有其他的相關性,例如程式的啟始化(initialization)。
溝通聚合(communication binding): 模組中包括一堆陳述,而這些陳述皆參
考同一組資料。
序列聚合(sequential binding): 其中一個陳述的輸出當作下一個陳述的輸入。

"MAKE-CEREAL" 模組顯然是功能性聚合, 因為可以把它當成是在做一件事,縱
使它是由幾個次級的工作所組成。


耦合性(coupling)
================

結構化設計的另一項教條和 " 耦合性 (coupling)" 有關, 這是用來考量一個
模組如何影響其他模組的行為。 最壞的情況是當一個模組實際地修改另一個模組內
的程式碼。即使是傳遞控制旗號給其他模組以控制其功能,也是很危險的。
一種可接受的耦合形式是 " 資料耦合 (data coupling)" ,是由一個模組傳遞
資料到另一個模組,而非控制訊息。 縱使如此,模組間的資料界面儘可能簡單,可
使系統的建構與維護更容易。
當資料可以被許多模組存取,例如公共變數 (global variable) ,這些模組間
有較強的耦合性。假使程式師需要更動某一個模組時,其他模組極有可能產生 " 邊
際效應 (side effect)" 的危險。
最安全的一種資料耦合是在一個模組中, 把區掝變數 (local variable) 當成
參數傳遞給其他模組。 實際上是,呼叫模組告訴次級模組: " 我要你使用我放在這
些稱為 X 與 Y 的變數中的資料,然後當你完成之後,我希望你把結果在稱為 Z 的
變數中。其他人不會使用這些參數。 "
正如前面所說的, 提供副程式的傳統語言,包含了精巧的方式來傳遞模組間的
參數。


輸入-處理-輸出的階層式設計
(hierarchical input-process-output designing)
=============================================

結構化設計的第三項箴言和設計方式有關。 程式師被叮嚀要採用由上到下
(top-down) 的設計步驟,一開始時不要太在意控制結構。 " 決斷設計 (decision
designing)" 應該等到稍後模組的詳細設計。 而在早期設計時應貫注於程式的階層
性 ( 那一個模組呼叫那一個模組 ) 以及模組間的資料傳遞。
為了幫助設計者順著這些新線思考, 發明了一種叫 " 結構圖 (structure
chart)"的圖形表示方法, ( 另一種是大同小異的 "HIPO chart" , 即
"hierarchical input-process-output" 之意。 ) 結構圖包括階層圖及輸入輸出表
兩部份。
圖 1-6 顯示出這兩部份。主程式為 DOIT ,包含三個次級模組,次級模組又再
呼叫在他們之下的其他模組,由此可見,此種設計方法強調輸入與輸出的轉換。
階層圖中的小數字表示這條線和輸入輸出表的對應, 在點 1 (READ 模組 ) ,
輸出值是 A ,在點 2 (TRANSFORM-TO-B 模組 ) 輸入值是 A ,而輸出值是 B 。
這種方法的最大的貢獻也許是認清了關於控制流程 (control flow) 的決斷不
應該主宰初始的設計。 我們將會瞭解控制流程只是問題的表面外觀,需求上的微小
改變即可使程式的控制結構大幅變動,以及要曠日費時的工作。 若程式以其他角度
來設計,例如資料流程,那麼當計劃變動時就不會有如此嚴重的影響。


資訊隱藏(information-hiding)
============================

在 1972 年的一篇論文中, David L. Parnas 博士指出模組分解的標準不應是
程序中的步驟,而應是可能更動的資訊片段,模組應該用來隱藏此類資訊。
讓我們來看看 " 資訊隱藏 " 的重要觀念: 假設你正在寫公司的作業手冊, 有
以下一部份:

業務部門接到訂單
藍色聯送到簿記部門(bookkeeping)
橘色聯送到發貨部門(Shipping)
Jay 將橘色聯登錄到桌上的紅色活頁本上,並且製作包裝條

每個人都同意這個程序是正確的,然後你的手冊分發給公司的每一個人。
有一天, Jay 離開,由 Marilyn 接替, 新的單據形式是綠色與黃色,不再是
藍色與橘色,紅色活頁本裝滿了,換一本黑色的活頁本。
你的整本手冊都得作廢,為了避免重蹈覆轍,你用 " 發貨員 " 代替 "Jay" 的
名字, 用 " 簿記部門聯 " 與 " 發貨部門聯 " 代替 " 藍色聯 " 與 " 橘色聯 "
等。
這個例子主要在說明, 為了因應多變的環境仍能保持正確,得將容易變動的細
節排除在程序之外, 若有需要,可以另外記錄這些細節,例如,每週或人事部門可
以發佈員工名冊及他們的工作職稱, 如此若有人想要知道誰是發貨員,就可以查這
名冊,當人員變動時,這份名冊也跟著變更。
在寫軟體時, 這個技術非常重要,為何在程式開始使用之後,還需要去改變它
呢?理由有上萬種,可能是一個舊程式要在新設備上執行,必須修改到足以適應新硬
體。 對使用者而言,程式可能不夠快或功能不夠強。大部份的軟體小組發現,他們
本身為某一個特殊應用領域寫了一系列不同版本的相關程式, 每個都和較早版本的
程式有一些差異。
要在軟體中應用資訊隱藏的原則, 程式的特定細節應該制於一個單獨的位置,
並且任何有用的資訊片段只能出現一次, 若程式忽略這個箴言,就是犯了冗贅之失
。硬體的冗贅 ( 如備份電腦 ) 可以使系統更安全,而資訊的冗贅只會造成危機。
任何一位有經驗的程式都會告誡你, 程式中的數字在未來版本中可能改變的話
,應該宣告成 " 常數 (constant)" ,然後在整個程式中參考其名稱而非數值。 例
如代表電腦報表紙寬度的行數應該宣告為一個常數, 甚至在組合語言中也提供
"EQU" 與標記 (label) ,可以用名稱來表示位址值及位元模型 (bit-pattern) 。
任何一位優秀的程式師在發展副程式時, 也會採用資訊隱藏的觀念,確保每一
個模組儘可能不知道其他模組內部。 現代的程式語言, 像 C , Modula 2 , 及
Edison ,在他們的模組結構中採用這種觀念。
Parnas 將這觀念往前更推進一步,建議這種觀念應擴展到演演算法與資料結構
。 事實上, 隱藏資訊 ---- 不是決斷結構 (decision-structure) 或呼叫階層
(calling- hierarchy) ---- 應該是設計的主要基礎。


+---------------------------------------------+
| 結構之膚淺(The superficiality of structure) |
+---------------------------------------------+

Parnas 提出分解 (decomposition) 的兩個條件:

a. 可能重覆使用(雖然目前並不打算),以及
b. 可能改變(雖然不打算如此)

這個對 " 模組 " 的新觀點和傳統觀點不同, 所謂的 " 模組 " 是一堆常式
(rountine)的集合,通常非常小,從問題某一方面來說,他們共同隱藏資訊。
另外兩位作者以不同的方式來描述此概念,名之為 " 資料抽象化 " 。 以堆疊
(push-down stack) 為例,堆疊 " 模組 " 中包括一些常式, 可用來啟始堆疊,存
一個到堆疊中,由堆疊中取出一個值,以及判斷堆疊是否空的。這個 " 多程序模組
(multi- procedure module)" 對應用程式的其他部份隱藏了堆疊如何構成的資訊。
這些模組可以看成一個單獨的模組, 因為他們是互相關聯的,因為無法只修改存值
的方法,而不用同時修改取值的方法。
"使用 (use)" 這個字眼在本觀念中扮演著重要的角色,Parnas在後來的論文中
說:

系統達到某一程度的 " 優雅 (elegance)".... 系統中的某些部份 " 使
用 " 其他的部份....
假若有此種階層順序 (hierarchical ordering) 存在, 那麼每一階層
(level) 都提供系統中的一個可測試及可用的子系統 (subset)....
" 使用 " 的階層 (hierarchy) 應是致力於設計的一個重要里程碑之一。
在將系統分解成獨立可被呼叫的子程式 (subprogram) 時, 對於使用
(use) 的決定 (decision)也必須同時進行,因為彼此間會互相影響。

根據控制流程 (control flow) 或順序 (sequence) 來設計那些模組要合為一
組,會使設計不容易改變。對控制流程的階層來說,結構是很膚淺的。
根據可能改變的事物來設計那些模組要合為一組,可以很容易地適應改變。


+---------------------------+
| 瞻前顧後看FORTH |
| Looking back,and FORTH |
+---------------------------+

在本節中將對 FORTH 的一些基本特色作一回顧,並且探討與前面所討論的傳統
方法論之關係。
下面是一段FORTH程式碼的例子:

: BREAKFAST
HURRIED? IF CEREAL ELSE EGGS THEN CLEAN ;

這和前面的 MAKE-BREAKFAST 程序 (procedure) 在結構上是相同。 ( 若你是
FORTH 新人請自行參考相關書籍 ) 。
HURRIED? , CEREAL , EGGS , 及 CLEAN 這些辭 (word) 也 ( 極可能 ) 都
是以冒號定義來定義的。
從某一個角度來看, FORTH 具有我們前面研究過的所有特質,可記憶性,抽象
化, 能力 (power) , 結構化控制運算元, 強的功能聚合 (strong functional
binding) ,有限的耦合性,以及模組化。 不過關於模組性,可能是 FORTH 最具代
表性的突破:

FORTH程式的最小元素不是模組,或副程式,或程序,而是 "辭(word)"。

甚且 FORTH 裏沒有副程式,主程式, utilities ,或 executives ,這些都
必須以不同的方式呼叫使用, FORTH 所有的就只有辭。
在探討以辭基環境 (word-based enviroment) 的內函之前,首先來研究使其可
能實現的兩項 FORTH 的發明。


隱含式呼叫(implicit calls)
==========================

首先是隱含式呼叫, 不需要用 CALL CEREAL , 只要使用 CEREAL 即可, 在
FORTH中, CEREAL 的定義知道它是那一類的辭以及用何種程序來呼叫其本身。
因此變數與常數,系統函式, utilities ,以及任何使用者定義的指令或資料
結構,都可以只用名字來 " 呼叫 (call)" 。


隱含式資料傳遞(implicit data passing)
=====================================

其次是隱含式資料傳遞,能產生這種效果的機制是 FORTH 的資料堆疊。 FORTH
自動將數值入堆疊中, 辭需要數值當輸入時,會自動由堆疊中取出,辭產生的數值
輸出,會自動存入堆疊中。高階的 FORTH 中並沒有存入與取出的辭。
因此可以寫出如下的程式:

: DOIT
GETC TRANSFORM-TO-D PUT-D ;

確定 GETC 會得到一個 "C" ,並且將之留置在堆疊上, TRANSFORM-TO-D 會從
堆疊中拿出 "C" ,經過轉換,然後將 "D" 留置堆疊上,最後, PUT-D 會拿出堆疊
中的 "D" 並且印出。 FORTH 消弭了程式中傳遞資料的動作,讓我們專注於資料轉
換的功能性步驟。
因為 FORTH 使用堆疊傳遞資料,辭可在辭中構成巢狀 (nest) ,任何辭都可以
把值存入堆疊中以及取出來,而不會擾亂了上一層的辭的資料流程 ( 當然,要防止
辭消耗或留置意料之外的值 ) 。因此堆疊支持結構化,模組化的程式法,同時提供
簡單的機制來傳遞區域性參數。
FORTH 從程式中消弭了辭被如何呼用及資料如何傳遞的細節,那還剩些什麼呢?
只剩那些描述問題的辭了。
有了辭, 我們可完全遵循 Parnas 的建議 ---- 根據可能改變的事物來分解問
題, 且每個模組由許多小的函式組成, 可多到隱藏該模組的資訊所需的數量。 在
FORTH 中,只要我們需要,我們可以寫許多辭,不用管可能多麼簡單。
典型的FORTH應用程式中的一行可能讀起來如下:

20 ROTATE LEFT TURRET

很少其他的語言會鼓勵你建一個叫 LEFT 的副程式, 只是用來當一個修飾詞,
或是一叫 TURRET 的副程式,只用來稱呼硬體的一部份。
因為 FORTH 的辭比副程式容易呼用 (invoke) ( 只用使用其名稱,而不是呼叫
) ,比起傳統程式分解成副程式,一個 FORTH 的程式似乎更容易分解成更多的辭。


+-------------------------------------+
| 組件式程式法(Component Programming) |
+-------------------------------------+

有了一大堆簡單的辭, 就使得一種我們稱為 " 組件化程式法 (component
programming)" 的技術很容易使用。 在解釋之前,首先我們再檢視一下那些我們籠
統地以 " 可能改變的事物 " 來描述的集合。 在一個典型的系統中,每種事物都可
能變動,諸如終端機及印表機一類的 I/O 裝置,或如 UART 元件的界面,作業系統
,任何資料結構或資料表示法,任何演算法,等等。
問題是: " 如何把此類變動的影響減至最小? 什麼是必需跟著這變動來改變的
最小集合?"
解答是: " 互動的資料結構及分享知識的演算法的最小集合決定於他們如何共
同運作 " ,我們稱這個單位叫 " 組件 (component)" 。
一個組件是一項資源, 可能是一個硬體,如 UART 或硬體堆疊,也可能是一種
軟體資源,如佇列 (queue) ,辭典,或一個軟體堆疊。
所有的組件包括資料個體 (data object) 及演算法。不論這資料個體是實際的
( 例如硬體暫存器 ) ,或是抽象的 ( 例如堆疊的位置或資料庫中的欄位 ) 。也不
論這演算法是以機械碼描述或以像 CEREAL 與 EGGS 問題導向的字眼來描述。
圖 1-7 把結構化設計與組件化設計的結果做一對照。我們所關注的不再是稱為
READ-RECORD , EDIT-RECORD , 及 WRITE-RECORD 的模組, 而是用來描述記錄
(record) 的結構,提供編輯指令集,以及提供儲存的讀寫常式的組件。
我們做了什麼事呢? 我們已在發展程序中插入一個新的層級 (stage) 。在我們
的設計中,先以組件來分解,然後才描述在建構中的序列,層級,以及輸入 - 處理
- 輸出。 沒錯,是多了一個額外的步驟,但是也多了一個分解的維度 ---- 不在只
是平面 (slicing)而是立體的 (dicing) 。
假設當程式完成之後, 我們需要更改記錄的結構, 在序向, 層級式
(hierarchical)的設計中, 這個變動將會影響到所有的三個模組,在用組件方式的
設計中,這個改變將侷限於記錄結構的組件中。 所有使用這個組件的程式碼都不需
要知道這個變動。
除了維護之外, 這種架構的另一個優點是團隊中的程式師可以分別指定組件,
而彼此之間的依賴也較少。 組件式程式法除了應用在軟體設計,同樣的可以用在團
隊管理上。
我們將描述一個組件的一組辭稱為 " 辭彙 (lexicon)" 。 ( 辭彙的另一個意
義是 " 屬於某一個特殊領域有興趣的一組辭 ") 。辭彙是組件與外界的界面。
在本書中, " 辭彙 " 一辭只是指在組件中,那些可供外界以名稱呼用的辭。
在組件中,可能也有一些定義僅是為了支援這些外界可看見的辭彙。 我們將稱這些
支援用定為 " 內部的 " 辭。
辭彙以名稱的形式提供與資料結構及演算法的邏輯性替身 (equivalent) 。 辭
彙隱藏了組件中資料結構與演算法 ---- " 如何工作 " 。對外界只以簡單的辭來描
述該組件的 " 概念模型 (conceptual model)" ---- " 它是什麼 " 。 " 什麼
(what)" 成了較高層組件的 " 如何 (how)" 。
使用 FORTH , 整個應用程式中只由組件構成, 圖 1-9 顯示一個機器人
(robotic) 的應用程式可以如何分解。
甚至可以說每一個辭彙是一個特殊目的的編譯器 (compiler) 。 其目的僅是用
來以每最有效及可靠的方式支援較高層應用程式。
另外, FORTH 本身不提供組件,也不需要。組件是程式設計者分解後的成果。
( 然而, FORTH 有 " 映幕 (screen)" ,高容量記憶裝置的小單元,用來儲存原始
碼,一個組件通常可以用 FORTH 的一至二個映幕寫完 ) 。
瞭解一個辭彙可以讓任何及所有的較高層的組件使用是很重要的, 每個後續的
組件不會埋藏其支援組,而通常階層方式的會如此。 相對的,每一個辭彙可以自由
地使用它下面的所有指令。如 robot-movement 指令依賴 (rely on) 基本語言的變
數,常數,堆疊運算元,數學運算元等等,就跟依賴任何其它組件一樣多。
這個方法的一個重要效果是整個應用程式使用單一的語法, 使得學習和維護更
容易。 這就是我為何要用 " 辭彙 " 的字眼,而不是 " 語言 " ,語言具有唯一的
語法。
這種指令的可用性也使得測試及除錯的工作更加的容易。因為 FORTH 是交談性
的,程式師可以從 " 外面 " 輸入及測試原始的指令,諸如

RIGHT SHOULDER 20 PIVOT

就和下面更強大的指令一樣的容易

LIFT COOFFEE-POT

同時, 當應用程式完成後,為了避免終端使用者 (end-user) 使用者,程式師
可以 ( 若他或她想要 ) 故意密封任何指令,包括 FORTH 本身。
現在 FORTH 的方法已很清楚, FORTH 的程式即是將基礎語言向應用程式擴展
,提供可用來描述問題的新指令。
" 應用導向語言 (application-oriented language)" 是特別為特殊的, 諸如
機器人,存貨控制,統計等應用所設計的程式語言, FORTH 是一種用來建立應用導
向語言的程式環境。 ( 你將會發現,最後這一句話是 FORTH 的最簡潔的描述 ) 。
事實上,你不該用 FORTH 來寫任何嚴肅的應用程式,作為一種語言,它根本就
不夠強大。你應該做的是,用 FORTH( 辭彙 ) 來寫你自己的語言,以便讓你根據對
問題的瞭解來建立模型,如此你可以很優雅地敘述它的解答。


+---------------------------+
| 對誰隱藏(Hide from whom?) |
+---------------------------+

因為現代主流 (mainstream) 的語言對於 " 資訊隱藏 " 這句話所賦予的意義
,用些微的差異,我們應該澄清一下。我們要對什麼或對誰隱藏資訊。
最新的傳統語言 ( 如 Modula 2) 倒行逆施地致力於確保能將模組內的常式
(routine)與資料結構對其他模組隱藏。 目的是要達到模組的獨立性 ( 最小耦合性
) 。 這種恐懼看起來好像模組會像入侵的抗體一般彼此攻擊,或者好像強盜的邪惡
之手出來搶奪珍貴的資料結構一樣。
這不是我們關心的, 對於資訊隱藏的目的,我們的詮釋只是將可能的設計變動
的影響減至最小,把可能改變的事物侷限於每個組件內。 FORTH 程式師通常較喜歡
保持程式在自己的完全控制之下,而不採用任何的技來實際地隱藏資料結構。 ( 不
過, Dewey Val Shorre 已發展一個非常簡單的技術, 可以在 FORTH 中加入
Modula 型式的模組,程式只有三行而已。 )

+--------------------------------------------+
| 隱藏資料結構之建構 |
| Hiding the construction of data structures |
+--------------------------------------------+

我們已經指出 FORTH 的兩項發明使得我們前面敘述的方法變為有可能 ---- 隱
含式呼叫及隱含式資料傳遞。 第三項特點是允許一個組件內的資料結構可以用先前
定義的組件來描述。這個特點即是直接存取記憶體。
假設我們像下面這樣定義一個叫做APLLES的變數:

VARIABLE APPLES

我們可以在變數中存一個數目代表我們目前有多少蘋果:

20 APPLES !

我們可以顯示變數的內容:

APPLES ? ==> 20 ok

我們可以把數目加一:

1 APPLES +!

(新手可以找本參考書來學習這些句子的原理。)
APPLES 這個辭只有一個功能: 將存放蘋果總數的記憶體區域的位址放在堆疊上
。這個總數可以當成是一個 " 事物 (thing)" ,而用來設定總數,讀取總數,或增
加總數的辭可以想成 " 動作 (action)" 。
因為允許資料結構的位址以堆疊來傳遞及提供 "fetch" 與 "store" 指令,
FORTH 可以很容易地從 " 動作 " 分出 " 事物 " 。
我們已經討論了依據可能改變的事物來設計的重要性。 假設我們已完成了許多
使用 APPLES 這個變數的程式碼。 現在,半夜十一點,我們發現我們必須追蹤兩種
不同的蘋果,紅的及綠的。
我們不需扭曲我們的雙手,而要記得 APPLES 的功能: 提供一個位址。 假如我
們需要分別的兩個總數, APPLES 可根據我們現在討論的種類來提供兩個不同的位
址。所以我們定義像下面更複雜的 APPLES:

VARIABLE COLOR ( pointer to current tally)
VARIABLE REDS ( tally of red apples)
VARIABLE GREENS ( tally of green apples)
: RED ( set apple-type to RED) REDS COLOR ! ;
: GREEN ( set apple-type to GREEN) GREENS COLOR ! ;
: APPLES ( -- adr of current apple tally) COLOR @ ;

如此,APPLES就重新定義了,現在它取出叫COLOR變數的內容,COLOR是一個指標,
指向REDS變數或GREENS變數,這兩個變數是實際的總數。
當我們先說 RED ,那麼我們可用 APPLES 參考到紅色蘋果, 若先說 GREEN ,
我們可用其參考到綠蘋果 ( 見圖 1-10) 。
我們不需要去修改任何已經存在且使用到APPLES的程式碼的語法。我們仍可說

20 APPLES ! 及

1 APPLES +!

再看一下我們做了些什麼, 我們把 APPLES 的定義由變數改成冒號定義,而不
影響它的使用。對於使用 APPLES 的程式碼, FORTH 允許我們把 APPLES 如何定義
的細節隱藏起來。 在原來的程式碼中,看起來是一個 " 事物 "( 一個變數 ) ,在
組件中實際上是定義成 " 動作 "( 一個冒號定義 ) 。
FORTH 允許以較低階的組件定義資料結構,而藉此鼓勵使用抽象資料型態。 只
有 FORH 可以提供這種水準的資訊隱藏,因為它將 CALL 從程序 (procedure) 中消
除,透過堆疊,允許位址及資料以隱含方式傳遞,以及提供 @ 及! 可以直接存取記
憶體的位置。
FORTH 不太在意那些是資料結構或演算法, 這種一視同仁的態度,使我們程式
人員有無比的自由,讓我們可以建造用來描述我們的應用的文章的辭藻。
我比較傾向於把任何傳回位址的辭 (word) 當成 " 名詞 (noun)" , 例如
APPLES ,不管它是如何定義的。而明顯完成一個動作的辭是 " 動詞 (verb)" 。
在我們的例子中,如 RED 及 GREEN 這種辭只能叫 " 形容詞 (adjective)" ,
因為它們修飾 APPLES 的功能。像

RED APPLES ? 與 GREEN APPLES ? 是不同的。

FORTH 的辭也可以當成副詞與介系詞, 試圖去分辨文章中的文詞屬於何者是不
太有意義的,因為 FORTH 根本不在乎。我們只要享受可以很容易地以自然的方描述
一個應用。


+----------------------------------+
| 那它是高階語言嗎? |
| But is it a high-level language? |
+----------------------------------+

在前面詳細的回顧中, 我們注意到傳統高階語言脫離組合語言,不只消除了指
令與機器碼間一對一的對應關係,也消除了線性對應。顯然的, FORTH 同意第一種
差異; 但看重後者,定義中辭的位置順序即是指令的編譯順序。這樣會使 FORTH 沒
資格成為高階語言嗎? 在回答之前,讓我們探討一下 FORTH 這種方式的優點。
下面是FORTH的發明人Charles Moore所說的話:

你定義每一個辭而電腦知道它的意義,它瞭解的方式是根據呼叫的順序執
行某些碼。電腦對於每一個辭執行一個動作,它不會把辭保留起來或記著
以便再用。
在哲學的意味上,我認為這代表電腦 " 懂 (understand)" 一個辭,它懂
DUP這個辭, 可能瞭解得比你更深, 因為在它的心目中, 根本就不會有
DUP 是什麼意思的問題。
辭對你的意義和辭對電腦的意義,這之間的聯結是很深淵的,電腦變成一
種人類與概念間的溝通工具。

原始碼與機器執行的這種對應的一項優點是,極度簡化了編譯器 (compiler)與
釋譯器 (interpreter) ,在後面的章節中,我們會看到這種簡化以數種方式提升了
性能 (performace) 。
從程式方法的觀點來看, FORTH 的這種作法的優點是可以很容易地增加新辭與
新語法。不能說 FORTH 是 " 尋找 (look)" 辭 ---- 它找出辭然執行他們。原先已
有辭與你新加的辭並無差別。
甚至,這種 " 延展性 (extensibility)" 可適用於所有型態的辭,不只是動作
型態函式 (function) 。 例如, FORTH 允許你加入新的編譯辭 (compiling
word)---- 像 IF 與 THEN 提供結構化控制流程的辭。 你可以很容易增加狀況
(case) 陳述或多出口 (multi-exit) 迴圈,假使有需要的話或只是覺得很重要,當
你不需要時,也可以把它去除。
相對的,任何語言要靠字的順序來瞭解一個陳述, 必須 " 知道 " 所有合法的
字及所有合法的組合。要包含所有你想要的建構 (construct) ,這種機會看來是很
渺茫的。現存的語言取決於其製造者; 你無法擴充它的知識。
實驗室的研究人員認為在他們的環境中, 認為彈性 (flexibility)及延展性
(extensibility) 是 FORTH 最重要的長處。 可發展辭彙 (lexicon) 用來隱藏關於
電腦所連接的各種測試設備的資訊, 當由有經驗的程式師完成這個工作之後,研究
人員可以用他們寫好的 " 軟體工具箱 " 內的辭來為實驗寫一些簡單的程式。 當增
加新設備時,可以增加新的辭彙。
Mark Bernstein 敘述在實驗室中使用現成特殊用途的程式庫的問題:"電腦主宰
了實驗,而不是使用者 " ,但使用 FORTH 的話,他寫道:" 電腦真地鼓勵科學家更
改,修正,以及改進軟體,用來實驗及配合他們的設備。 主動再度成為研究人員的
特權。
對那些正統人士來說,他們認為 FORTH 不能叫做高階語言。 FORTH 把事情弄
得更糟,而嚴格的語法檢查與資料型態變成現代程式語言的一項主要利器。 FORTH
幾乎不做語言檢查, 為了提供前面提到的自由性及彈性, 它不能告訴你應該輸入
RED APPLES ,而非 APPLES RED 。你只要發明那種語法。
但是 FORTH 為了補償這項疏失,讓你編譯每一個定義,一次一個,數秒之內即
可全部編譯完。 當定義不工作時,你可以立即發現錯誤,另外,假如你想要的話,
你可以在定義中加入適當的語法檢查。
藝術家的畫筆不會指出藝術家的藝術家得自行判斷。 廚師的廚具和作曲家的鋼
琴仍保持簡單和順從。為什麼要讓程式語言試圖指導你呢?
所以, FORTH 是高階語言嗎? 論語法檢查,它被判出局。若說抽象化與能力,
它像無限等級 ---- 它萬以具備,從輸出埠的位元處理到商業應用。
你做決定吧! (FORTH不在乎。)


+------------------------------------+
| 設計之語言(The language of design) |
+------------------------------------+

FORTH 是一種設計語言,對一個學生來講,這個陳述自相矛盾, " 不應該用語
言設計,建構 (implement) 才用語言,設計在建構之前。 "
有經驗的 FORTH 程式師不同意,在 FORTH 中,藉著分解成辭彙 (lexicon) 的
優點,你可以寫出抽象化,設計階段的程式碼,而仍隨時都可以測試。 在發展進行
中, 組件隨時都可以很容易地重寫, 而不影響使用它的組件。 首先組件中的辭
(word) 可將數字從終端機印出以代替控制步進馬達,它們可以印出自己的名稱,只
是讓你知道它們已經執行了,它們也可以不做任何事。
使用這種原理, 你可以替你的應用寫一個簡單但可測試的版本,然後繼續修改
與精練,直至達到你的目標。
用程式碼來設計變成有可能的另一個因素是, 像其他較新的語言一樣, FORTH
排除了 " 批次編譯 (batch compile)" 的發展順序 ( 編輯 - 編譯 - 測試 - 編輯
- 編譯 - 測試 ) 。 由於回饋是立即的,媒介 (medium) 成了創作過程中的伙伴。
使用批次編譯的程式師極少能像藝術家一樣, 在心中靈感湧現時,不斷創作的境界

基於這個因素, FORTH 程式師比起傳統的程式師,在計劃上花的時間不多,傳
統程式師覺得計劃是理所當然的,對他們來說,不計劃似乎是魯莽且不負責。 傳統
環境迫使程式師要計劃,因為傳統環境不能迅速適應變化。
不幸的是, 縱使是在最佳的條件下,人的遠見也是有限的,太多的計劃反而一
事無成。
當然, FORTH 不排斥計劃,它允許用原型 (prototype) , 建立原型是比計劃
更精練的方式,正如電子設計用的麵包板 (breadboard) 。
在下一章裏,我們將看到,實驗證明實際得到的比臆測式的計劃更可靠。


+----------------------------------------+
| 性能之語言(The language of performace) |
+----------------------------------------+

雖然,性能不是本書的主題,但 FORTH 新人應該放心,它的優點並非純粹哲學
性的。 整體上, FORTH 在速度,能力,及緊緻 (compactness) 各方面超越其他高
階語言。


速度(speed)
===========

雖然 FORTH 是交談性語言,但它執行編譯過的碼,因此它執行的速度大約比交
談性 BASIC 快上十倍。
FORTH 是靠 " 線串碼 (threaded code)" 的技術來達到辭的執行最佳化。而因
每個模組只包含小片段程式碼所增加的額外負擔也相當小。
它無法執行的和組合碼一樣快, 因為視不同的處理器, 內部釋譯器 (inner
interpreter) 大約耗去了基本辭執行時間的 50% 。 ( 內部釋譯器翻譯位址的串列
,位址串列是由每個定義組成的。 )
但是在大型的應用中,FORTH的速度和組合語言非常接近,原因有三:
第一點, 也是最重要的一點, FORTH 簡單, FORTH 使用資料堆疊大幅降低了
辭之間傳遞參數的性能代價。 在大部份的語言中,模組之間的參數傳遞是使用副程
式會降低效能的一個主要因素。
其次, FORTH 允許你用高階或機器語言來定義辭,不論那種方式,都無需特別
的呼叫方式, 你可以用高階定義新辭,並且在驗證無誤之後,以組合語言重寫,而
不用更動任何使用它的程式碼。在典型的應用中,大概有 20% 的程式碼會佔掉 80%
的執行時間。 FORTH 系統本身大部份由機器碼定義建構而成,所以你只有很少的應
用辭必須用組合語言撰寫。
第三點, FORTH 應用比完全用組合語言撰寫更容易設計。 FORTH 程式師可以
在決定那種演算法最符合他們的需求之前,利用 FORTH 語言的原型能力的優點,嚐
試數種演算法。因為 FORTH 鼓勵變動,它也可以稱為最佳化之語言。


能力(capability)
================

FORTH可做其他語言可做的任何事情----往往較容易。
在低階,幾乎所有的 FORTH 系統都包括組合語言,它們支援控制結構運算元,
可用結構化程式技巧來寫條件判斷及迴圈, 它們通常允許你寫中斷 ---- 假若你想
要的話,甚至可以用高階來寫中斷程式。
有些 FORTH 是多工的, 允許你加入如你所需的前台 (foreground) 或後台
(background) 任務 (task) 。
FORTH 可以架在任何作業系統之上,如 RT-11 , CP/M ,或 MS-DOS---- 或者
,對那些較喜歡這麼作的人, FORTH 可以建成一個獨立自己自足的作業系統,包括
自己的終端機驅動程式與磁碟驅動程式。
使用交互編譯器 (cross-compiler) 或目標編譯器 (target compiler) ,你可
以用 FORTH 在同樣的電腦或是不同的電腦上, 重建一個新的 FORTH 系統。 因為
FORTH 是用 FORTH寫的,你有其他不可思議的機會, 為了因應你的應用所需,重寫
作業系統。 或者你可以將執行順暢的應用程式移植到內嵌系統 (embedded system)
上。


體積(size)
==========

在這兒,要考慮兩點,基本FORTH系統的體積與編譯後的FORTH應用系統的體積。
FORTH 的核心非常有彈性,在內嵌應用中,你個應用執行所需的 FORTH 部份可
小至 1K ,在完整的發展環境中,一個多工的 FORTH 系統,包括釋譯器,編譯器,
組合語言,編輯器,作業系統,及其他支援的 utility 平均 16K 。 這留下充分的
空間給應用程式。 ( 並且, 有些在可操作 32 位元位址的新式處理器上的 FORTH
可允許有難以想像的大程式。 )
同樣的, FORTH 編譯的應用程式傾向於非常小 ---- 通常比組合語言寫的同樣
的程式還小, 再次的,其理由是線串碼,每一個對應到前面定義的參考,不論是功
能多強,都只佔兩個 byte 。
對於 FORTH , 一個最令人鼓舞的新領域是 FORTH 晶片的生產, 如 Rockwell
的 FORTH基礎 (FORTH-based) 的 R65F11 處理器。這個晶片不只是包括硬體的特性
,也為特殊應用的 FORTH 語言及作業系統提供執行時期 (run-time) 的部份。緊緻
才有可能造就 FORTH 基礎的微處理器。


+---------------+
| 摘要(Summary) |
+---------------+

FORTH 常被視為異類,在結構化和哲理上,完全不像其他普遍的語言。 相對的
, FORTH 結合了許多大多數受到現代語言誇耀的原理。如今日大聲急呼的結構化設
計,模組化,以及資訊隱藏等。
一些新語言使用的方式甚至很接近 FORTH 的本質, 例如 C 語言, 可以像
FORTH 一樣,讓程式師用 C 或組合語言來定義新函式。並且和 FORTH 一樣, C 的
大部份都是以函式定義的。
但是 FORTH 比起任何其他的現代語言,把模組化及資訊隱藏做更多的擴展。至
隱藏了辭被呼叫的方式及區域參數傳遞的方式。
產生的碼變得專注於辭之間的交互作用,最純粹的抽象思想的表達。其結果是,
FORTH程式師傾向於更多產,以及寫出更緊緻,更有效率,且更好維護的程式。
FORTH 可能不是終極的語言, 但我相信若真有所謂的終極的語言, 一定最像
FORTH ,甚於任何其他的現代語言。


Reply all
Reply to author
Forward
0 new messages