You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析Enumerable协议中map实现里acc与x的枚举值及工作原理

解析Elixir Enumerable协议中map实现的acc与reducer工作机制

这段代码是Elixir官方文档中手动实现map功能的示例,核心依赖Enumerable.reduce遍历集合,下面从枚举过程中x和acc的变化入手拆解逻辑:

核心代码展示

def map(enumerable, fun) do
  reducer = fn x, acc -> {:cont, [fun.(x) | acc]} end
  Enumerable.reduce(enumerable, {:cont, []}, reducer) |> elem(1) |> :lists.reverse()
end

1. Reducer函数定义

reducer是一个匿名函数,负责定义单次枚举的处理规则:

  • 参数x:当前正在枚举的集合元素
  • 参数acc:累加器,用于暂存历次迭代的处理结果
  • 返回值{:cont, [fun.(x) | acc]}:
    • :cont是控制信号,告知Enumerable.reduce继续枚举下一个元素
    • [fun.(x) | acc]是更新后的累加器——把当前元素经过fun处理后插入到现有累加器列表的头部(列表头插操作效率远高于尾插)

2. 枚举过程模拟(以enumerable = [1,2,3],fun = &(&1*2)为例)

初始状态:Enumerable.reduce的启动参数是{:cont, []},即从空累加器开始执行枚举

第一次迭代

  • x = 1(集合第一个元素),acc = [](初始累加器)
  • 执行fun.(1)得到2,新累加器变为[2 | []] = [2]
  • 返回{:cont, [2]},通知reduce继续枚举

第二次迭代

  • x = 2(集合第二个元素),acc = [2](上一轮的累加器)
  • 执行fun.(2)得到4,新累加器变为[4 | [2]] = [4, 2]
  • 返回{:cont, [4, 2]},通知reduce继续枚举

第三次迭代

  • x = 3(集合第三个元素),acc = [4, 2](上一轮的累加器)
  • 执行fun.(3)得到6,新累加器变为[6 | [4, 2]] = [6, 4, 2]
  • 返回{:cont, [6, 4, 2]},通知reduce继续枚举

枚举结束

当集合所有元素处理完成后,Enumerable.reduce返回{:done, [6, 4, 2]}

3. 最终结果处理

  • |> elem(1):从reduce的返回值中提取累加器部分[6, 4, 2]
  • |> :lists.reverse():将列表反转,得到符合预期顺序的[2, 4, 6]——这就是map函数的最终输出

关键概念总结

  • acc(累加器):作为迭代过程中的状态容器,初始值由开发者指定(这里是[]),每次迭代都会被reducer更新,最终存储所有元素的处理结果
  • reducer(规约函数):负责定义单次迭代的业务逻辑(元素转换、累加器更新),同时返回控制信号,决定枚举的继续/停止/挂起

内容的提问来源于stack exchange,提问作者zdean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 15:02:43