传递给Enum.filter的Elixir Enum.map无效

时间:2017-12-17 17:53:47

标签: elixir pipeline enumerable

我正在尝试编写一个工具,它将从File.ls获取文件/文件夹列表,添加完整路径,并根据它们是否为目录进行过滤。

这有效:

directory_contents = File.ls!(directory_path)

contents_with_full_paths = Enum.map directory_contents, fn(item) -> Path.join(directory_path, item) end
only_dirs = Enum.filter contents_with_full_paths, fn(item) -> File.dir?(item) end

这不是:

directory_contents = File.ls!(directory_path)

directory_contents
|> Enum.map fn(item) -> Path.join(directory_path, item) end
|> Enum.filter fn(item) -> File.dir?(item) end

它抛出

** (Protocol.UndefinedError) protocol Enumerable not implemented for #Function<1.10194857/1 in RepoFinder.subdirectories_in/1>, only anonymous functions of arity 2 are enumerable. This protocol is implemented for: Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Range, Stream
    (elixir) lib/enum.ex:3213: Enumerable.Function.reduce/3
    (elixir) lib/enum.ex:1847: Enum.filter/2

为什么?这两种实现不应该以基本相同的方式工作吗?

1 个答案:

答案 0 :(得分:4)

编译代码时,编译器会发出详细警告,解释此代码的错误:

  管道进入函数调用时需要

警告:括号。例如:

foo 1 |> bar 2 |> baz 3
     

含糊不清,应写成

foo(1) |> bar(2) |> baz(3)
     

模糊管道发现于:
  /path/to/file.ex:line

也就是说,对于管道运算符,必​​须在函数调用的参数周围使用括号:

directory_contents
|> Enum.map(fn(item) -> Path.join(directory_path, item) end)
|> Enum.filter(&File.dir?/1)

否则,编译器使用错误的运算符优先级。