2016-09-24 44 views
0

我无法弄清楚它是如何工作的。以下是来自Elixir文档的示例代码,以及我如何工作的思考过程。请让我知道是否有什么问题。Kernel.get_in如何使用函数作为关键字?

# Code example from Elixir docs 
users = [%{name: "john", age: 27}, %{name: "meg", age: 23}] 
all = fn(:get, data, next) do 
    Enum.map(data, next) 
end 
get_in(users, [all, :age]) 
#=> [27, 23] 
  1. users匹配到包含两个地图列表。
  2. all与以:get, data, next作为参数并执行Enum.map(data, next)的函数相匹配。
  3. Kernal.get_in(users, [all, :age])被调用。
  4. 由于其中一个密钥all是一个函数,因此它的调用为all(:get, users, next)
  5. Enum.map遍历users的每个元素并在其上调用next,返回一个列表。
  6. 列表中每个用户的密钥:age作为列表返回。

这是我的问题,在此基础上分析:

  1. 这是什么功能next?它从来没有定义也没有提供,但怎么没有错误报告?
  2. 总结当get_in被函数调用(在本例中为all)作为关键字时,它是否正确地返回该函数的结果中的键的值(在本例中为:age)?
  3. 如果我在2中的猜测是正确的,那么当该函数的结果不是字典类型并且没有键值对时会发生什么?它会引起错误吗?

回答

1

有两个完美的来源来检索信息。第一个是Elixir Docs,该状态为Kernel#get_in/2

从嵌套结构获取值。

[...]

如果密钥是一个函数,该函数将被调用传递三个参数,操作(:get),要被访问的数据,以及下一个被调用的功能。

最终的来源将是Elixir源代码,在那里我们可以看到Kernel#get_in/2 in our particular case的确切实现。

也就是说,next在这里扮演acc的角色,将get_in传递给尾递归,直到列表的尾部为空。

问题2在文档中得到了完美的回答。

问题3的答案是:another Kernel#get_in/2将在上一步中匹配,递归将开始揭晓。

+0

谢谢。我不敢相信看到源代码的想法不在我脑海。现在一切都说得通了。我认为让我感到沮丧的是,没有明确提及在文档中对'get_in'的递归调用。对于那些更熟悉FP的人来说,这很明显,但是直到我看到源代码之前,它并没有清晰地呈现出来。 – Harfangk

+1

欢迎。 Elixir源代码本身非常干净,在大多数情况下,它使得相对容易理解引擎盖下发生了什么。仅供参考:要直接从文档访问源代码,可以简单地按下相应功能描述右上角的''链接。 – mudasobwa

相关问题