以下代码应该读取文件并为每行创建Item
记录:
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
有data
个文件,其中包含以下内容:
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
有趣的是,如果我将load_data
函数更改为:
def load_data do
list = File.read!("data")
|> String.split
|> Enum.map &(String.split &1, ",")
Enum.map list, &(list_to_item &1)
end
按预期工作:
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"]]
那么,关于错误在哪里的任何想法来自第一个版本? Aren他们应该是同等的吗?
顺便说一下,我使用的是Elixir 0.12.4。
答案 0 :(得分:5)
您的代码实际上与此相同:
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))
这是Elixir设计中的一个不幸的缺陷(也是我仍然喜欢Erlang的唯一原因)。