Elixir 管道贴图正在尝试调用原始函数

Elixir 管道贴图正在尝试调用原始函数,elixir,Elixir,以下代码用于读取文件并为每行创建项记录: defmodule Ship do defrecord Item, product_code: 0, quantity: 0, destination: "" def load_data do File.read!("data") |> String.split |> Enum.map &(String.split &1, ",") |> Enum.map &am

以下代码用于读取文件并为每行创建
记录:

defmodule Ship do
  defrecord Item, product_code: 0, quantity: 0, destination: ""

  def load_data do
    File.read!("data") 
      |> String.split 
      |> Enum.map &(String.split &1, ",")
      |> Enum.map &(list_to_item &1)
  end

defp list_to_item([pc, q, d | []]) do
    {parsed_q, _} = Integer.parse q
    Item.new product_code: pc, quantity: parsed_q, destination: d
  end
end
有一个包含以下内容的
数据
文件:

1,100,London
1,30,Lisbon
3,2,Braga
问题是,当我执行load_data函数时,对Enum.map的最后一次调用似乎是试图递归调用父函数(load_data),并抛出一个
BadArityError

结果如下:

iex(1)> Ship.load_data
** (BadArityError) #Function<0.127338698/1 in Ship.load_data/0> with arity 1 called with 2 arguments ({:cont, []}, #Function<30.103209896/2 in Enum.map/2>)
    (elixir) lib/enum.ex:2000: Enumerable.Function.reduce/3
    (elixir) lib/enum.ex:879: Enum.map/2
            ship.ex:8: Ship.load_data/0
它按预期工作:

iex(2)> Ship.load_data
[Ship.Item[product_code: "1", quantity: 100, destination: "London"],
 Ship.Item[product_code: "1", quantity: 30, destination: "Lisbon"],
 Ship.Item[product_code: "3", quantity: 2, destination: "Braga"]]
那么,你知道第一个版本的错误来自哪里吗?难道它们不应该是等价的吗


顺便说一句,我使用的是Elixir 0.12.4。

您的代码实际上相当于:

File.read!("data") 
|> String.split 
|> Enum.map (&(String.split &1, ",") |> Enum.map &(list_to_item &1))
您需要更多的括号,因为
|>
比无括号函数应用程序具有更高的优先级:

File.read!("data") 
|> String.split 
|> Enum.map(&(String.split &1, ","))
|> Enum.map(&(list_to_item &1))

这是长生不老药设计中的一个不幸缺陷(也是我仍然喜欢Erlang的唯一原因)。

对不起,这不是长生不老药设计中的一个不幸缺陷。一旦您注意到Elixir中的所有运算符的优先级都高于函数调用,您就会意识到具有不同优先级的
|>
实际上会导致更多的混淆。例如,我在测试中看到的断言是
assert foo |>List.flatte==[1,2,3]
或类似
foo=bar |>Enum.baz
的表达式,如果我们降低
>
的优先级,它们的行为将不符合预期。如果我阅读
assert foo |>List.flatte=[1,2,3]
我非常希望它将
assert foo的结果传递给
List.flatten==[1,2,3]
。也许是因为我的F#背景吧。我认为
|>
-作为在线上的第一个令牌被更广泛地使用。
File.read!("data") 
|> String.split 
|> Enum.map(&(String.split &1, ","))
|> Enum.map(&(list_to_item &1))