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


 

什么是Clojure

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

Clojure的特性:

  • 函數式編程基礎,包括一套性能可以和典型可變數據結構媲美的持久性數據結構
  • 由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,內容如下:

#!/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編程》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM