万灵药复杂模式匹配顺序

时间:2019-03-07 10:29:42

标签: pattern-matching elixir

我正在阅读出色的Joy of Elixir,并试图将模式匹配示例中的操作顺序包裹住。

我有清单

crew = [  
    %{name: "mal", age: 40},
    %{name: "zoey", age: 36},
]

现在,我可以使用模式匹配来获取列表的第一个元素,并将名称分配给其他变量,例如

[first = %{name: first_name} | others] = crew

我了解到crew中的第一个元素已分配给first,而name中的first被分配给了first_name

iex> first
%{age: 40, name: "mal"}
iex> first_name
"mal"

根据示例,我还可以从右到左将名称分配给另一个变量:

%{name: first_name2} = first

但是当我从左到右尝试时,同样失败:

iex> first = %{name: first_name3}
** (CompileError) iex:33: undefined function first_name3/0
    (stdlib) lists.erl:1354: :lists.mapfoldl/3
    (stdlib) lists.erl:1355: :lists.mapfoldl/3

我的问题是:为什么列表匹配内的从左到右分配可以,但是列表匹配外的失败?

2 个答案:

答案 0 :(得分:2)

首先评估=(匹配运算符)的右侧。在表达式中

 first = %{name: first_name3}

它试图获取first_name3的值,但范围中没有first_name3

对于表达式

[first = %{name: first_name} | others] = crew

您可以将其视为

[first = %{name: first_name} = %{age: 40, name: "mal"} | others] = crew

others = tl(crew)
head = hd(crew)
first = %{name: first_name} = head

这是另一个例子:

x = "foo"将变量x绑定到字符串"foo"(因为x首先是未绑定的)。现在x已绑定   到"foo""foo" = x也是有效的表达式,因为"foo"x匹配。

答案 1 :(得分:1)

这是因为e剂评估序列的方式。当您启动IEX时,您的环境将是空的。当您输入first =%{name:first_name3}时,将从评估右侧开始。在实际的地图内部,您尝试将键“名称”与变量first_name3关联。如果您的环境中不存在first_name3,则表达式将无法求值,并且将出现未定义的函数错误。

这应该有效:

first_name3 = "John"
first = %{name: first_name3}