Clojure與Lisp

Clojure與Lisp

"Lisp 不是一門語言,它是一種構建素材。" (艾倫·凱)java

"任何C或Fortran程序複雜到必定程度以後,都會包含一個臨時開發的、只有一半功能的、不徹底符合規格的、處處都是bug的、運行速度很慢的Common Lisp實現。"(格林斯潘第十定律(Greenspun's Tenth Rule))算法

Clojure是一門Lisp方言(Lisp dialect).express

Lisp 是一種編程語言,以表達性和功能強大著稱,但人們一般認爲它不太適合應用於通常狀況。Clojure 是一種運行在 Java™ 平臺上的 Lisp 方言,它的出現完全改變了這一現狀。現在,在任何具有 Java 虛擬機的地方,均可以利用 Lisp 的強大功能。編程

Clojure 是徹底的,真正意義上的神聖的lisp語言的一個方言.數據結構

lisp語言由於其無以倫比強大能力和幾乎無窮的表達力而得到了盛譽,Clojure天然也不例外. 它的功能和元編程的能力是創建在這樣的基礎之上的:異常馴服的C語言的"石頭" 或 具備 延展性的java語言的"木頭" . 你能夠用幾百行甚至幾十行Clojure代碼取替代幾千行靜態語言 的代碼,伴隨着這而來的是bug數量的減小和開發時間的縮短.多線程

樣板代碼(Boilerplate code )被徹底刪去. 域指定語言(Domain Specific Languages ) 不只 簡單,並且更通常化--lisp程序每每是按照 "自下而上" 的開發方式寫成的. 展開式(演進式)的 結構和語法更適合特定的問題領域. 你在程序運行的時候取修改程序,而不須要從新編譯或重啓 程序.併發

可是,歷史上也有對lisp進行詆譭的人,或許稱爲抱怨更爲合適. lisp發展過程當中,沒有完整的規範, 各類不兼容的實現,陳舊落伍的限制.cruft accumulate 在其存在的四五十年裏一直存在. 對於 大多數人來講,它的語法過於詭異了.編程語言

Clojure 修正上面的大多數這些問題. 它保留了 lisp 的思想和哲學,並同時清除了過去的不少限制. Clojure 高速、乾淨、具備優先能力和優雅的特徵. 可是沒有改變lisp中 "代碼也是數據" 的哲學. Clojure 語言在直覺和觀感上比歷史上的lisp更易於閱讀. 在後面開始學習的初級階段,你就發現雖然 仍有各類括號,可是代碼是難以置信的容易讀和寫.函數式編程

對於那些熟悉lisp語言的人來講,他們很快就會發現他們很是適應Clojure.函數

Lisp簡史

1958年,John McCarthy設計了Lisp語言

20世紀50年代中期,在大多數計算機處理的都是數值數據等,包括語言學、心理學和數學領域上一些人們開始對人工智能產生了興趣。以爲必須實現共同須要的一個方法,使計算機可以處理鏈表中的符號數據,容許語言的處理、信息存入和檢索、定理證實的過程機器化。IBM是首先對人工智能開發有興趣的商業機構之一。

1958年夏天,來自麻省理工學院的人工智能研究先驅約翰·麥卡錫(John McCarthy)參與IBM資訊研究部的工做,研究符號運算及應用需求。但是,IBM旗下的Fortran表處理語言卻未能支援符號運算的遞歸、條件表達式、動態存儲分配及隱式回收等功能。約翰·麥卡錫於1958年秋季回到麻省理工學院後,和Marvin Minsky組成了人工智能項目。開展一個表處理軟件系統來實現McCarthy提出建議採納者程序的工做,爾後推進了表處理語言LISP的誕生。

1960年4月,麥卡錫在ACM雜誌發表了一片文章《遞迴函數的符號表達式以及由機器運算的方式,第一部》.

自1960代末年至1980年初年,各類更新LISP版本涌現,有源自加利福尼亞大學伯克利分校的Franz Lisp、在AutoCAD運行的AutoLISP前身XLISP、猶他大學開展的Standard Lisp及Portable Standard Lisp、專屬於Lisp機器上運行的ZetaLisp、源自法國國家信息與自動化研究所的LeLisp、以及MIT人工智能實驗室的Gerald Sussman與Guy Steele所開發的Scheme等。

  

1984年,改良自MacLisp、集各版本大成、跨平臺、且被目爲事實標準的Common Lisp誕生。至1994年,美國國家標準學會(ANSI)對Common Lisp語言進行了標準化。

自穩定運行的Common Lisp出現起,再有各機構按各自所需而開展後續Lisp,包括1990年來自歐洲用戶的EuLisp、運行於Java虛擬機的Clojure、受到Maclisp影響而創的Emacs Lisp、以及自由開源來自卡內基·梅隆大學的CMUCL、還有IsLisp,Racket,ACL2等蓬勃涌現。

  

自2000年起,LISP共享者協力支援的自由開源社區逐漸造成,致力於LISP後續發展。

當前最新潮的編程語言,只是實現了他在1958年的設想而已。

這怎麼可能呢?計算機技術的發展,不是突飛猛進嗎?1958年的技術,怎麼可能超過今天的水平呢?

這是由於John McCarthy原本沒打算把Lisp設計成編程語言,至少不是咱們如今意義上的編程語言。他的原意只是想作一種理論演算,用更簡潔的方式定義圖靈機。

因此,爲何上個世紀50年代的編程語言,到如今尚未過期?簡單說,由於這種語言本質上不是一種技術,而是數學。數學是不會過期的。

Lisp語言就比如是快速排序(Quicksort)算法,這種算法是1960年提出的,至今仍然是最快的通用排序方法。

Lisp的思想

Lisp語言誕生的時候,就包含了9種新思想。其中一些咱們今天已經習覺得常,另外一些則剛剛在其餘高級語言中出現,至今還有2種是Lisp獨有的。按照被大衆接受的程度,這9種思想依次是:

1 條件結構(即"if-then-else"結構)

如今你們都以爲這是理所固然的,可是Fortran I就沒有這個結構,它只有基於底層機器指令的goto結構。

2 函數也是一種數據類型

在Lisp語言中,函數與整數或字符串同樣,也屬於數據類型的一種。它有本身的字面表示形式(literal representation),可以儲存在變量中,也能看成參數傳遞。一種數據類型應該有的功能,它都有。

3 遞歸

Lisp是第一種支持遞歸函數的高級語言。

4 變量的動態類型

在Lisp語言中,全部變量實際上都是指針,所指向的值有類型之分,而變量自己沒有。複製變量就至關於複製指針,而不是複製它們指向的數據。

5 垃圾回收機制

6 程序由表達式(expression)組成

Lisp程序是一些表達式區塊的集合,每一個表達式都返回一個值。

7 符號(symbol)類型

符號其實是一種指針,指向儲存在哈希表中的字符串。

8 代碼使用符號和常量組成的樹形表示法(notation)

9 不管何時,整個語言都是可用的

Lisp並不真正區分讀取期、編譯期和運行期。你能夠在讀取期編譯或運行代碼;也能夠在編譯期讀取或運行代碼;還能夠在運行期讀取或者編譯代碼。

在讀取期運行代碼,使得用戶能夠從新調整(reprogram)Lisp的語法;

在編譯期運行代碼,則是Lisp宏的工做基礎;

在運行期編譯代碼,使得Lisp能夠在Emacs這樣的程序中,充當擴展語言(extension language);

在運行期讀取代碼,使得程序之間能夠用S-表達式(S-expression)通訊,近來XML格式的出現使得這個概念被從新"發明"出來了。

Lisp的宏

Lisp語言剛出現的時候,它的思想與其餘編程語言截然不同。後者的設計思想主要由50年代後期的硬件決定。隨着時間流逝,流行的編程語言不斷更新換代,語言設計思想逐漸向Lisp靠攏。

思想1到思想5已經被普遍接受,思想6開始在主流編程語言中出現,思想7在Python語言中有所實現,不過彷佛沒有專用的語法。

思想8多是最有意思的一點。它與思想9只是因爲偶然緣由,才成爲Lisp語言的一部分,由於它們不屬於John McCarthy的原始構想,是由他的學生Steve Russell自行添加的。它們今後使得Lisp看上去很古怪,但也成爲了這種語言最獨一無二的特色。

Lisp古怪的形式,倒不是由於它的語法很古怪,而是由於它根本沒有語法,程序直接以解析樹(parse tree)的形式表達出來。在其餘語言中,這種形式只是通過解析在後臺產生,可是Lisp直接採用它做爲表達形式。它由列表構成,而列表則是Lisp的基本數據結構。

用一門語言本身的數據結構來表達該語言,這被證實是很是強大的功能。思想8和思想9,意味着你能夠寫出一種可以本身編程的程序。這可能聽起來很怪異,可是對於Lisp語言倒是再普通不過。最經常使用的作法就是使用宏。

術語"宏"在Lisp語言中,與其餘語言中的意思不同。Lisp宏無所不包,它既多是某樣表達式的縮略形式,也多是一種新語言的編譯器。若是你想真正地理解Lisp語言,或者想拓寬你的編程視野,那麼你必須學習宏。

若是你創造了一種新語言,其中有car、cdr、cons、quote、cond、atom、eq這樣的功能,還有一種把函數寫成列表的表示方法,那麼在它們的基礎上,你徹底能夠推導出Lisp語言的全部其餘部分。事實上,Lisp語言就是這樣定義的,John McCarthy把語言設計成這個樣子,就是爲了讓這種推導成爲可能。

Clojure簡介

運行於Java虛擬機的List方言Clojure.

Lisp是一種以表達性和功能強大著稱的編程語言,但人們一般認爲它不太適合應用於通常狀況,而Clojure的出現完全改變了這一現狀。現在,在任何具有 Java 虛擬機的地方,均可以使用 Lisp 的強大功能。

Clojure 是一種函數式編程語言

它囊括了函數式編程的全部精華:

避免了不穩定狀態、遞歸、更高階的函數等。

Clojure 仍是一個動態類型的語言

咱們能夠選擇添加類型信息來提升代碼中的關鍵路徑的性能。

Clojure 不只可在 JVM 上運行,並且能夠與Java無縫融合(JVM平臺的語言家族原則上都支持)的互操做性。最後,Clojure 在設計上也考慮了併發性,並具備併發編程的一些獨特特性。

Clojure的設計原則

(1)簡單: 鼓勵純函數,極簡的語法(少數special form),我的也認爲clojure不能算是多範式的語言(有部分OO特性),爲了支持多範式引入的複雜度,咱們在C++和Scala身上都看到了。

(2)專一:前綴運算符不須要去考慮優先級,也沒有什麼菱形繼承的問題,動態類型系統(有利有弊),REPL提供的探索式編程方法(告別修改/編譯/運行的死循環,所見即所得)。

(3)實用:前面提到,構建在JVM之上,跟Java語言的互操做很是容易。直接調用Java方法,不去發明一套新的調用語法,努力規避Java語言中繁瑣的地方(doto,箭頭宏等等)。

(4)清晰:純函數(前面提到),immutable var,immutable數據結構,STM避免鎖問題。不可變減小了心智的負擔,下降了多線程編程的難度,純函數也更利於測試和調試。

(5)一致:語法的一致性:例如doseq和for宏相似,都支持destructring,支持相同的guard語句(when,while)。數據結構的一致性:sequence抽象之上的各類高階函數。

光劍說

Clojure有着獨特的吸引力,首先由於它是LISP —— 一門富有傳奇色彩的語言,一直但願有機會能夠學習一門LISP的方言;

其次Clojure是一門接地氣的語言,它運行在JVM這個最成功、應用最普遍平臺之上,可以跟Java代碼無縫互操做,JVM上全部資源均可覺得Clojure所用。

Clojure是這樣的有潛力、接地氣,那麼若是你要選擇一門新語言來玩玩,不選它選什麼?

相關文章
相關標籤/搜索