【问题标题】:How does Kernel.get_in work with function as a key?Kernel.get_in 如何以函数为键工作?
【发布时间】:2016-09-25 13:54:17
【问题描述】:

我无法弄清楚这是如何工作的。以下是 Elixir 文档中的示例代码,以及我对它们如何工作的思考过程。如果有问题请告诉我。

# 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. 中的猜测是正确的,那么当该函数的结果不是字典类型并且没有键值对时会发生什么?它会引发错误吗?

【问题讨论】:

    标签: elixir


    【解决方案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 将在上一步匹配,递归将开始揭晓。

    【讨论】:

    • 谢谢。我不敢相信我没有想到查看源代码的想法。现在一切都说得通了。我认为让我感到震惊的是文档中没有明确提及递归调用get_in。可能对那些更熟悉 FP 的人来说很清楚,但是直到我查看源代码后我才明白。
    • 欢迎。 Elixir 源代码本身非常干净,这使得在大多数情况下可以相对容易地理解幕后发生的事情。仅供参考:要直接从文档中访问源代码,可以简单地按相应功能描述右上角的</> 链接。
    • 源代码链接已经失效了。这是正确的链接:github.com/elixir-lang/elixir/blob/master/lib/elixir/lib/…
    猜你喜欢
    • 2013-03-12
    • 1970-01-01
    • 2010-09-13
    • 2012-01-17
    • 1970-01-01
    • 2017-02-25
    • 2018-08-05
    相关资源
    最近更新 更多