List (串列)
在elixir中,List串列是資料結構中的single-linked-list的實作,他長得像這樣:[1, "haha", :test, 34, 3]
雖然跟PHP還有JS的Array很像,但他的本質是連結串列,所以他裡面的內容是分散的記憶體,並藉由指標的方式連結起來,因此假如你現在想抓到這個串列的第3項,你必須先從第0項,找到第1項,第2項,才能找到第3項,得到他的內容是34。如果你想找到這個陣列的第n項,就必須花費O(n)的複雜度。
因此List的功能也是比較明確的,他適合用來遍歷,對於依序處理或是依序讀取List中的資料,Elixir提共了相對應的函式模組,並且可以得到好的效能。
iex(1)> [1, 2, 6, 3, 2] -- [1, 3, 2]
[6, 2]
iex(1)> [1, 2, 6, 3, 2] ++ [1, 3, 2]
[1, 2, 6, 3, 2, 1, 3, 2]
且由於串列的性質,下列第一種情況會比第二種來得快。
iex(1)> [1] ++ [1, 3, 2, 4, 7, 8]
[1, 1, 3, 2, 4, 7, 8]
iex(2)> [1, 3, 2, 4, 7, 8] ++ [1]
[1, 3, 2, 4, 7, 8, 1]
iex(1)> 6 in [1, 2, 6, 3, 2]
true
iex(1)> length([1, 2, 6, 3, 2])
5
Keyword List (關鍵字串列)
有著簡單的鍵值的串列是常有可能被需要的,所以elixir提供一種資料型態(其實算是種語法糖):
[name: "jack", age: 18, cell: "0911111111"]
elixir在編譯時會將上述語法轉化成:
[{:name, "jack"}, {:age, 18}, {:cell, "0911111111"}]
也就是List包裝Tuples。
然後當然,因為Keyword List的本質上就是List而已,所以下面的語法也是被允許的。[name: "jack", age: 18, cell: "0911111111", "hahah", 123]
會被編譯成[{:name, "jack"}, {:age, 18}, {:cell, "0911111111"}, "hahah", 123]
賦值
在elixir中,可以使用下面這種類似語法,達到類似JS中的解構賦值的效果,這都是得益於elixir的pattern matching,在之後的章節會提到。
iex(1)> [a, b, c] = [1, 2, 3]
[1, 2, 3]
iex(2)> a
1
iex(3)> b
2
iex(4)> c
3
iex(1)> [head | tail] = [1, 2, 3]
[1, 2, 3]
iex(2)> head
1
iex(3)> tail
[2, 3]
事實上,List的表示法也算是一種語法糖,其實他真正的樣子是這樣的:
[1, 2, 3] 其實長這樣 => [1 | [2 | [3 | []]]]
而當你在iex輸入時也可以看到相同的結果:
iex(1)> [1 | [2 | [3 | []]]]
[1, 2, 3]
所以看到這邊,就可以大概了解[head | tail] = [1, 2, 3]
可以做到解構賦值的原因了吧。
相關函式
如一些基本的新增刪除,都可以在文檔中找到,因此這邊就不寫了,只找幾個實務上最可能會有機會用到的列出來。
List官方文檔([https://hexdocs.pm/elixir/List.html])
List.flatten([1, [[2], 3]])
[1, 2, 3]
Enum.map([1, 2, 3], fn x -> x * 2 end)
[2, 4, 6]
Enum.each(["some", "example"], fn x -> IO.puts(x) end)
"some"
"example"
#=> :ok
Enum.filter([1, 2, 3], fn x -> rem(x, 2) == 0 end)
[2]
Enum.reduce([1, 2, 3], 0, fn x, acc -> x + acc end)
6