在Elixir中,我们可以使用Enum.each函数逐个打印列表的值。
a = [1, 2, 3]
Enum.each(a, fn(x) -> IO.puts x end)
输出是:
1
2
3
:ok
使用list comprehension执行相同的任务:
a = [1, 2, 3]
for x <- a, do: IO.puts x
输出是:
1
2
3
[:ok, :ok, :ok]
在输出结束时,Enum.each函数返回一个:ok,list comprehension返回三:ok。这两种方法有什么区别? 抱歉这个愚蠢的问题。我读了官方的灵药医生。但没有找到答案。
答案 0 :(得分:5)
到目前为止提供的答案,虽然正确无法解决您问题的核心问题。这里你的问题的核心是你不熟悉Enum.each
,Enum.map
,for x <- a
等的实施方式。
Enum.map
只是一个接受两个输入的递归函数:
此递归函数的返回值是一个新列表。
进一步澄清:
假设您已将列表[1, 2, 3, 4]
和函数fn e -> e * 2 end
作为输入,那么您将获得新列表[2, 4, 6, 8]
Enum.map
可以像这样实现:
defmodule MyEnum do
def map(list, fun) do
if Enum.empty?(list) do
[] # Null case reached, stop recursing.
else
[head | tail] = list # obtain the first element in the list, assign that value to `head`. Store the remaining list inside the variable `tail`
projected_value = fun.(head) # This is where your function gets applied
[ projected_value | map(tail, fun)] # Recurse
end
end
end
因此MyEnum.map([1,2,3], fn e -> e * 2 end)
会向您返回列表:[2, 4, 6]
现在假设你在这里使用函数IO.puts/2
,如:
MyEnum.map([1,2,3], fn e -> IO.puts(e) end)
,变量projected_value
最终将是IO.puts/2
的返回值。它将值打印到屏幕上,并返回:ok
原子。
这意味着在这种情况下构建的列表将在每个新递归上累积原子:ok
。
引擎盖下的理解for x <- a
类似于Enum.map,这是一个递归函数,它将提供的函数应用于列表的每个元素,但只是使用不同的语法。
Enum.each
也是一个递归函数,但它只会循环遍历每个元素,而不是关心在过程中积累任何东西。这是你如何实现它:
defmodule MyEnum do
def each(list, fun) do
if Enum.empty?(list) do
:ok # Return `:ok` to communicate the entire list has been traversed
else
[head | tail] = list
fun.(head) # Only apply the function to the element of the list, and do not care about its return value
each(tail, fun) # Continue to traverse the list recursively
end
end
end
如您所见,此函数将始终返回:ok
,Enum.map
将始终返回新列表。
所有这些都是基本的东西,所以:
Enum.map
和for x <- [1,2,3]
基本上是一个相同的递归函数,只有一个不同的接口 |>
然后应该澄清所有问题。
此外,Javascript
中也提供了相同的结构。如果您在JS中执行[1,2,3,4].map
或[1,2,3,4].each
,那么它们与Elixir
完全相同,因此如果您在Javascript
中首先理解这些结构,您可以更清楚地了解这些结构理解差异仍然存在问题。
答案 1 :(得分:3)
Enum.each/2非常合适,如果你想在整个系列中做一些事情而不关心结果。 :ok
总是由于此功能而返回。
List comprehension返回新的集合,这是对原始可能事物(在您的案例列表中)的每个元素的函数调用的计算结果。将其视为Enum.map/2
的替代方案。
在您的情况下,结果为[:ok, :ok, :ok]
,因为:ok
也是每次IO.puts
来电的结果。
答案 2 :(得分:1)
简单地说,Enum.each/2
是迭代,而Enum.map/2
和理解是 mappers ,理解可以在某种程度上一个reducer 。