使用管道运算符时获取第一个参数

时间:2016-03-21 08:32:30

标签: elixir

管道操作员是非常好的事情。 例如,我希望将枚举用于Enum.reduce或其他东西:

foo |> bar(...) |> Enum.reduce([], fn x, acc -> acc ++ [Enum.at(<enumerable>, x)] end)

然后我被迫写道:

enumerable = foo |> bar(...)
Enum.reduce(enumerable, [], fn x, acc -> acc ++ [Enum.at(enumerable, x)] end)

在匿名函数中使用管道运算符和&1时,第一个参数可能存在语法糖吗?

1 个答案:

答案 0 :(得分:3)

简单地将整个Enum.reduce移动到它自己的函数是一个好主意,该函数接受一个参数并命名它,这样每个人都可以理解它在做什么。 rearrange不是最具描述性的名称,但我不确定您的应用中如何使用此过程。

def rearrange(enumerable) do
  Enum.reduce(enumerable, [], fn x, acc -> acc ++ [Enum.at(enumerable, x)] end)
end

foo |> bar(...) |> rearrange

另一种解决方案是使用您在问题中提到的匿名函数。情况更糟,但我提到它是完整的。

&(Enum.reduce(&1, [], fn x, acc -> acc ++ [Enum.at(&1, x)] end))

这看起来真的很复杂。您在匿名函数中有匿名函数,但它显示您可以在函数中多次使用&1

最后,acc ++ [thing]非常糟糕,因为它每次都会从头开始重新创建内存中的列表。它开着)。 Enum.at也是线性的,Enum.reduce也是线性的,所以这个函数是O(n ^ 3)。

您可以改为fn x, acc -> [Enum.at(enumerable, x) | acc] end并在结尾处反转结果。

def rearrange(enumerable) do
  enumerable
  |> Enum.reduce([], fn x, acc -> [Enum.at(enumerable, x) | acc] end)
  |> Enum.reverse
end

[thing | acc]是O(1)。这将使整个过程O(n ^ 2),这是它正在做的事情的合理时间。