Clojure 學習筆記 1
Clojure 是一門運行在 JVM 上的 Lisp 方言。我的學習方式是通過看官網的Getting Started。
Mac OS 下配置開發環境
用 homebrew 先安裝 Java:
brew install java
然後安裝 Clojure 的 REPL 解釋器:
brew install clojure
暫時只安裝了這麽多,沒有安裝 Leiningen 和 Boot。
字面值(Literals)
Clojure 有下面幾種數據類型:
;; 數字類型
42 ; Long - 64 bits 整數
6.022e23 ; Double - 64 bits 浮點數
42N ; BigInt - 高精度整數
1.0M ; BigDecimal - 高精度定點數
22/7 ; 分數
;; 字符類型
"hello" ; 字符串
\e ; 字符
;; 其他類型
nil ; 空值
true ; Boolean 類型(還有 false)
#"[0-9]+" ; 正則表達式
:alpha ; 關鍵字
:release/alpha ; 帶 namespace 的關鍵字
map ; 符號(symbol)
+ ; 符號可以是標點符號
clojure.core/+ ; Namespaced symbol
;
表示註釋,兩個分號表示首行。
另外還有四種 collection 類型:
‘(1 2 3) ; 列表(list)
[1 2 3] ; 向量(vector)
#{1 2 3} ; 集合
{:a 1, :b 2} ; map
求值(Evaluation)
Clojure 不同於傳統的 源代碼 -> 編譯 -> 運行的方式,Clojure 的每一個表達式都能夠求值,通過 Reader 讀取用戶輸入,然後編譯到 JVM 的字節碼,然後在 JVM 上運行求值。
結構(Structure)和語義(Semantics)
示意圖種的綠字表示符號,藍色字表示語義。大部分 Clojure 的表達式對自身求值,除了符號和列表。
如圖所示,(+ 3 4) 讀入一個列表,包含一個符號(+)和兩個數字(3、4),列表中的第一個元素(圖片中 + 所在的位置)被稱作“function position“,表示要調用的函數。
Delaying evaluation with quoting
不知道這裏怎麽翻譯,簡單的說就是用引號表示“推遲求值”,暫時不求出來。
舉個例子:
user=> ‘x
x
這裏 x 前面加了一個引號,解釋器不會對這個符號進行求值,而是保留了這個符號。
我們還可以用引號表示一個列表(list),而不進行求值:
user=> ‘(1 2 3)
(1 2 3)
REPL
REPL(Read-Eval-Print-Loop) 由以下四步組成:
- 讀出表達式
- 對 #1 的表達式進行求值
- 輸出 #2 中求出的值
- 回到最開始
探索 REPL
絕大多數 REPL 環境都有一些小技巧可以交互使用。比如:
*1
表示上一個結果*2
表示上上個結果*3
表示上上上個結果
user=> (+ 3 4)
7
user=> (+ 10 *1)
17
user=> (+ *1 *2)
24
還有一個 namespace 叫 clojure.repl
包含了標準 Clojure 庫,裏面有幾個有用的函數,首先我們要載入這個庫:
(require ‘[clojure.repl :refer :all])
然後我們就可以用這幾個函數了:doc
、find-doc
、apropos
、source
、dir
這幾個函數的具體作用可以在官網上看,我就不列舉出來了。
Clojure 基礎
def
如果你想要在 REPL 環境中用你求值後的值,可以這樣寫:
user=> (def x 7)
#‘user/x
然後我們就把符號(symbol)x
和值(var) 7
關聯起來了,接下來就可以直接用這個符號了:
user=> (+ x x)
14
需要註意的是這個符號默認是 user
這個namespace 中的符號。我們調用的時候也默認實在 user
這個 namespace 中。
打印
Clojure 提供了四種打印函數:
println
是給人讀的帶換行的打印函數prn
是給機器讀的帶換行的打印函數print
是給人讀的不帶換行的打印函數pr
是給機器讀的不帶換行的打印函數
簡單的說,給人讀的會對字符進行轉義,而且會把其中的表達式的值求出來:
user=> (println "This is a\ttest" (+ 1 2 3))
This is a test 6
機器讀的不會轉義,而且也不會把表達式的值求出來。
Clojure 學習筆記 1