【问题标题】:Elixir: error when piping to a function the result of inline comprehensionElixir:将内联理解的结果传递给函数时出错
【发布时间】:2017-01-17 01:45:25
【问题描述】:

我注意到 Elixir 的 for 理解在用于将结果通过管道传输到函数时有些令人惊讶。

例如,这些表单可以工作:

foo = fn(list) ->
  for n <- list do
    n + 1
  end
  |> Enum.reverse
end

foo.([1,2,3])
# [4, 3, 2]

foo = fn(list) ->
  for(n <- list, do: (n + 1))
  |> Enum.reverse
end

foo.([1,2,3])
# [4, 3, 2]

但这并没有,因为它考虑了宏的 do 块的第二行部分的 |&gt; Mod.func

foo = fn(list) ->
  for n <- list, do: n + 1
  |> Enum.reverse
end

foo.([1,2,3])
** (Protocol.UndefinedError) protocol Enumerable not implemented for 2
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:116: Enumerable.reduce/3
    (elixir) lib/enum.ex:1636: Enum.reduce/3
    (stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:228: :erl_eval.expr/5
    (elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3

我猜这与宏的扩展方式和返回值有关,但有趣的是这些工作:

bar = fn(list) ->
  if true, do: list
  |> Enum.reverse
end
bar.([1,2,3])
# [3, 2, 1]


bar = fn(list) ->
  if true, do: Enum.map(list, &(&1 + 1))
  |> Enum.reverse
end
bar.([1,2,3])
# [4, 3, 2]

【问题讨论】:

    标签: elixir


    【解决方案1】:

    我认为是因为:

    警告:您正在输入不带括号的函数调用, 这可能是模棱两可的。请包装您正在管道中的功能 在括号中。

    这行得通:

    iex()> foo = fn(list) ->
    ...()> (for n <- list, do: n + 1)
    ...()> |> Enum.reverse
    ...()> end
    #Function<6.52032458/1 in :erl_eval.expr/5>
    iex()> foo.([1,2,3])
    [4, 3, 2]
    

    没有括号你的功能,如:

    foo = fn(list) ->
      for n <- list, do: n + 1 |> Enum.reverse
    end
    

    n + 1 不是list 所以(Protocol.UndefinedError) protocol Enumerable not implemented for 2

    【讨论】:

    • 值得一提的是 OP 的 if true, do: list |&gt; Enum.reverse 有效,因为在这种情况下,优先/执行顺序不会改变任何事情。
    • @mudasobwa 谢谢,好点子。此外,这只是返回 list,无需迭代。
    • 不过,我认为这并不能真正回答我的问题。我知道用括号括起来 for 宏可以解决问题(您所做的与我的一个工作示例非常相似)。我的困惑来自|&gt; forward-pipe 忽略了新行。我认为新行是有意义的,但是对于内联关键字列表形式,新行会被忽略。
    • 我不明白你到底有什么惊喜。 |&gt; 具有最前面的顺序,这就是它首先应用的原因。 n + 1 计算结果为 2,2 |&gt; 失败。为什么你会期待任何其他行为?
    • 好的,感谢您提及运算符的优先顺序。我很惊讶,因为新行被忽略了。我希望\n 分开独立的陈述。显然这不会发生。
    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 2012-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    相关资源
    最近更新 更多