理想的編程語言 鞠文廣
以下純粹是個人觀點, 不代表任何組織或社團.
現在流行的編程語言如Java和C#, 大多是面向對象的, 程序的各部分是通過方法調用連在一起, 其編程范式是命令編程, 即使支持其他范式也包裝得很難理解和使用.
面向對象實際上只適合實現抽象數據類型, 讓它去完成除此之外的任務確實是勉為其難, 即便能完成也給人不倫不類的感覺, 既不像面向對象編程, 也不像它的前任(過程編程). 這些語言中的對象與物質世界的物質(或對象)很不一致, 它使用方法調用的方式與其他對象進行相互作用, 而這與物質之間的(通過通信或媒介)相互作用是截然不同的, 因此用面向對象無法很確切地模擬現實世界(面向對象思想的初衷), 更不用說準確地為現實世界建立模型.
這幾年流行的web服務和SOA雖使程序間交互更方便, 但它從本質上說還是使用”面向對象+命令編程+方法調用”的思路, 在編程方法論上并沒有實質的進步.
用現在流行的語言實現的完成復雜功能的程序邏輯不清晰, 原因在于”命令編程+方法調用”的設計機制. 這使程序很難模塊化, 副作用無所不在, 因此很難正確實現復雜功能.
現實世界的發展變化是通過事物間的相互作用實現的, 而這種相互作用用計算機科學的語言來說就是并發(concurrency). 軟件的本質是什么? 我覺得:軟件總是完成某種功能的,歸根到底是對現實世界的事物間相互作用進行建模. 因此軟件的組成部分間自然就是并發的關系, 而不是過程調用的關系. 用通信進程來對現實世界的事物間相互作用進行建模是比較合理的. 所以進程應該作為語言的基礎成分, 是軟件的基本組成部分, 而不是只為了提高效率才采用的.
為了使程序能準確地為現實世界建立模型, 從而正確性更高, 結構更合理, 模塊化程度更高, 因此在幾種編程思想或語言的基礎上(見references), 我提出一種新的編程方法論: 面向進程+函數編程+進程間通信+邏輯編程+約束編程+其他合理的范式(命令編程除外)和一門編程語言ProcessLog (全稱process logic).
ProcessLog只支持一種并發:通信進程. 它就是計算機科學家在上世紀70年代為了克服現在的Java中仍采用的那種并發方式的缺點而提出的. 它是經過充分研究得到的一種理想并發方式, 看了并發理論(concurrency)和進程代數(Process algebra), 就會明白這種并發方式可解決實際中的各種并發問題, 用它足夠了.
這里的進程是進程代數的進程,不是過程,也不是Java中的線程. 看看jcsp或Hoare的CSP(
http://www.usingcsp.com/)就明白了.推薦網址:
http://www.cs.kent.ac.uk/projects/ofa/jcsp/,
其中有兩個ppt說得很明白:
"Process Oriented Design for Java: Concurrency for All",
"Communicating Processes, Components and Scaleable Systems".
ProcessLog的語法概要如下:
1 運算符
(1) ? 輸入; c ? x 從輸入端口c或通道c上接收輸入值放到變量x中
(2) ! 輸出; c ! v 把v的值從輸出端口或通道c上輸出
(3) -> 順序進行的事件的先后關系
(4) | b : s 分支
(5) || 進程并行
(6) // 附屬進程
(7) and, or, not 邏輯運算符
(8) 算術運算符和關系運算符 與Java中相同
2 程序的組成成分
(1) Unit 程序單元
(2) Process 進程
(3) Function 函數
(4) Predicate 謂詞
(5) Channel 通道, 有兩個端口: in 輸入端口, out 輸出端口
(6) OutPort 輸出端口
(7) InPort 輸入端口
3 數據結構
(1) List (函數編程中的List類型, 對List的操作函數與函數編程中相同);
(2) Tuple 元組, 同Clean.
(3) Set 集合
沒有數組
4 進程的定義
Process p1 (OutPort pt1, InPort pt2 ){
pt2?x -> pt1! compute(x) -> p1
}
5 進程間相互作用
(1) 進程并行 process1( c1.out, c2.in)|| process2(c1.in, c2.out)
(2) 附屬進程 (getE: getElements || getR: getReleasedVersion) // X.(in?method -> getE ! method ? elems -> getR ! em ? rem-> … ->X)
6 函數
[Function] compute(double x)=
| x<=0: x*x+3
| x>0: compute(x-5)* compute(x-3)
函數只能以事件的方式在進程中使用或在其他函數中使用, 不能獨立使用.
7 謂詞
/* 建圖 */
Predicate createGraph(t, graph):-
addNode(t, null, ({},{}), graph1),
getDS(t, graph1.ns, tlist),
addList(tlist, t, graph1, graph).
/* 加節點 */
Predicate addNode(t, null, (ns, es), (ns1, es):-
merge(ns, {t}, ns1).
Predicate addNode(t, upper, (ns, es), (ns1, es1)):-
merge(ns, {t}, ns1),
merge(es, {(upper, t)}, es1).
8 把謂詞轉換為函數
create(t)= graph
where createGraph(t, graph)
謂詞不能獨立使用也不能在進程中直接使用, 要在進程中使用需要先轉換為函數.
9 程序單元: 包含進程和數據類型
Unit PmethodDAO;
interface
Tuple Method;
Process getLastVersion(OutPort pt1 , InPort pt2);
…
implementation
Method=(String id, String name, String version);
Process getLastVersion(OutPort pt1 , InPort pt2){
…
}
指導原則: 程序是由通過通道通信的進程組成的. 數據處理和算法用函數編程實現, 如果函數編程不適用于要處理的問題, 就使用邏輯編程或約束編程.
ProcessLog語言限制了編程的隨意性, 要求只能用進程代數+函數編程+邏輯編程的方式編程, 不允許用Java或c#的命令方式編程.
ProcessLog 現在還沒有在機器上實現. 我用該語言重寫了實際項目中的一些復雜代碼(原是Java代碼), 證實用它寫的程序確實簡單清晰, 有類似數學的簡潔美. "7 謂詞"就是其中一部分代碼.
我的想法是: 應先在紙面上規定它的語法與語義, 再通過使用它編寫一些應用程序來發現它的不足,再進而改進它, 再實踐, 再改進, 直到它基本完善再在機器上實現. 另外, 大家不要把語言分為中國人提出的還是外國人提出的, 科學無國界, 這里不存在狹隘的愛國主義. 我不是那種技術高手, 但我自信我是一個能將理論很好地聯系實踐的研究者.
希望有識之士和我一起共同發展這種編程方法論和這門語言.
juwenguang2000@yahoo.com.cn
References
1. CSP
http://www.usingcsp.com/
2. JCSP
http://www.cs.kent.ac.uk/projects/ofa/jcsp/
3. Clean
http://clean.cs.ru.nl/
4. Prolog
5. Delphi
注: 轉載時請注明作者.