Dylan語言

Dylan是多範型的程式語言，包括了支援函式式和麵向物件程式設計，它是動態和反射式的，卻提供了設計用於支援生成高效機器程式碼的程式設計模型，包括了在動態和靜態行為上的細粒度的控制。它是在1990年代早期由蘋果公司領導的群組創造的。概述.在Dylan參考手冊中有簡明而徹底的語言概述。Dylan派生自Scheme和Common Lisp，並增加了派生自Common Lisp物件系統。Dylan的主要設計目標是成為適合開發商業軟體的動態語言。Dylan嘗試解決潛在的效能問題，透過向完全靈活性的Lisp系統介入“本性”限制，允許編譯器清晰的理解可編譯單元比如函式庫。Dylan從Scheme和其他Lisp派生出了它的很多語義；某些Dylan實現最初建造在現存Lisp系統之內。但是Dylan有著類似ALGOL的語法而非類似Lisp的字首語法。歷史.Dylan是在1990年代早期由蘋果公司領導的一個群組建立的。在它開發的時候，它被意圖用於Apple Newton計算機，但是Dylan實現那時還沒有達到充分成熟，而Newton轉而使用了C和Walter Smith開發的NewtonScript二者的混合。Apple在1995年終止了其Dylan開發努力，儘管他們製作了一個可獲得的“技術發行”版本。其他兩個小組對語言設計和開發實現做出了貢獻：發行了Microsoft Windows下的商業IDE，卡內基·梅隆大學發行了叫作Gwydion Dylan的Unix下的編譯器。二者的實現分別於2004年和1998年開放了原始碼。Harlequin實現當前叫作Open Dylan並由一組志願者維護。Dylan語言的代號是Ralph。James Joaquin選擇名字Dylan表示“動態語言”。語法.Dylan的多數語法特徵來自它的Lisp傳承。Dylan最初使用類似Lisp的字首語法，它基於了S-表示式。到了語言設計完成的時候，語法被變更為類似ALGOL的語法，預期廣泛的程式設計者受眾會更加熟悉它。語法由Michael Kahl設計。它在Dylan參考手冊中有詳盡描述。詞法.Dylan不是大小寫敏感的。Dylan的詞法允許使用連字暨減號的命名約定，來連線多單詞識別符號的各部份。這個約定在Lisp語言中是常見的，但不適用於將不是數值一部份的連字號暨減號，當作一個單一詞法記號處理的那些程式語言，即使在它沒有包圍著空白字元的時候。除了字母數字字元和連字暨減號之外，Dylan允許特定非字母數字字元作為識別符號的一部份。識別符號不可以單獨的由非字母數字字元或數字字元組成。如果有任何歧義，應使用空白。樣例程式碼.有幾個槽的一個簡單的類：define class )slot point-x :: ,required-init-keyword: x:;slot point-y :: ,required-init-keyword: y:;end class ;在約定上，類使用尖括號來命名，比如這個程式碼例子中的類名字codice_1。在codice_2中，codice_3和codice_1二者都是可選的。對所有codice_5子句都是如此。例如，可以寫codice_6或只寫codice_5來終止一個codice_8語句。同樣的類，可以用極小化方式重寫為：define class )slot point-x;slot point-y;end;槽現在都確定型別為codice_9。槽必須被手動初始化。在約定上，常量名字開始於codice_10：define constant $pi ::  = 3.1415927d0;階乘函式：define method factorial (n :: )casen  error("Can't take factorial of negative integer: %d\n", n);n = 0 =&gt; 1;otherwise =&gt; n * factorial(n - 1);endend;這裡的codice_11和codice_12就是正常的識別符號。這裡沒有顯式的返回語句。一個方法或函式的結果是最後求值的那個表示式。除掉在返回位置上的表示式後面的分號是常見的風格。模組與名稱空間.在很多面向物件語言中，類是封裝和模組化的主要方式；每個類定義一個名字空間並控制哪些定義是在外部可見的。進一步的，在很多語言中類定義必須被用作一個整體的不可見單元。例如，使用codice_13串接函式要求匯入並編譯全部的codice_13。某些語言包括Dylan，還包括一個分立的顯式的名稱空間或模組系統，可以用更一般性的方式進行封裝。在Dylan中，編譯單元和匯入單元的概念是分開的，類對於二者都沒有什麼特殊可以言。“庫”定義應當被一起編譯和處理的專案，而“模組”定義一個名稱空間。類可以一起放置在模組中，或分拆至其中，隨程式設計者意願。經常是一個類的完全定義不存在於一個單一的模組中，而是延展於進行選擇性收集的多個模組至上。不同的程式可以有相同的類的不同的定義，並只包括它們所需要的。例如，考慮支援codice_13的一個附加庫regex。在某些語言中，一個功能要被包括在字串中，這個功能就必須被增加到codice_13名稱空間。隨著這種事情不斷髮生，codice_13類變得越來越大，而不需要使用regex的函式仍必須為增加了庫大小付出代價。為此，這種附加件典型的放置在它們自己的名稱空間和物件之中。這種方式的缺點是新函式不再是codice_13的一部份；它轉而被隔離在單獨宣告的它自己的函式集合之中。不再使用codice_19，從OO視角這是自然的組織方式，而是使用像 codice_20這樣的東西，它在效果上反轉了次序。在Dylan之下，可以為相同程式碼定義很多介面，例如codice_13串接方法可以給放置在codice_13介面和codice_23介面二者之中，後者將不同的類中的不同的串接函式收集在一起。這常用於數學庫中，這裡的函式意圖適用於廣泛的不同物件型別。介面構造的更實際用法是建造一個模組的公開和私有版本，在其他語言中這被包括為一個附帶特徵，並總是導致問題並增加語法。在Dylan之下，所有的函式呼叫可以簡單的放置在“私有”或“開發”介面中，而把可公開訪問的函式收集在codice_24介面之中。在Java或C++之下，一個物件的可見性是定義在程式碼中的，意味著要提供類似的變更，程式設計者將被強制的去完全重寫定義，並且不能同時有兩個版本。類.在Dylan中以類似於大多數OO語言的風格，類描述了物件的codice_25。 所有對槽的訪問都要透過方法，就像Smalltalk那樣。預設的codice_26和codice_27方法基於槽名字而自動生成。對比於多數其他OO語言，可應用於類的其他方法經常定義於這個類的外部，因此在Dylan中類定義典型的只包括儲存的定義。例如：define class )slot title ::  = "untitled", init-keyword: title:;slot position :: , required-init-keyword: position:;end class;在這個例子中，定義了類codice_28。codice_29語法只是約定，使得類名字顯得突出，尖括號只是這個類名字的一部份。與之相對比，在一些語言中，約定為大寫類名字的首字母，或給名字字首上C或T。codice_28繼承了一個單一類codice_31，幷包含二個槽：codice_32持有這個視窗標題的字串，和codice_33持有這個視窗一角的X-Y點。在這個例子中，標題給出為預設值，而位置還沒有值。可選的codice_34語法允許程式設計者在初始化這個類的物件時指定這個槽的初始值。在語言比如C++或Java中，類還定義了它的介面。所以在這二種語言中，如果像上述案例中，類定義沒有顯式的對可見性的指令，則對資料成員和方法的訪問都被當作是codice_35，意味著它們只能被子類使用。要使得無關程式碼使用這個視窗的例項，它們必須給宣告為codice_36。在Dylan中，這些槽的可見性規則不被當作這個程式碼的一部份，而是模組/介面系統的一部份。這增加了相當大的靈活性。例如，在早期開發中用的介面可以宣告所有東西為codice_36，而用在測試和部署中用的介面會加以限制。對於C++或Java，這種變更會需要改變原始碼，所有人們就不做了，而在Dylan中，這是完全無關的概念。儘管這個例子沒有用到，Dylan還支援多重繼承。方法和泛化函式.在Dylan中，方法不是固有的關聯於任何特定的類；方法可以被認為存在於這個類之外。就像CLOS，Dylan是基於多分派的，這裡特定方法的呼叫是基於它的所有實際引數的型別來選擇的。方法不需要在編譯時間就知道，基於使用者的偏好，所要求的函式可以是能獲得到的也可以不能。在Java之下，相同的方法被隔離在特定的類之中。要使用這個功能，程式設計者被強制去codice_38這個類並顯式的引用它來呼叫這個方法。如果這個類不可獲得，或在編譯時間未知，這個應用簡單的不能編譯。在Dylan中，泛化函式表示零或多個類似的方法，用codice_39方式建立的所有方法自動的包含在同名的泛化函式之內。泛化函式也可以顯式的用codice_40宣告，允許程式設計者精確控制可以增加哪種方法。程式碼被隔離於儲存而位於泛化函式中。很多類在其中擁有它們自己的方法，因此在感官上就像多數其他OO語言一樣。但是程式碼實際上位於泛化函式之中，意味著它們不附屬於特定的類，並可以被任何人自然的呼叫。下例將類codice_28的方法codice_42併入同名的泛化函式之內：define method turn-blue (w :: )w.color := $blue;end method;這個定義類似於其他語言的定義，並有可能被封裝到codice_28類之中。注意codice_44這個codice_27呼叫，它是codice_46的語法糖。泛化函式的自主利用可見於更泛化的例子之中。例如，在多數語言中的一個常見函式codice_47，它返回這個物件的某種人類可讀形式。比如說一個視窗可能返回它的標題和它在父視窗中的位置，而一個字串將返回它自身。在Dylan中，這些方法可以給收集到叫作codice_47的一個單一模組中，因而這個程式碼被從這個類自身的定義中移除。如果一個特定物件不支援codice_47，可以簡單的在codice_47模組中增加上它。擴充套件性.上述的整體概念可能讓讀者覺得很奇怪。處理一個視窗的codice_47不定義在codice_28之中。除非考慮到Dylan對codice_47呼叫的處理方式，否則就可能變得沒有意義。在多數語言中，在程式編譯的時候，查詢給codice_28的codice_47並把它替代為到這個方法的一個指標。在Dylan中，這發生在程式初次執行的時候，執行時系統建造一個方法名字/形式引數細節的表格，並透過這個表格來動態的查詢方法。這意味著一個特定方法可以位於任何地方，不只是在編譯時間單元中。最後程式設計者得到了在放置其程式碼上的相當大的靈活性，只要合適，可以收集在它的類之中，也可以與相同功能的方法收集在泛化函式中。這裡隱含著程式設計者可以透過在單獨檔案中定義函式，來向現存的類增加功能。例如人們可能希望向所有codice_56增加拼寫檢查，這在多數語言中將需要訪問到字串類的原始碼，而這種基本類很少以原始碼形式給出。在Dylan都會得到這個增加的功能。