Skip to content

Latest commit

 

History

History
223 lines (156 loc) · 6.22 KB

01.md

File metadata and controls

223 lines (156 loc) · 6.22 KB

基本組成

運算式

Clojure 程式是由許多運算式 (Expression) 組合而成。在 Clojure 中,Expression (運算式) 也被稱爲 Form (形式)。一個運算式執行之後 (或叫做 Evaluate 求值),得到執行後的結果。

以 Hello World 範例程式爲例,以下是 Clojure 版本:

(str "Hello " "World")
;; => "Hello World"

以上的運算式使用列表 (List) 來表示函式呼叫,列表使用左右兩個小括號來表示。括號中分別有三個元素:符號 (Symbol) str,以及兩個字串:Hello World

符號 (Symbol) str,對應到 Clojure 內建的函式。Clojure 會找到這個符號對應的函式並呼叫它,執行的結果是將帶入的字串串接起來。

Clojure 與 LISP 家族跟其他語言不同的是,語法採用前置表示法 (或稱做波蘭表示法),將函式或運算元擺放在括號內的第一個位置,之後的位置則擺放各個參數。有些情況下第一個位置擺放的並非函式或運算元,這種特殊的運算式被稱爲 Special forms。

在其他非使用前置表達式的語法中,要將一連串數字相加起來會寫成:

1 + 2 + 3 + 4 + 5

而使用前置表達式的 Clojure 只要寫成:

(+ 1 2 3 4 5)

或是在其他語言中的 +* 的執行優先順序需要注意,一搞錯結果就會不一樣:

1 + 2 * 3

使用前置表達式就非常清楚,誰先處理後處理則一目瞭然:

(+ 1 (* 2 3))

資料型態

Clojure 提供跟其他主流語言類似的資料型態與資料結構,而有些則與主流程式語言不盡相同,這裡先提供大致的導覽,之後文章將會詳細介紹。

數字

Clojure 提供了跟主流語言類似數字表示法,常用的有整數、浮點數和有理數。

整數:

42
;; => 42

浮點數:

3.14
;; => 3.14

有理數:

(/ 1 3)
;; => 1/3

字串

Clojure 的字串使用雙引號方式來表示,引號內擺放需要的文字。型態是 Java 中的字串類型 java.lang.String:

"Issac Asimov"
;; => "Issac Asimov"

字符

Clojure 表現字符 (Character) 的方式與主流程式語言稍有不同,它在欲使用的字符之前加上反斜線 (\):

\A
;; => \A
\B
;; => \B
\b
;; => \b
\a
;; => \a

除了可視字符之外,以下是其它特殊字符的使用方式:

\space
;; => \space
\newline
;; => \newline
\formfeed
;; => \formfeed
\return
;; => \return
\backspace
;; => \backspace
\tab
;; => \tab

布林

Clojure 程式語言使用 truefalse 來表示邏輯上的真與假:

true
;; => true
false
;; => false

除了 true 以及 false 之外,Clojure 還加入了 nil 表示不存在與虛無。當用在邏輯判斷時,nilfalse 被當作邏輯上的假。

符號

符號用來指稱某種東西,例如前面提到的 str+ 用來表示函式與運算元。Clojure 類似於其他程式語言用來定義變數的方式,就是使用 def 定義一個符號以及它對應的事物。

(def clojurist "Bob")
;; => #'user/clojurist
clojurist
;; => “Bob”

使用 def 會建立符號 clojurist 連結到 "Bob" 字串。在 REPL 中看到結果 clojurist 加了 user 與斜線 (/),斜線前面的符號指的是 clojurist 的命名空間 (namespace)。在 REPL 中,預設的命名空間是 user

關鍵字

關鍵字 (Keyword) 與符號的功能類似,也是標識符號 (Identifier),但是關鍵字必須以冒號 (:) 爲開頭,而且關鍵字不代表其他資料,只代表它自己。通常跟映射 (Map) 搭配使用,作爲映射的索引鍵 (Key)。

:foo
;; => :foo
:bar
;; => :bar
{:Lisp "McCarthy" :Clojure "Hickey"}
;; => {:Lisp "McCarthy", :Clojure "Hickey"}

正則表達式

Clojure 將前面加上井號 (#) 的字串視爲正則表達式,型態爲 Java 中的 java.util.regex.Pattern:

(class #"[0-9A-Za-z]")
;; => java.util.regex.Pattern

正則表達式與內建的函式,如 re-seqre-findre-match 一起搭配使用。

群集

當資料變多變雜時,會需要程式語言提供容器將相似的資料整理在一起。Clojure 提供四種群集型態 (Collections):列表 (List)、向量 (Vector)、映射 (Map) 與集合 (Set)。

;; List
'(1 2 3)
;; => (1 2 3)

;; Vector
[1 2 3]
;; => [1 2 3]

;; Map
{:author "Isaac Asimov" :title "I, Robot"}
;; => {:author "Isaac Asimov", :title "I, Robot"}

;; Set
#{1 2 3 4}
;; => #{1 4 2 3}

空白

Clojure 使用空白分隔運算式中的各個元素,主流程式語言中則是使用逗號 (,)。其實也可以使用逗號,它的功能跟空白完全一樣,但是依照編寫的習慣,建議使用空白來區隔元素。逗號通常用來分隔映射裡的元素,以增加可讀性。

{:name "Catherine", :age 40}

註解

以分號 (;) 開頭的文字被視爲單行註解,Clojure 會將它忽略不執行。如果想要撰寫多行註解,可以使用 comment

(+ 1 2) ; the result is 3
;; => 3
(comment
  I have a dream that one day this nation will rise
  up, live out the truth meaning of its creed.)
;; => nil

函式

Clojure 是一個函數式語言,函式的定義與使用至關重要。通常使用 defn 來定義函式:

(defn hello [name]
  (str "Hello, " name))
;; => #’user/hello

defn 的第一個參數用來表示函式的名稱,名稱之後則是新定義函數的參數,中括號裡代表各參數的名字,之後便是函式的本體 (Body)。當函式被呼叫時,本體中的表達式將會被求值,所得到的值就是此函式的返回值。

回顧

從本篇文章中你已經知道了 Clojure 可以表達的數字類型,還有字串與字符的表達方式;也了解用來判斷邏輯真假的布林型態、指稱事物的符號和關鍵字型態;還知道了四種集合型態:列表、向量、映射與集合。還知道了定義函式的方法。

還不賴吧?今天就先到這裡,下一篇文章再見囉!