Enum.each与列表理解之间的区别.

6 elixir

在Elixir中,我们可以使用Enum.each函数逐个打印列表的值.

a = [1, 2, 3]
Enum.each(a, fn(x) -> IO.puts x end)
Run Code Online (Sandbox Code Playgroud)

输出是:

1
2
3
:ok
Run Code Online (Sandbox Code Playgroud)

使用list comprehension执行相同的任务:

a = [1, 2, 3]
for x <- a, do: IO.puts x
Run Code Online (Sandbox Code Playgroud)

产出是:

1
2
3
[:ok, :ok, :ok]
Run Code Online (Sandbox Code Playgroud)

在输出结束时,Enum.each函数返回一个:ok,list comprehension返回三:ok.这两种方法有什么区别?抱歉这个愚蠢的问题.我读了官方的灵药医生.但没有找到答案.

Kev*_*son 6

到目前为止提供的答案,虽然正确无法真正解决您的问题的核心.在这里你的问题的核心是,你不熟悉如何Enum.each,Enum.map,for x <- a等的引擎盖下实现的.

Enum.map 引擎盖下只是一个接受两个输入的递归函数:

  1. 一个列表
  2. 需要应用于该列表中每个元素的函数

此递归函数的返回值是一个新列表.

为了澄清更多:说你有列表[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
Run Code Online (Sandbox Code Playgroud)

所以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
Run Code Online (Sandbox Code Playgroud)

如您所见,此函数将始终返回:okEnum.map始终返回新列表.

所有这些都是基本的东西,所以:

  1. 如果你明白发生了什么事情,那么;
  2. 你明白,从本质上讲Enum.map,for x <- [1,2,3]它基本上是一个相同的递归函数,只有一个不同的接口

|> 那么你的所有问题都应该澄清.

另外,也提供相同的构造Javascript.如果你这样做[1,2,3,4].map或者[1,2,3,4].each在JS中,他们做的完全相同Elixir,所以Javascript如果你仍然有理解差异的问题,你可以在第一次理解这些结构时更清楚.