在Elixir中编写代码时,使用Enum库而非Erlang Lists是否有原因?
好问题!这确实是很多刚接触Elixir的开发者会疑惑的点——毕竟Erlang的lists模块功能相当齐全,而且Elixir官方也明确强调了和Erlang库的互操作性,甚至不鼓励无意义的封装。不过日常开发中优先选择Enum,原因远不止条件函数的格式差异,主要有以下几点:
贴合Elixir的编码习惯与管道操作
Erlang的lists模块函数参数顺序是「函数在前,列表在后」,比如lists:map(fn x -> x*2 end, my_list);而Enum的参数顺序是「列表在前,操作在后」,刚好适配Elixir的管道运算符|>:# 用Enum的管道写法,流畅直观 my_list |> Enum.map(fn x -> x*2 end) |> Enum.filter(&(&1 > 5)) # 用Erlang lists的话,管道就变得很别扭 my_list |> (&lists:map(fn x -> x*2 end, &1)).() |> (&lists:filter(fn x -> x >5 end, &1)).()另外,
Enum的函数命名采用Elixir统一的蛇形命名(比如take_while),而Erlang是驼峰式的takewhile,风格上更契合Elixir生态。统一接口支持多种数据类型
Enum模块基于Elixir的Enumerable协议构建,不仅能处理列表,还支持Map、Range、Stream等所有实现了该协议的数据结构。比如:# 用Enum处理Range Enum.map(1..10, &(&1 * 3)) # 用Enum处理Map Enum.reduce(%{a: 1, b: 2}, 0, fn {_k, v}, acc -> acc + v end)而Erlang的
lists模块只针对列表,换了其他数据类型就得切换到对应的Erlang模块(比如maps模块),学习和维护成本更高,代码风格也难以统一。提供更多便捷的高阶函数
Enum内置了不少Erlanglists模块没有的实用函数,比如Enum.chunk_every/2(按指定长度拆分列表)、Enum.intersperse/2(在元素间插入分隔符)、Enum.frequencies/1(统计元素出现频率)等,这些都是日常开发中高频使用的功能,不用自己手动实现或者依赖第三方库。更友好的错误提示与版本兼容性
Enum是Elixir官方维护的模块,会和Elixir版本同步更新,错误提示也更符合Elixir开发者的阅读习惯;而Erlang的lists模块虽然稳定,但错误信息更偏向底层Erlang风格,对于不熟悉Erlang的Elixir开发者来说不够友好。
当然,这并不是说完全不能用Erlang的lists模块——如果遇到Enum没有覆盖的功能,或者需要极致性能优化的场景,直接调用lists模块完全没问题,毕竟Elixir和Erlang的互操作性本来就很好。只是大多数日常开发场景下,Enum的设计更贴合Elixir的生态,能让代码更简洁、易读、易维护。
内容的提问来源于stack exchange,提问作者Roman Rabinovich

