"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.函數
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語言誕生的時候,就包含了9種新思想。其中一些咱們今天已經習覺得常,另外一些則剛剛在其餘高級語言中出現,至今還有2種是Lisp獨有的。按照被大衆接受的程度,這9種思想依次是:
如今你們都以爲這是理所固然的,可是Fortran I就沒有這個結構,它只有基於底層機器指令的goto結構。
在Lisp語言中,函數與整數或字符串同樣,也屬於數據類型的一種。它有本身的字面表示形式(literal representation),可以儲存在變量中,也能看成參數傳遞。一種數據類型應該有的功能,它都有。
Lisp是第一種支持遞歸函數的高級語言。
在Lisp語言中,全部變量實際上都是指針,所指向的值有類型之分,而變量自己沒有。複製變量就至關於複製指針,而不是複製它們指向的數據。
Lisp程序是一些表達式區塊的集合,每一個表達式都返回一個值。
符號其實是一種指針,指向儲存在哈希表中的字符串。
Lisp並不真正區分讀取期、編譯期和運行期。你能夠在讀取期編譯或運行代碼;也能夠在編譯期讀取或運行代碼;還能夠在運行期讀取或者編譯代碼。
在讀取期運行代碼,使得用戶能夠從新調整(reprogram)Lisp的語法;
在編譯期運行代碼,則是Lisp宏的工做基礎;
在運行期編譯代碼,使得Lisp能夠在Emacs這樣的程序中,充當擴展語言(extension language);
在運行期讀取代碼,使得程序之間能夠用S-表達式(S-expression)通訊,近來XML格式的出現使得這個概念被從新"發明"出來了。
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把語言設計成這個樣子,就是爲了讓這種推導成爲可能。
運行於Java虛擬機的List方言Clojure.
Lisp是一種以表達性和功能強大著稱的編程語言,但人們一般認爲它不太適合應用於通常狀況,而Clojure的出現完全改變了這一現狀。現在,在任何具有 Java 虛擬機的地方,均可以使用 Lisp 的強大功能。
它囊括了函數式編程的全部精華:
避免了不穩定狀態、遞歸、更高階的函數等。
咱們能夠選擇添加類型信息來提升代碼中的關鍵路徑的性能。
Clojure 不只可在 JVM 上運行,並且能夠與Java無縫融合(JVM平臺的語言家族原則上都支持)的互操做性。最後,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是這樣的有潛力、接地氣,那麼若是你要選擇一門新語言來玩玩,不選它選什麼?