必威电竞|足球世界杯竞猜平台

ML語言
來源:互聯(lián)網(wǎng)

ML語言是通用的函數(shù)式編程語言,由愛丁堡大學的Robin Milner及他人在二十世紀七十年代末開發(fā)的。其語法是從ISWIM得到的靈感,作為元語言的ML是為了幫助在LCF定理證明機中尋找證明策略而構(gòu)想出來的。

ML語言簡介

ML 是一個通用的函數(shù)式編程語言,它是由愛丁堡大學的Robin Milner及他人在二十世紀七十年代晚期開發(fā)的。它的語法是從ISWIM得到的靈感。作為元語言的ML是為了幫助在LCF定理證明機中尋找證明策略而構(gòu)想出來的。(之前的元語言是pplambda,它聯(lián)合了一階邏輯演算、多態(tài)及Λ演算)。它使用了Hindley-Milner類型推論算法來推測大多數(shù)值的類型,而不需要四處使用注解。

ML一般被歸為非純函數(shù)式編程語言,因為它允許副作用和指令式編程。這一點和純函數(shù)式編程語言例如Haskell很不一樣。

ML特性有惰性求值的求值策略,一階類型函數(shù),帶有垃圾收集的自動內(nèi)存管理,參數(shù)多態(tài),靜態(tài)數(shù)據(jù)類型,類型推斷,代數(shù)數(shù)據(jù)類型,模式匹配和異常處理。

不像Haskell,ML使用表達式求值,也就是說所有的子表達式總是被求值。導致的一個結(jié)果是你不能使用無窮表。然而,惰性求值產(chǎn)生的無窮表可以通過使用匿名函數(shù)來模擬。

今天在ML家族中有好幾種語言:兩種主要的方言是Standard ML和Caml,其他的包括F# - 針對Microsoft .NET平臺的開放研究項目。ML中的思想影響了眾多的語言,例如Haskell,Cyclone和Nemerle?! L的實力大多被用于語言設計和操作(編譯器、分析器、定理證明機),但是它作為通用語言也被用于生化,金融系統(tǒng),和宗譜數(shù)據(jù)庫,一個P2P的客戶/服務器程序等等。

ML可以算一種具備命令式語言特點的函數(shù)型語言,或者說面向函數(shù)的命令型語言。和LISP一樣,ML具有非常靈活的函數(shù)功能。例如一個表達式的值可能就是一個函數(shù),這個函數(shù)可以被作為參數(shù)傳遞給另一個函數(shù),或者函數(shù)的返回值就是一個函數(shù)。同時和ALGOL類的語言比較接近的是,ML的語法象命令型的,而且用起來象用Algol家族的很多比較新的后代們一樣方便。而且ML有并行擴展,可以用來寫并行系統(tǒng);甚至還有面向?qū)ο髷U展。

John C. Mitchell在他的Concepts in Programming Langugaes一書中使用ML來展示Algol類語言、LISP類語言、以及并行語言和面向?qū)ο笳Z言中的概念。

ML是Robin Milner主管LCF項目時設計的。LCF項目是受Dana Scott給出的一組邏輯原則啟發(fā)而設立的,致力于開發(fā)一種“可計算函數(shù)邏輯”(Logic of Computable Functions)。Robin Milner的目標是構(gòu)造一個方便實用的系統(tǒng),來自動的或者半自動的證明函數(shù)程序中一些有趣的性質(zhì)。他的LCF項目于1970年在Standford開始,并于1980年代在Edinburge繼續(xù)進行。期間取得了很多重要進展,并且激發(fā)了相關(guān)領域的一系列研究工作。

ML是作為LCF項目的元語言(Meta Language)設計的,這也是其名字的來歷。它的最初用途是寫一些可以生成數(shù)學證明的程序。今天,大多數(shù)著名的推理系統(tǒng)都是用ML寫的。

目前ML有兩個發(fā)展分支:Standard ML和Caml。

大多數(shù)SML編譯器的行為方式都是交互式的:用戶一條一條輸入語句,編譯器一一給出反饋??雌饋硐?a href="/hebeideji/4869022066093875087.html">LOGO語言或者Basic解釋器一樣。但是其實用戶輸入的程序是被先編譯再執(zhí)行的(其中細節(jié)大家可以從SML/NJ編譯器的相關(guān)文檔和論文中找到)。

ML的相關(guān)資源

SML New Jersey --> http://www.smlnj.org/

最著名的SML編譯器——Standard ML New Jersey的官方網(wǎng)站。其中還可以找到很多SML相關(guān)的內(nèi)容

Programming in Standard ML --> http://www.計算機科學cmu.edu/afs/cs/usr/rwh/public/www/introsml/

教科書——Programming in Standard ML。

Emacs作為SML的開發(fā)環(huán)境

目前有兩個常用的SML的Emacs mode。一個是 Stefan Monnier寫的,功能強大一些??梢詮倪@里下 載。SML/NJ的網(wǎng)站上有它的文檔。

一個在線教程

Programming in Standard ML '97: On-line Tutorial --> http://www.減壓病ed.ac.uk/home/stg/NOTES/

SML的Basic Library文檔

如果要用ML寫能實際干點事情的程序,離了Standard ML Basic Library是不行的。SML/NJ編譯器安裝時已經(jīng)包含了Basic Library,你可以直接使用。

ML編程環(huán)境的配置

在Windows環(huán)境下使用Emacs作為ML的集成開發(fā)環(huán)境。下面關(guān)于Emacs和SML在Windows下的配置說明其實同樣適合于各種Unix類操作系統(tǒng))。這里有一副抓圖:在左邊的frame中編輯好SML源程序后,按下C-c C-b,程序就交付給運行在右邊f(xié)rame中的SML編譯器了。你也可以直接在右邊的frame中交互式的輸入SML程序。

