Elixir Enum.map 通过管道传送到 Enum.filter 不起作用
Posted
技术标签:
【中文标题】Elixir Enum.map 通过管道传送到 Enum.filter 不起作用【英文标题】:Elixir Enum.map piped to Enum.filter not working 【发布时间】:2018-05-31 04:08:48 【问题描述】:我正在尝试编写一个工具,该工具将从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】:当代码被编译时,编译器会抛出一个详细的警告,解释这段代码有什么问题:
警告: 插入函数调用时需要括号。例如:
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)
否则,编译器使用错误的运算符优先级。
【讨论】:
以上是关于Elixir Enum.map 通过管道传送到 Enum.filter 不起作用的主要内容,如果未能解决你的问题,请参考以下文章