Elixir Enum.map 通过管道传输到 Enum.filter 不起作用

neu*_*mic 0 pipeline enumerable elixir

我正在尝试编写一个工具,该工具将从 中获取文件/文件夹列表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
Run Code Online (Sandbox Code Playgroud)

这不会:

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
Run Code Online (Sandbox Code Playgroud)

它抛出

** (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
Run Code Online (Sandbox Code Playgroud)

这是为什么?这两个实现的工作方式本质上不应该相同吗?

Ale*_*kin 5

当代码被编译时,编译器抛出了一个详细的警告,解释了这段代码的\xe2\x80\x99s错误:

\n\n
\n

警告:管道传递到函数调用时需要括号。例如:

\n\n
foo 1 |> bar 2 |> baz 3\n
Run Code Online (Sandbox Code Playgroud)\n\n

是不明确的,应该写成

\n\n
foo(1) |> bar(2) |> baz(3)\n
Run Code Online (Sandbox Code Playgroud)\n\n

发现不明确的管道:
\n\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0/path/to/file.ex:line

\n
\n\n

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

\n\n
directory_contents\n|> Enum.map(fn(item) -> Path.join(directory_path, item) end)\n|> Enum.filter(&File.dir?/1)\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n