為了配置這個環(huán)境我安裝了GNU Emacs for Windows(你也可以用XEmacs for Windows)、SML編譯器SML/NJ(你也可以用其他編譯器,比如Moscow ML,Poly/ML)、Emacs的SML mode。安裝和配置步驟如下:

下載和安裝GNU Emacs for Windows

下載和安裝SML New Jersey編譯器

下載和安裝Emacs的SML major mode。具體的方法如下:

在你的Emacs安裝目錄(例如F:\Program Files\emacs-21.3)下建一個子目錄叫site-LISP。如果已經(jīng)有了就不用建了。

在其中建一個子目錄叫sml-mode

將你下載的SML major mode壓縮包解開,將其中所有.el文件拷貝到site-lisp/sml-mode子目錄下

編輯site-lisp中的site-start.el,加入兩行:

(add-to-list 'load-path "F:/Program Files/emacs-21.3/site-lisp/sml-mode")

(load "sml-mode-startup")

在PATH環(huán)境變量里包含SML編譯器所在的目錄。我的是f:\sml\bin。

啟動Emacs后,敲 M-x run-sml就可以在Emacs中啟動一個SML交互環(huán)境。

如果用 M-x sml-mode就將當前buffer的major mode設置為sml-mode,你會發(fā)現(xiàn)其中的SML代碼被語法高亮顯示了。如果沒有語法高亮,你可以在Emacs的配置文件(對于Windows版本的GNU Emacs和XEmacs而言是C:\.emacs,對Unix版本的是~/.emacs)中加入一行:

SYNTAX highlight

(global-font-lock-mode t)

從例子看ML編程風格

通常大家學習編程都是從命令式語言開始的。和函數(shù)示語言不同,命令式語言以語句作為基本單位。ALGOL家族的所有語言都是命令式語言,ML也不例外。因此學習ML不像學習Scheme那樣需要完全轉(zhuǎn)換一套思路。但是ML繼承了函數(shù)式語言的很多特征,而且也有自己的一些特點。

線性數(shù)據(jù)結(jié)構(gòu)

程序中總要定義數(shù)據(jù)結(jié)構(gòu)。常用的定長線性結(jié)構(gòu)包括:Pascal的record,C的struct,C++和Java的class。在ML中我們通常用tuple,即用圓括號括起來的,用逗號分隔的若干項元素。

Tuple是個線性結(jié)構(gòu),可以用整數(shù)索引。比如

#1(1, 2.0, "apple") = 1

#2(1, 2.0, "apple") = 2.0

#3(1, 2.0, "apple") = "apple"

ALGOL類語言的數(shù)組不同的是,tuple中各個元素的類型可以不一樣。

C++的boost模板庫中提供了一個模板tuple,模仿ML/Scheme的tuple,使C++程序員可以將不同類型的數(shù)據(jù)組織成一個便于訪問的線性結(jié)構(gòu)。

函數(shù)的嵌套定義

ML和大多數(shù)Algol類語言一樣支持函數(shù)的嵌套定義(包括Algol 60、Algol 68和Pascal,但是C是例外)。

如果函數(shù)A和函數(shù)B互相嵌套調(diào)用(indirect recursion),則源程序中可以將B的函數(shù)體定義在 A的函數(shù)體內(nèi),或者A的定義在B的函數(shù)體內(nèi)。具體采用那一種,要看外界是調(diào)用A還是B。

函數(shù)addqueen和其內(nèi)部函數(shù)try就是這樣的例子。顯然addqueen是要被外部調(diào)用的。

用尾部遞歸(tail recursion)代替循環(huán)

如果用ALGOL類語言(例如 Pascal和C)來寫函數(shù)addqueen,其中需要一個循環(huán),從某行的第一個位置開始,判斷如果在這個位置上放一個皇后是否可以使得其不和前面已經(jīng)放上的皇后沖突,而且后面還可以繼續(xù)放滿皇后。而ML中這個循環(huán)用遞歸函數(shù)tryARow表示。

純表達式(pure expression)風格

大多數(shù)Algol類語言對機器的抽象是以內(nèi)存為中心的,即變量和對象(object)對應內(nèi)存中的存儲區(qū)域,賦值語句對應機器的訪存操作,所以程序中有大量的賦值語句。ML也支持賦值,但是通常建議采取的風格是類似LISPScheme的純表達式風格,避免賦值操作。

例如如果用C來描述n皇后問題,通常我們會設計一個數(shù)據(jù)結(jié)構(gòu)描述棋盤(和ML程序一樣),然后定義這個數(shù)據(jù)結(jié)構(gòu)的一個實例(可能是個全局變量)。算法的主要工作是通過賦值修改這個實例的內(nèi)容。

而例子中的ML代碼中經(jīng)典的一段是函數(shù)place。這是修改棋盤數(shù)據(jù)結(jié)構(gòu)的代碼。但是并沒有使用賦值,而是產(chǎn)生了一個新的數(shù)據(jù)結(jié)構(gòu)實例,其內(nèi)容和參數(shù)略有區(qū)別(放上了一個新的皇后)。

純表達式的使用要求程序員先對程序考慮得非常細致才能動筆(動手?),因此使得程序邏輯更加清晰。(這和literate programming的思想是一致的。)但是目前的硬件機器是以內(nèi)存為中心設計的,所以純表達式語言的實現(xiàn)(編譯器和解釋器)的效率依靠于設計者多費心思。ML就是通過靜態(tài)作用域(statically scoping)和uniform data representation等特點結(jié)合起來達到高效的。

參考資料 >

生活家百科家居網(wǎng)