編程語(yǔ)言都有類(lèi)似集合的容器類(lèi)型怕膛。最典型的莫過(guò)于數(shù)組和哈希結(jié)構(gòu)庶溶。
通常數(shù)組是一些列有序元素的集合。有的語(yǔ)言的數(shù)組需要初始化大小垒棋,有的則是動(dòng)態(tài)變化卒煞。那些動(dòng)態(tài)變化的數(shù)組,在高級(jí)語(yǔ)言通常是列表叼架。當(dāng)然也有一些序列集合一旦創(chuàng)建了畔裕,就不能改變,這類(lèi)序列通常稱之為元組(tuple)乖订。
元組
Elixir中的元組是一組有序的數(shù)據(jù)集合扮饶。元組的項(xiàng)目元素可以是任意的Elixir數(shù)據(jù)類(lèi)型,元組還可以嵌套乍构。
元組使用花括號(hào)定義甜无,這個(gè)估計(jì)是Elixir特有,大多數(shù)語(yǔ)言如Python,Swift的元組都使用小括號(hào)岂丘。而使用花括號(hào)定義字典(python)或者對(duì)象(javascript)這樣的哈希結(jié)構(gòu)陵究。
實(shí)際上,Elixir的元組使用也類(lèi)似這樣的字典元潘。怎么說(shuō)呢畔乙,先看幾個(gè)元組的例子了:
iex(1)> {1, 2}
{1, 2}
iex(2)> {1, "2"}
{1, "2"}
iex(3)> {:ok, 42, "next", 'elixr'}
{:ok, 42, "next", 'elixr'}
iex(4)> {:error, :enoent}
{:error, :enoent}
可以看到,Elixir的元組很靈活翩概,可是,通常定義的元組都是2~4個(gè)元素返咱。這樣的定義钥庇,恰好和字典很像。例如這個(gè){:ok, "message"}
第一個(gè)元素是一個(gè)原子,第二個(gè)元素是一個(gè)字符串。之所以這樣定義集峦,是因?yàn)榫幊痰臅r(shí)候剿另,函數(shù)返回的可能不僅僅是一個(gè)值,而是好幾個(gè)值蔚龙,那么就可以把返回的好幾個(gè)值放入元組之中。返回的值又可以使用元組來(lái)做模式匹配。這樣一個(gè)單元的小對(duì)嗦枢,后面還可以用來(lái)組成關(guān)鍵字列表。
元組與模式匹配
我們知道屯断,凡是數(shù)據(jù)結(jié)構(gòu)一致文虏,就可以使用模式匹配。
iex(1)> {status, count, action} = {:ok, 42, "next"}
{:ok, 42, "next"}
iex(2)> status
:ok
iex(3)> count
42
iex(4)> action
"next"
正如上面提到殖演,可以把函數(shù)返回的多個(gè)值放入元組內(nèi)氧秘。通過(guò)元組的模式匹配獲得返回的值。例如文件的API操作:
iex(1)> {status, file} = File.open("hello.exs")
{:ok, #PID<0.60.0>}
iex(2)> {status, file} = File.open("nofile")
{:error, :enoent}
File模塊的open方法趴久,接受一個(gè)文件路徑作為參賽丸相,返回一個(gè)元組,元組的第一個(gè)元素為打開(kāi)文件的狀態(tài)彼棍。:ok
表示打開(kāi)成功灭忠,:error
則打開(kāi)失敗。第二個(gè)元素對(duì)于打開(kāi)成功的文件滥酥,返回一個(gè)文件資源的句柄更舞。
通過(guò)元組的模式匹配,很容易的就解包函數(shù)的返回值坎吻。
元組的基本操作
元組都有下標(biāo)索引缆蝉,索引從零開(kāi)始。可以借助函數(shù)elem通過(guò)索引訪問(wèn)元素刊头。
iex(5)> t
{:ok, 1, "hello", {1, 2}}
iex(6)> elem t, 1
1
iex(7)> elem t, 0
:ok
在Elixir中黍瞧,函數(shù)調(diào)用的小括號(hào)是可以省略的。elem t, 1
等價(jià)于 elem(t, 1)
原杂。
可以使用tuple_size 獲取元組的元素個(gè)數(shù)
iex(8)> tuple_size t
4
可以使用 put_elem “改變”元組元素的值印颤。
iex(9)> t
{:ok, 1, "hello", {1, 2}}
iex(10)> elem t, 2
"hello"
iex(11)> pelem t, 2
put_elem/3 put_in/2 put_in/3 pwd/0
iex(11)> put_elem t, 2, "hello world"
{:ok, 1, "hello world", {1, 2}}
iex(12)> t
{:ok, 1, "hello", {1, 2}}
注意這里的"改變"的含義。元組與其他Elixir數(shù)據(jù)結(jié)構(gòu)一樣穿肄,都是不可變的年局。這也是函數(shù)式語(yǔ)言的一大特性。put_elem 并沒(méi)有改變?cè)氐脑Mt咸产,而是返回了一個(gè)新的元組矢否,新的元組的第三個(gè)元素與舊的不一樣。
至于為什么這樣的更新而又不改變脑溢,如何理解Elixir中的不可變性呢僵朗?下一節(jié)我們?cè)賮?lái)探討。