Fortran 2003:完美還是虛幻?(節選)

《程序員》第10期發表了我寫的“Fortran 2003:完美還是虛幻?”一文。我把該文的節選貼在這裏吧,要閱讀全文的話,可以找《程序員》雜誌來看。

Fortran 2003:完美還是虛幻?(節選)
王詠剛,2004年8月
 
“Fortran 2003!面向對象的Fortran!自由、開放的Fortran!擁抱Fortran 2003吧!”我手舞足蹈、興奮異常。
“Fortran 2003?你發什麼顛?”地球物理系一位戴着寬邊眼鏡的博士生攔住了我,鄙夷的目光從厚重的眼鏡片裏直射過來,“我昨天才用Fortran 77做完了課題。你說的‘面向對象’、‘自由’、‘開放’什麼的,都是你們程序員的鬼把戲吧?它們能讓我的SCI論文數量翻番嗎?能讓我提前評上副教嗎?”
“……”

1.不斷變革的Fortran
2004年5月,Fortran 2003,這個新世紀裏誕生的Fortran語言新標準,終於在ISO、IEC的聯合工作組JTC1/SC22/WG5以及美國Fortran委員會NCITS/J3的共同努力下,走完了編撰、修訂的最後一步。不出意外的話,再過一兩年,支持Fortran 2003的開發工具就會充斥Fortran世界;那些仍在堅守Fortran 77陣地的老用戶們也會自然而然地把質疑的目光從Fortran 90/95投向更富有革命精神的Fortran 2003。
要了解Fortran 2003,我們有必要先簡單回顧一下Fortran語言的歷史。
1954到1957年間,世界上第一種高級程序設計語言——Fortran誕生於IBM公司。Fortran這個名字的原意是IBM Mathematical FORmula TRANslation,其設計目的在於爲科研人員提供一種符合數學思維習慣的高級語言,以滿足科學計算的需要。1960年代,在美蘇太空競賽的大背景下,在國防、教育和科研領域對高性能計算工具的迫切需求下,Fortran語言蓬勃發展,成爲了當時統治計算機世界的高級語言之王。
…… …… ……

2.面向對象的Fortran
從結構化程序設計到面向對象,這是大多數高級語言的發展、演變規律,Fortran也未能免俗。在Fortran 77中,由於缺乏對數據抽象和數據封裝的基本支持,人們很難引入面向對象的理念和方法。在Fortran 90/95中,儘管我們可以用派生類型(Derived Type)和模塊(Module)模擬一部分面向對象的特性,但卻無法實現真正意義上的封裝和繼承。
對數據和相關操作的封裝是面向對象的基礎。傳統的結構化程序設計語言大多擁有簡單的數據封裝能力(如Pascal語言中的record),但缺乏對操作封裝的支持。當我們爲結構化程序設計語言引入面向對象機制時,在語法層面一般有兩種思路:一種是引入一個全新的語法容器,允許用戶藉助該容器定義出封裝了數據和操作的統一數據類型,例如,C++在C語言的基礎上擴展出了class的概念,並以class爲中心支持面向對象編程;另一種是通過某種機制,將原有的數據封裝容器和表述操作的過程或函數捏合在一起,例如,Ada 95利用Ada 83中已有的概念,將private type和相關操作封裝在package中,創建了完整的面向對象機制。Fortran 2003對Fortran 90/95的改造正是遵循着後一種思路進行的。
首先,Fortran 2003第一次引入了過程指針(Procedure Pointer)的概念。Fortran 90/95只支持普通指針。爲了實現回調機制,Fortran 90/95特意引入了用過程名充當形式參數(Dummy Procedure)的語法,但這種語法還無法解決在數據類型中內嵌相關操作的問題。在Fortran 2003中,我們可以使用過程指針將數據和操作綁定在一起:
TYPE point
 REAL :: x, y
 PROCEDURE (testif), POINTER :: test
END TYPE
這種綁定是一種運行時的動態綁定,我們可以根據需要爲過程指針賦值,這類似於我們在C語言的struct中嵌入函數指針。
其次,如果與類型相關的操作在編譯時已經預知,我們就可以直接使用Fortran 2003提供的類型綁定過程(Type-bound Procedure),將數據和操作關聯在一起:
TYPE point
 REAL :: x, y
CONTAINS
 PROCEDURE :: test => my_test
END TYPE
這樣,在同一個模塊中,類型和相關操作相互關聯,用戶可以直接使用CALL p1%test或類似的代碼來訪問特定操作,這已經非常近似於Ada 95的封裝機制了。
和C++或Java語言相比,Fortran 2003的這種過程綁定方式較爲靠近語言設計的底層。例如,對於綁定在point類型中的my_test過程,我們必須顯示指明,該過程的第一個參數爲point類型:
SUBROUTINE my_test(a)
 TYPE(point), INTENT(IN) :: a
