Elixir:通过管道传递给函数的错误是内联理解的结果 [英] Elixir: error when piping to a function the result of inline comprehension

查看:67
本文介绍了Elixir:通过管道传递给函数的错误是内联理解的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用Elixir的 for 理解将结果通过管道传递到函数中时,我发现了一些令人惊讶的事情。



例如,这些形式有效:

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

foo。[[1,2,3])
#[4,3,2]

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

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

但这不是,因为它认为 |> do 宏的第二行部分的Mod.func

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

foo。[[1,2,3])
**(Protocol.UndefinedError)协议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:枚举。 -reduce / 3-lists ^ foldl / 2-0- / 3

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

  bar = fn(list)-> 
如果为true,请执行:列出
|> Enum.reverse
end
bar([1,2,3])
#[3,2,1]


bar = fn (清单)->
如果为true,请执行:Enum.map(list,&(& 1 + 1))
|> Enum.reverse
end
bar。([1,2,3])
#[4,3,2]


解决方案

我认为是因为:


<警告:您正在使用不带括号的函数调用
,这可能是不明确的。请用括号将要传递给函数的函数包装到
中。


这有效:

  iex()> foo = fn(list)-> 
...()> (对于n<-list,执行:n + 1)
...()> |> Enum.reverse
...()> end
#Function< 6.5203​​2458 / 1 in:erl_eval.expr / 5>
iex()> foo。([1,2,3])
[4,3,2]

不带括号的函数如下:

  foo = fn(list)-> 
for n<-list,do:n + 1 |>倒数
结束

n +1 不是列表,因此(Protocol.UndefinedError)协议Enumerable未针对2

I've noticed something surprising with Elixir's for comprehensions when used to pipe the results into a function.

For example, these forms work:

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]

But this doesn't, as it considers the |> Mod.func on the second line part of the do block of the macro:

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

I would guess that is has to do with how macros are expanded and their value returned, but interestingly these work:

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]

解决方案

I think it's because of:

warning: you are piping into a function call without parentheses, which may be ambiguous. Please wrap the function you are piping into in parentheses.

This works:

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]

without parentheses your function like:

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

and n + 1 isn't a list so (Protocol.UndefinedError) protocol Enumerable not implemented for 2

这篇关于Elixir:通过管道传递给函数的错误是内联理解的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