今天來說明幾種 Elixir 中的基本型別及一些常用到的語法細節,比較簡單的部份就直接寫 code 不說明了。
# 註解
do_something() # 也可以放在行尾
1 # 整數
0b1010 #整數,2 進位
0o777 #整數,8 進位
0x1F #整數,16 進位
1.5 #浮點數
1.0e-10 #浮點數,科學計號表示法
數字可以用於四則運算 +/2
, -/2
, */2
, //2
1 + 2 #=> 3
10 * 10 #=> 100
6 / 3 #=> 2.0
注意 //2
永遠回傳浮點數,如果你想要整數的結果時,請用 div/2
,若需要餘數,則要用 rem/2
div(6, 3) #=> 2
rem(6, 5) #=> 1
round/1
可以將浮點數四捨五入,trunc/1
則可以取得整數的部份:
round(3.5) #=> 4
round(3.46, 3) #=> 4
trunc(3.8) #=> 3
就 ture
跟 false
。
之前提過可以在 guards 裡用的 and
跟 or
的第一個參數必須要是布林值。例如當 and
的第一個參數是 false
會直接回傳,其它情況則會拿到第二個參數,無論那是什麼。
false and 0
#=> false
true and 1
#=> 1
is_atom(100) or 2
#=> 2
1 and true
#=> ** (BadBooleanError) expected a boolean on left-side of "and", got: 1
相對來說,&&
及 ||
就沒有這種限制:
1 || false
#=> 1
nil && 10
#=> nil
Atom 是常數,長得像這樣 :foo
。當宣告了一個 atom 後,整個應用程式將從此參考同一個值。在 Ruby 裡一樣的型別叫做 symbol 。
如果需要在 atom 裡放 .
或
,可以這樣宣告: :"my atom"
之前提到的布林值其實也是個 atom。
true == :true
#=> true
is_atom(false)
#=> true
而當你定義 module 名稱時,會使用 CamelCase 來取名,這在 elixir 中稱做 aliases (別名)。這其實也是用 atom 實作的。
is_atom(MyModule)
#=> true
MyModule == :"Elixir.MyModule"
#=> true
要特別注意的是,atoms 一旦宣告後,完全不會被垃圾回收,所以不要用程式來自動產生大量的 atoms。
在 Elixir 裡,字串是用雙括號括起來的。 而跟 Ruby 一樣,也可以使用 string interpolation:
"This is a string"
i = 5
"I need #{i} apples"
判斷型別要這樣:
s = "hełło"
is_bitstring(s)
#=> true
而字串相加要用 <>
"Hello" <> " world"
#=> "Hello world"
重點小技巧是這也可以拿來做 pattern matching:
"Hello " <> name = "Hello Tai"
#=> name = "Tai"
在 Elixir 裡,你可以用單括號括起一串字,雖然試著印出來的時候好像蠻正常的,但你會發現它某些行為非常奇怪,原因來自於 Erlang 系統的歷史包袱。由於 Erlang 最初是做給電話機交換系統使用的,對於字串的需求與現今的系統不同,所以在 Erlang 中,字串是…整數的串列。每個整數對應到 ASCII code 的文字編碼。而在 Elixir 中,若以單括號來括住字串,這種資料被稱為 charlist,基本上就是個串列。
後來新版的 Erlang/OTP 引進了新的二進位字串語法 <<string>>
,這才是你在 Elixir 裡用雙括號括起字串時拿到的東西。於是在 Elixir 中,你也可以用 <<somenthing>>
這種叫 binary 的方式來操作包含字串的各種二進位值。不過這個較少用,就留待大家自行去玩了。
在 Erlang / Elixir 裡,所有的型別都可以互相比較大小。型別間的大小順序是:
number < atom < reference < function < port < pid < tuple < map < list < bitstring
你不需要記得這個順序,只要記得能夠跨型別比較就可以了。就像 Erlang 的作者 Joe Armstrong 說的:
真正的大小順序並不重要,重要的是把順序定義出來這件事。
明天將介紹函數式編程裡最重要的資料型別們:集合。
Happy hacking! 明天見。