END SUBROUTINE
這裏的參數a相當於C++或Java方法中隱含的this參數,其目的是將調用該操作的對象實例傳入過程。我把這種顯示實現this參數的做法稱爲“赤裸裸的面向對象”。儘管寫起來稍嫌繁瑣,但這種“赤裸裸”的做法也有不少好處。例如,我們可以在Fortran 2003中使用NOPASS屬性禁止傳遞對象實例,或通過PASS屬性改變對象實例參數在過程參數表中的位置。
…… …… ……

3.自由的Fortran
靈活性一直是Fortran語言的一個弱項。早期的Fortran甚至不支持內存的動態分配。Fortran 90引入了指針的概念,全面支持數據的動態存取,同時也引入了泛型過程(Generic Procedure)的機制,以支持與C++的函數重載類似的功能。在此基礎上,Fortran 2003通過參數化派生類型、覆蓋、多態型等機制,進一步增強了Fortran語言的靈活性。例如:
TYPE point(k, n)
 INTEGER, KIND :: k = KIND(0.0D0)
 INTEGER, LEN :: n
 REAL(KIND=k) :: x, y
 CHARACTER(LEN=n) :: name
END TYPE
基於上面這樣的參數化派生類型(Parameterized Derived Type),我們可以在定義對象時,根據需要指定對象的具體類型參數,也可以在程序運行期間,動態指定可分配內存對象的類型參數(Deferred Type Parameter)。
除了Fortran 90已經實現的重載(Overloading)機制以外,Fortran 2003還允許擴展類型覆蓋(Overriding)基類型中的類型綁定過程。更重要的是,Fortran 2003通過抽象類型(Abstract Type)、延遲綁定(Deferred Binding)、多態實體(Polymorphic Entity)、類型選擇結構(SELECT TYPE)等要素完整地實現了面嚮對象語言必備的多態機制。舉例來說,我們可以聲明下面這樣的抽象類型:
TYPE, ABSTRACT :: point 
 REAL :: x, y
CONTAINS
 PROCEDURE(testif), DEFERRED :: test
END TYPE
ABSTRACT INTERFACE
 SUBROUTINE testif(p)
  CLASS(point), INTENT(in) :: p
 END SUBROUTINE
END INTERFACE
上述代碼相當於在C++或Java語言中聲明瞭一個抽象類,其中的test過程相當於C++語言中的一個純虛函數,只有接口聲明,而沒有實現代碼。在此基礎上,我們可以從抽象類型point擴展出具體的子類型。
當某個對象的具體類型在運行時才能確定時,我們可以用CLASS關鍵字(這裏的CLASS指的是一組有繼承關係的類型,與C++中的class並不等同)定義一個具有多態功能的指針或可分配對象:
CLASS(point), POINTER :: p
現在,指針p可以指向任何由point擴展的具體類型的對象,這種使用方式已經和我們在C++中用基類指針引用派生類對象的做法一模一樣了。使用這種具有多態性特徵的實體時,我們還可以用Fortran 2003提供的內部過程SAME_TYPE_AS和EXTENDS_TYPE_OF來判定對象的類型,這是一種簡單的運行時類型識別(RTTI)機制,其功能和C++語言中的typeid關鍵字相仿。
…… …… ……

4.高性能的Fortran
與其他科學計算語言或工具相比,Fortran語言在性能上歷來是出類拔萃的。因爲語言本身專門針對數值計算、矩陣處理等功能進行了優化,大多數Fortran編譯器產生的可執行代碼在效率上甚至會超過以高效著稱的C或C++語言。爲了在高性能的並行處理系統(如IBM的“深藍”和我國的“曙光”)上獲得更出色的執行效率,Fortran 95還特意吸收了HPF語言的優點,爲Fortran語言增添了若干支持並行計算的語法特徵(比如著名的FORALL語句和PURE過程)。
繼續改進Fortran語言的計算性能當然也是Fortran 2003的任務之一。一個最明顯的例子是,Fortran 2003引入了VOLATILE屬性。這個屬性類似於C語言或Java語言中的volatile關鍵字。編寫過併發或實時應用的程序員都知道這個含義爲“易變”的關鍵字的價值:在併發系統中,如果沒有這個關鍵字的幫助,我們就必須時刻警惕共享數據的取值是否已被正確刷新。
不過,相對而言,Fortran語言本身的並行計算機制仍不算十分健全。編寫併發或實時程序時,Ada語言中的任務(Task)管理和同步(Synchronization)機制,或是Java語言中的多線程同步特性都可以爲程序員提供更有力的支持。
實際上,Fortran 95和Fortran 2003陸續引入並行語法的目的之一是消除標準Fortran語言與已經存在並得到廣泛應用的各種Fortran語言變種之間的隔閡,允許同一份Fortran代碼在不同的語言環境間移植。至少到Fortran 2003爲止,標準Fortran語言還沒有能力完全替代以HPF爲代表的“高性能”Fortran語言變種。僅就適應高性能並行計算環境的能力而言, HPF等Fortran變種也仍有足夠的理由繼續存在和發展,直到未來某一個大而全的Fortran標準把它們真正統一起來爲止。
爲了適應現代CPU的時鐘精度,Fortran 2003擴展了內部過程SYSTEM_CLOCK的功能,允許其COUNT_RATE參數爲INTEGER或REAL類型。
…… …… ……

