در خیلی از آموزش ها در مورد مواردی مثل
tail
آموزش های زیادی داده شده و همینطور از ویژگی جادویی اون صحبت شده در این قطعه کد ما می خوایم یک الگوریتمی رو بنویسیم که لیست رو شمارش کنه ولی به کمک
tail
/ head
برای مثال
defmodule MyList do
def len([]), do: 0
def len([head|tail]), do: 1 + len(tail)
end
حال کد بالا چطور اجرا می شود ؟
len([11,12,13,14,15])
= 1 + len([12,13,14,15])
= 1 + 1 + len([13,14,15])
= 1 + 1 + 1 + len([14,15])
= 1 + 1 + 1 + 1 + len([15])
= 1 + 1 + 1 + 1 + 1 + len([])
= 1 + 1 + 1 + 1 + 1 + 0
= 5
توابع ناشناس رو فبلا توضیح دادیم حال اگر بخواهیم با یک لیست تلفیق کنیم کمی جالب می شود به صورت مثال
MyList.map [1,2,3,4], fn (n) -> n+1 end
همانطور که می بنید به صورت مثال هر ورودی که قبلا داده بودی بعد از خروجی گرفتن وارد تابع ناشناس ما می شود
اضافه کردن مقداری به یک لیست
iex> [ 1, 2, 3 | [ 4, 5, 6 ]]
[1, 2, 3, 4, 5, 6]
فکر کنید یک سری داده های هواشناسی داریم و می خواهیم در یک لیست در لیست اون درجه مورد نظرمون رو در بیاریم و بگیم که دیگر پرامتر هاش چییه
داده ها به صورت زیر می باشد
defmodule WeatherHistory do
def test_data do
[
[1366225622, 26, 15, 0.125],
[1366225622, 27, 15, 0.45],
[1366225622, 28, 21, 0.25],
[1366229222, 26, 19, 0.081],
[1366229222, 27, 17, 0.468],
[1366229222, 28, 15, 0.60],
[1366232822, 26, 22, 0.095],
[1366232822, 27, 21, 0.05],
[1366232822, 28, 24, 0.03],
[1366236422, 26, 17, 0.025]
]
end
اگر بخواهیم توضیح بدهیم اولین پرامتر هر لیست زمانش دومی مثلا درجه مورد نظر ما و ... می باشد حال ما از دومین ورودی لیست عدد ۲۷ را نیاز داریم
def for_location_27([]), do: []
def for_location_27([ [time, 27, temp, rain ] | tail]) do
[ [time, 27, temp, rain] | for_location_27(tail) ]
end
def for_location_27([ _ | tail]), do: for_location_27(tail)
end
اگر به کد ها توجه کنید متوجه می شوید اگر لیست خالی باشد که خوب چیزی وجود ندارد و اگر دومین جواب ما باشد
یعنی ۲۷ مورد نظر ما دومین پارامتر باشد دیگر اطلاعات آن در یک پارامتری قرار می گیرد تا فراخوانی شود و اگر نبود که آخرین خط لود می شود
به صورت مثال فراخوانی می کنیم
for_location_27(test_data)
[[1366225622, 27, 15, 0.45], [1366229222, 27, 17, 0.468], [1366232822, 27, 21, 0.05]]
مورد خیلی جذاب ما در این استن که همانطور که می دانیم لیست به عدد جواب مورد نظر برسد متوقف می شود ولی فکر کنیم اگر چند داده می داشتیم مثل بالا چه کار می شد کرد؟
خوب نویسنده کد بالا اومده دوباره تابع رو برای
tail
به صورت بازگشتی فراخوانی کرده است. که برای ما بقی داده ها نیز این مورد انجام گردد. حال بر اساس خلاقیت شما می تواند تمامی موارد بالا
به صورت دیگر نیزنوشته شود
ماژول لیست دستورات بسیار کلیدی رو به همراه خودش داره که می تونه به کدهای شما قدرت بسیار زیادی رو بده به صورت مثالی برخی از این مورد به شرح زیر می باشد
#
# Concatenate lists
#
iex> [1,2,3] ++ [4,5,6]
[1, 2, 3, 4, 5, 6]
#
# Flatten
#
iex> List.flatten([[[1], 2], [[[3]]]])
[1, 2, 3]
#
# Folding (like reduce, but can choose direction)
#
iex> List.foldl([1,2,3], "", fn value, acc -> "#{value}(#{acc})" end)
"3(2(1()))"
iex> List.foldr([1,2,3], "", fn value, acc -> "#{value}(#{acc})" end)
"1(2(3()))"
#
# Updating in the middle (not a cheap operation)
#
iex> list = [ 1, 2, 3 ]
[ 1, 2, 3 ]
iex> List.replace_at(list, 2, "buckle my shoe")
[1, 2, "buckle my shoe"]
#
# Accessing tuples within lists
#
iex> kw = [{:name, "Dave"}, {:likes, "Programming"}, {:where, "Dallas", "TX"}]
[{:name, "Dave"}, {:likes, "Programming"}, {:where, "Dallas", "TX"}]
iex> List.keyfind(kw, "Dallas", 1)
{:where, "Dallas", "TX"}
iex> List.keyfind(kw, "TX", 2)
{:where, "Dallas", "TX"}
iex> List.keyfind(kw, "TX", 1)
nil
iex> List.keyfind(kw, "TX", 1, "No city called TX")
"No city called TX"
iex> kw = List.keydelete(kw, "TX", 2)
[name: "Dave", likes: "Programming"]
iex> kw = List.keyreplace(kw, :name, 0, {:first_name, "Dave"})
[first_name: "Dave", likes: "Programming"]