本篇文章將介紹 Clojure 內建的的資料結構與型態,會先從簡單的資料型態如數字及字串開始,再介紹複雜的資料結構如群集 (Collection) 與序列 (Sequence)。
在 Clojure 中,整數的表示法與主流程式語言無異,如果沒有特別聲明,預設爲十進位表示法。大小爲 64 位元有號整數,內部使用的型態爲 Java 中的 long:
(class 42)
;; => java.lang.Long
42
;; => 42
-42
;; => -42
除了十進位表示法之外,也提供了八進位、十六進位的表示法:
0x2a
;; => 42
052
;; => 42
在數字前面加上 0 被視爲八進位表示法、前面加上 0x 則是十六進位表示法。也可以自行決定數字的基底,只要在數字前面加上想要使用的基底 (範圍從 2 到 36),再加上 r 即可:
2r101010
;; => 42
16r2A
;; => 42
Clojure 的浮點數表示法也與主流程式語言無異,採用的是 IEEE 754 雙精度標準,大小爲 64 位元,內部使用的型態爲 Java 中的 double:
(class 3.14)
;; => java.lang.Double
3.14
;; => 3.14
1.618
;; => 1.618
以指數的方式表現:
3.14e-2
;; => 0.0314
+1.618e-1
;; => 0.1618
Clojure 爲了支持高精度的計算,提供了有理數型態。舉例來說,在其他主流程式語言裡,1/3 的結果爲 0.3333…,或是將浮點數相加起來,原有的精確度反而在計算中喪失了:
>>> 1.0 / 3.0
0.3333333333333333
>>> 0.1 + 0.1 + 0.1
0.30000000000000004
使用有理數型態作運算,不會經過不必要的轉換而喪失準確度,只有在需要的時候,由使用者決定是否該轉換型態。內部使用的型態爲 clojure.lang.Ratio。
(class (/ 1 3))
;; => clojure.lang.Ratio
(/ 1 3)
;; => 1/3
(+ 1/10 1/10 1/10)
;; => 3/10
你可以將有理數轉型成浮點數:
(double 1/3)
;; => 0.3333333333333333
也可以將浮點數轉型成有理數:
(rationalize 0.3)
;; => 3/10
一般來說,預設提供的 64 位元整數與浮點數已經綽綽有餘,但是如果需要處理超過 64 位元範圍的數值,就需要使用到 Clojure 提供的兩個大數型態:大整數 (BigInt)、大浮點數 (BigDecimal)。內部使用的型態分別爲 clojure.lang.BigInt 以及 java.math.BigDecimal。
(class 1N)
;; => clojure.lang.BigInt
(class 2M)
;; => java.math.BigDecimal
大整數的表示法爲在數字後加上大寫的 N;大浮點數則是在數字後加上大寫的 M。內建的 +
、-
、*
、/
、inc
、dec
等運算元,作用在整數時如果超出 64 位元範圍 (overflow),會出現錯誤而拋出例外。如果想避免錯誤,讓 Clojure 把結果套用到大數上,則必須使用大數版的運算元,即在運算元後加上單引號 (‘):
(+ 9141592653589793238 9141592653589793238)
;; => ArithmeticException integer overflow
(+' 9141592653589793238 9141592653589793238)
;; => 18283185307179586476N
基本的四則運算與其他主流程式語言一樣,需要注意的是 Clojure 採用前置表示法:運算元擺在小括號的第一個位置:
(+ 1 2)
;; => 3
(- 1 3)
;; => -2
(* 2 4)
;; => 8
(/ 6 3)
;; => 2
如果想要獲得整數除法運算的商,可以使用 quot
函式:
(quot 47 7)
;; => 6
取得除法運算的餘,則使用 rem
函式:
(rem 47 7)
;; => 5
(未完待續)