在“Programming Elixir 1.6”中,有这个例子:
authors = [
%{name: "José", language: "Elixir"},
%{name: "Matz", language: "Ruby"},
%{name: "Larry", language: "Perl"}
]
languages_with_an_r = fn (:get, collection, next_fn) ->
for row <- collection do
if String.contains?(row.language, "r") do
next_fn.(row)
end
end
end
IO.inspect get_in(authors, [languages_with_an_r, :name])
#=> ["José", nil, "Larry"]
我对这个例子有一些疑问:
-
传递给
get_in()
的函数由Elixir调用,而Elixir传递给函数的第一个参数是atom:get
. 这有用吗? -
Elixir传递给函数的第三个参数是一个绑定到
next_fn
的函数 . 文档中的哪个位置表示函数需要多少个参数?这个功能有什么作用?我们该如何使用next_fn
?在我看来,for
构造已经遍历列表中的每个 Map ,那么next_fn
甚至意味着什么呢?next_fn
曾经以某种方式标记一行以供进一步考虑吗? -
结果列表中的nil来自哪里?
而且,我在任何编程书中都看到了 - 因为没有充分讨论这个例子,而且 get_in()
的文档很糟糕 . 这意味着至少有三个人不理解 get_in()
:我,戴夫托马斯,以及编写文档的人 - 因为如果你能够自己理解它 .
编辑:我在source code中发现了这个:
def get_in(data, [h | t]) when is_function(h),
do: h.(:get, data, &get_in(&1, t))
&1
指的是什么? data
?为什么不只使用 data
呢?
1 回答
好吧,我一直在玩iex:
看起来语法
&max(&1, 3)
返回匿名函数:当周围范围中的x = 3时,语法
&max(&1, x)
也将返回该函数:和
&1
将成为调用匿名函数的任何单个arg .在这个例子中:
在这里调用
get_in()
:匹配源代码中的以下函数定义:
这会创建以下绑定:
然后Elixir执行函数体并调用:
这相当于:
这创造了绑定:
因此,在作者的例子中,该行:
相当于调用:
这导致
get_in()
使用这些参数执行:并且对
get_in()
的调用返回row
中与:name
键对应的值 . 我认为如果重命名languages_with_an_r()
定义中的参数变量,作者的例子会更清楚:如果
row.language
包含"r",该代码将仅搜索row
中的:name
键 .最后,以下代码段显示
nil
来自哪里:就像在Ruby中一样,似乎Elixir中的
do block
返回已计算的最后一个表达式的值 . 并且,当do block
不评估表达式时,do block
默认返回nil
. 因此,如果row.language
不包含"r",则跳过if语句,do block
不计算任何表达式,因此默认情况下do block
返回nil .