Clojure學習筆記(一)——介紹、安裝和語法

 

什麼是Clojure

Clojure是一種動態的、強類型的、寄居在JVM上的語言。java

Clojure的特性:node

  • 函數式編程基礎,包括一套性能能夠和典型可變數據結構媲美的持久性數據結構
  • 由JVM提供的成熟的、高效的運行時環境:因此Clojure可使用Java類庫,反之Clojure庫也能夠被Java使用
  • 跟JVM/Java的互操做能力使得不少架構、運維方面的需求能夠獲得知足:Clojure代碼能夠像Java代碼同樣被打包,而後部署到任何Java應用能夠部署的地方
  • 一套提供併發、並行語義的機制:Clojure的應用類型強制咱們把對象的狀態和對象的標識區分開(這是個天才的思想,參見[1][2]),對於多線程的支持使得咱們不用手動加鎖,解鎖也能編寫多線程代碼
  • 是一種Lisp方言,所以提供了很是靈活、強大的元編程能力:Clojure保留了Lisp的最好的特性,去掉了Lisp方言的缺陷。

 

安裝Clojure

由於Clojure須要運行在JVM上因此須要JRE。而後能夠在http://clojure.org/community/downloads下載Clojure的代碼。有了這些就能夠運行Clojure的REPL了。程序員

運行REPL

從命令行運行運行REPL的方式:1. 進入下載的Clojure目錄;2.運行java -cp clojure-1.8.0.jar clojure.main,若是會看到以下,則成功:正則表達式

 爲了之後運行方即可以建立一個shell腳本cljREPL.sh,內容以下:shell

#!/bin/sh 
cd /home/namenode/Code/workspace/clojure-1.8.0
java -cp clojure-1.8.0.jar clojure.main 

而後,修改執行權限:編程

chmod +x cljREPL.sh

而後建立軟連接:數組

sudo ln -s /home/namenode/Code/workspace/clojure-1.8.0/cljREPL.sh /bin/cljREPL

這樣在終端直接輸入cljREPL就能夠直接運行Clojure的REPL了數據結構

安裝Clojure命令工具

在Ubuntu下能夠直接用apt-get安裝Clojure。多線程

sudo apt-get install clojure1.6

測試,建立文件balance.clj(例子來自《Java虛擬機併發編程》)架構

 

(def balance(ref 0))
(println "Balance is " @balance)
 
(dosync
(ref-set balance 100))

(println "Balance is now " @balance)

運行:clojure balance.clj則會打印下圖的結果

 

語法

Clojure、Java、Python和Ruby中的函數調用語法比較

同像性

Clojure是由Clojure自身的數據結果:原子值(字符串、數字等)和集合的字面量來表示。這種特徵就叫「同像性」,或者稱爲「代碼即數據」。

Clojure沒有定義一種將會別轉換成AST(Abstract Sytax Tree,抽象語法樹)的語法,Clojure代碼是直接用表示抽象語法樹的Clojure數據結構來寫的。

 

Clojure使用數據來表示語言代碼的特徵使得Clojure代碼能夠很容易地用來編寫和轉換其餘Clojure代碼。這是宏(Macro)的基礎,Clojure中的元程序編程工具要比C語言中提供的那種宏以及其餘文本預處理器要強勁的多。

Clojure Reader

Clojure reader的功能是把程序員寫的文本格式的代碼轉換成Clojure數據結構。Reader的全部操做是由一個叫read的函數定義的,這個函數從一個字符流裏讀入代碼的文本形式,產生這個文本所對應的數據結構。Clojure的REPL就是使用Reader來讀入文本代碼的, reader的做用其實能夠看作是反序列化的過程。與read和read-string對應的兩個函數是pr和pr-str,這兩個函數是序列化的過程。

全部Clojure的數據結構和值序列化以前都是既對人可讀,又對機器可讀

標量字面量

字符串

和Java等語言同樣 「Hello World」

並且Clojure自然支持多行

布爾值

Clojure中用true和false表示布爾值

nil

Clojure中的nil和Java中的null是相似的,在判斷中nil是邏輯的false

字符

字符字面量是經過反斜槓加字符表示的:

對於Unicode編碼和octal編碼,可使用對用前綴:

同時對於一些特殊字符也有對應的常量:

\space
\newline
\formfeed
\return
\backspace
\tab

關鍵字

關鍵字始終是以冒號開頭,它能夠包含任意非空字符。若是關鍵字裏麪包含/,表示這個關鍵字是命名空間限定的。若是關鍵字是以兩個冒號(::)開頭的,那麼表示是當前命名空間的關鍵字。若是關鍵字以兩個冒號開頭,同時又包含了/,如::alias/kw,那麼表示某個特定命名空間裏面的關鍵字。這個設計與XML裏面的命名空間實體的用法和動機是同樣的,也就是爲了讓同一個名字在不一樣的命名空間裏有不一樣的值和語義。

符號

符號也是一種標識符,符號的值是它所表明的Clojure運行時裏面的那個值,這個值可使var所持有的值、Java類、本地引用等。

數字

十六進制:0xff  八進制:040(以0開頭)   任意進制:BrN(N表示數字,B表示進制)  有理數:用比例數表示

 

正則表達式

以#開頭,不須要對反斜槓轉義

註釋

  • 單行註釋以分號開頭
  • 形式級別的註釋#_宏,告訴reader忽略下一個Clojure形式

空格和逗號

在Reader眼裏,逗號就是空格

集合字面量

 

命名空間

全部的Clojure代碼都是在一個命名空間中被定義和求值的。命名空間能夠禪城Ruby和Python的module,Java的package。

Clojure中的一種引用類型var是一種可修改的內存地址,從而能夠保存任何值,在var被定義的命名空間裏,var和一個符號相關聯,而後咱們就能夠經過這個符號來使用這個var,從而獲得這個var的值。

在Clojure中var是用def來定義的。如:

在當前命名空間user中定義了一個名叫x的var

當前的命名空間始終綁定到*ns*上

符號求值

阻止求值:quote

阻止求值也能夠用單引號表示

代碼塊:do

do會依次傳入進來全部的表達式,而且把最後一個表達式的結果做爲返回值

定義Var:def

本地綁定:let

全部本地綁定都是不可變的;let的綁定數組在編譯期間在編譯器間能夠對通用集合進行解構,利用解構,能夠大大簡化從綁定數據中抽取想要的數據的操做。

解構:let

不少Clojure函數都接受順序性數據結構和map做爲參數或返回值,並且接受或返回抽象數據類型。這使函數在調用Clojure類庫時,不須要額外的代碼去對接具體數據結構的實現,也就不須要一些glue code來作類型轉換之類的事情,可保持代碼簡單

定義函數:fn

函數是把參數值綁定到參數上,在執行

defn

defn基於fn,封裝了def和fn的功能,定義一個具備名的函數

判斷:if,when,cond

循環:loop和recur

與Java的互操做:.和new

異常處理:try和throw

狀態修改:set!

鎖的原語:monitor-enter和monitor-exit

參考

  1. http://ifeve.com/stm-1/
  2. Dr. Alan Kay, 《on the Meaning of 「Object-Oriented Programming」》, http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht81Ht/doc_kay_oop_en
  3. Chas Emerick, Brian Carper, Christophe Crand,《Clojure編程》
相關文章
相關標籤/搜索