Elixir的loops,嗯.....
遞迴!是的,我們的老朋友遞迴又出現了.
來看一個簡單的範例,產生自然數的.
defmodule NaturalNums do
def print(1), do: IO.puts(1)
def print(n) do
print(n - 1)
IO.puts(n)
end
end
編譯及執行:
iex(1)> c "natural_nums.ex"
[NaturalNums]
iex(2)> NaturalNums.print(3)
1
2
3
:ok
再來看一個加總list的範例.
defmodule ListHelper do
def sum([]), do: 0
def sum([head | tail]) do
head + sum(tail)
end
end
尾遞迴的版本:
defmodule ListHelper do
def sum(list) do
do_sum(0, list)
end
defp do_sum(current_sum, []) do
current_sum
end
defp do_sum(current_sum, [head | tail]) do
new_sum = head + current_sum
do_sum(new_sum, tail)
end
end
相信大家對遞迴與尾遞迴應該很熟悉了.
這在前面Erlang的部份也有介紹過.直接來看範例.
凡是可以計數的,序列化的,(enumerable);都可以使用
Enum模組裡的函數,搭配Higer-order functions
的方法再加工.
iex(1)> Enum.each(
...(1)> [1,2,3],
...(1)> fn(x) -> IO.puts(x) end
...(1)> )
1
2
3
:ok
iex(2)> Enum.map(
...(2)> [1,2,3],
...(2)> &(&1 * 2)
...(2)> )
[2, 4, 6]
iex(3)> Enum.filter(
...(3)> [1,2,3],
...(3)> fn(x) -> rem(x, 2) == 1 end
...(3)> )
[1, 3]
可以改寫成
iex(4)> Enum.filter(
...(4)> [1,2,3],
...(4)> &(rem(&1,2) == 1)
...(4)> )
[1, 3]
Enum的 Enum.each, Enum.map, Enum.filter 三個函數,
相信大家都很熟悉了.
來介紹一下Enum.reduce/3
在介紹Elixir的Enum.reduce之前,我們先來看另一種程式
語言的片段:
var sum = 0;
[1,2,3].forEach(function(element) {
sum += element;
})
這程式語言有受到Lisp影響.有看出來是哪個程式語言了嗎?
現在回到Elixir,介紹Enum.reduce的格式:
Enum.reduce(
enumerable,
initial_acc,
fn(element, acc) ->
...
end
)
對 list [1,2,3]進行加總,可以這樣寫
iex(5)> Enum.reduce(
...(5)> [1,2,3],
...(5)> 0,
...(5)> fn(element, sum) -> sum + element end
...(5)> )
6
上面的fn 可以改寫成lambda方式.
iex(6)> Enum.reduce([1,2,3], 0, &+/2)
6
結合上面介紹的Enum.reduce及lambda方式,
可以將加總寫成以下形式.
defmodule NumHelper do
def sum_nums(enumberable) do
Enum.reduce(enumberable, 0, &add_num/2)
end
defp add_num(num, sum) when is_number(num), do: sum + num
defp add_num(_, sum), do: sum
end
實際應用:
iex(8)> NumHelper.sum_nums([1,"Hi", :xyz, 2, 3, "World"])
6
這在前面Erlang的部份,也有介紹過.直接看範例.
iex(9)> for x <- [1,2,3] do
...(9)> x * x
...(9)> end
[1, 4, 9]
你沒看錯,有for
Elixir有for,用在 List Comprehension,看上面的範例,就與一般程式語言
的方式差別不大了.
Erlang的List Comprehension格式偏向數學式,Elixir偏向一般方式.
例如在數學中,我們要表達正整數可以用以下方式
在Erlang 中
[ x || x <- ListofIntegers, x > 0]
來看應用範例,假設阿拉蕾,多拉A夢跟哥吉拉要一起聚餐,
但是飯店房門無法讓超過2m的通過,可以使用以下程式,
看誰到室內用餐.
customers = [
%{ name: "arale", height: 1.39},
%{ name: "doraemon", height: 1.293},
%{ name: "godzilla", height: 150}
]
for data = %{ height: howtall} <- customers
howtall < 2
do: IO.inspect data
結果是:
%{height: 1.39, name: "arale"}
%{height: 1.293, name: "doraemon"}
哥吉拉只能在室外用餐了.