5.開放的Fortran
傳統意義上的Fortran語言看上去並不那麼開放,這恐怕和Fortran語言向來只注重科學計算,而忽視語言通用性的習慣有關。中國的Fortran用戶最常抱怨的兩件事情是:不同的Fortran編譯器連接外部程序(如C語言程序或Matlab程序)的方法不盡相同,不同的Fortran編譯器對中文的支持能力也強弱有別。人們迫切希望制定Fortran標準的專家們能體諒到最終用戶的苦衷,儘早將Fortran納入開放、規範的發展軌道。
在開放性方面,Fortran 2003爲我們帶來的第一個福音是,新標準終於規範了Fortran語言與C語言的連接方式。Fortran 2003提供了一個名爲ISO_C_BINDING的內部模塊,該模塊定義了Fortran與C語言連接時必需的類型常量。引用了ISO_C_BINDING模塊後,我們就可以……
…… …… ……

6.象牙塔裏的Fortran
無論Fortran 2003多麼強調面向對象、靈活和開放,Fortran語言在根本上仍然是一種面向科學計算的高級程序設計語言。
環顧一下四周,我們很容易發現,Fortran語言最常出現的地方也是科技創新最活躍、知識密集度最大的地方:在中科院大氣物理研究所裏,研究人員們正使用Fortran語言編寫大氣數據分析軟件;在國家高性能計算中心裏,Fortran語言正在新安裝的曙光並行計算機上執行着各種科學計算任務;在一個又一個分子生物學、高能物理學、應用數學的國家重點實驗室裏,Fortran是研究者們最爲倚重的工具之一;在相當數量的理工科學生的課程表中,Fortran是學生進入大學課堂後接觸的第一門高級語言……
但正如本文開頭那位博士生所說的那樣,國內的Fortran語言應用多半還侷限在Fortran 77的層面,大多數研究者仍在使用打孔卡片式的代碼風格編寫Fortran程序。這件事背後的潛臺詞是:一方面,Fortran 77已經可以滿足大多數科研人員的需要,另一方面,科研人員不是專業的程序員,不可能有充足的時間學習新語言。在這種情況下,我們有什麼理由讓科研人員學習更復雜的面向對象語法並轉向更強大的Fortran 95或Fortran 2003呢?
我個人覺得,Fortran 2003爲所有Fortran用戶帶來的不僅是新鮮的語法特性,也是一種新的選擇和機遇。
…… …… ……

7.明天的Fortran
根據JTC1/SC22/WG5工作組和NCITS/J3委員會的規劃,2004年5月到2009年8月是下一代Fortran標準的醞釀、編撰和定稿時間。到了2010年時,Fortran語言會變成什麼樣呢?
在高級程序設計語言的發展史中,我們可以很容易地找出兩種截然不同的語言風格。
第一種是LISP語言開創的“實驗風格”,這種風格強調高級語言的語法邏輯應儘量服從計算機表達數據和操作的基本方式,以充分發揮計算機的“智慧”。例如,LISP語言中用“廣義表”來統一描述代碼和數據,以及Smalltalk語言用“對象-消息”這樣的基本語法結構來實現面向對象機制的做法都是這種風格的完美體現。不幸的是,“實驗風格”的語言儘管在表達能力和邏輯性上表現出色,但因爲更接近電腦而不是更接近人,它們在與普通程序員的溝通上總顯得力不從心,無法得到大多數程序員的認可。
第二種是Fortran語言開創的“實用風格”,這種風格強調高級語言的語法應儘可能接近人類的自然語言或特定領域(如科學計算)的思維習慣,以簡化程序員的編碼或維護工作,降低程序員的學習難度。直接受Fortran影響的BASIC語言,以及間接受Fortran影響的C、Pascal、Ada、C++、Java、C#語言都是這種風格的傑出代表。在現代軟件產業中,“實用風格”的語言佔據了絕對的優勢,但隨着軟件規模的增大,它們也逐漸暴露出了靈活度不足、表達能力不強、與計算機交流不順暢的弱點。
現在看來,“實驗風格”和“實用風格”在一定程度上的相互融合、相互促進是未來程序設計語言發展的總體趨勢。這一點可以從Python、Ruby等新生代腳本語言的蓬勃發展中見到一些端倪。
根據這樣的判斷,Fortran語言在未來的幾年裏,是不是也會向更靈活、更富有表達能力的“實驗派”靠攏呢?也許是,也許不是。但無論如何,Fortran語言注重科學計算、注重執行效率的基本特徵都不會改變,語言設計者們仍要在Fortran語言天生的“科學屬性”與“現代化”改造的矛盾中謹慎前行——沒辦法,誰讓Fortran語言生來就活脫脫是一個愛科學、講科學、用科學的“動腦筋爺爺”呢?

 

發佈了76 篇原創文章 · 獲贊 2 · 訪問量 48萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章