我没有得到Elixir中等号的确切含义。 不清楚的是,它看起来像是赋值和模式匹配操作之间的混合。
iex(1)> x=4
4
iex(2)> y=5
5
iex(3)> 3=y
** (MatchError) no match of right hand side value: 5
iex(3)> y=3
3
iex(4)> y=x
4
据我所知,在Elixir中,等于运算符意味着将=符号的左侧与右侧匹配。前两行对我来说很有意义。 x和y是未绑定的变量,因此它们可以匹配任何内容。他们在匹配时受到约束。因此,我理解第三行。你不能将3与5匹配。
我开始松开脑袋的原因是为什么最后两行的执行没有给出同样的错误。看起来等号仅仅是一个赋值运算符。
我试图接受这种行为作为一个没有充分理解的事实,并试图进一步学习语言。但由于模式匹配是Elixir的核心机制之一,我不断锁定并觉得我应该回到这个原始问题。在我完全理解" ="之后究竟发生了什么之前,我不会再进一步了解。签署和逻辑是什么。
答案 0 :(得分:5)
等号表示:"尝试将右侧形状的表达式拟合并相应地指定值"。所以左右两侧是不同的,你不能切换它们。在右侧,所有变量都必须绑定,因为它是一个表达式。在左侧,即使您使用已经绑定的变量,它们也会被重新分配。
首先,在右边你可以得到你想要的任何表达:
{:error, :enoent} = File.open("foo")
但你不能在左侧有一个表达式:
iex(1)> File.open("foo") = {:error, :enoent}
** (CompileError) iex:1: cannot invoke remote function File.open/1 inside match
如果是
y=3
5=y # y gets evaluated to 3 and then you pattern match 3=5
它失败了。但你可以做到
y=3
y=5 # y gets reassigned.
在左侧,您只能拥有"形状"这可能是任意嵌套的数据结构:
[a, b, %{"a" => {1, c}}] = [1, 2, %{"a" => {1, 2}]
# c is now assigned value of 2
因此模式匹配用于解构数据或断言某些条件,如
case File.open("foo") do
{:ok, contents} -> enjoy_the_file(contents)
{:error, reason} -> print_error(reason)
end
或者如果你想断言数据库中只有一个实体而不是先断言它存在,那么只有一个实体可以模式匹配:
[entity] = Repo.all(query)
如果要断言列表中的第一个值是1,则可以进行模式匹配:
[1 | rest] = [1, 2, 3]
模式匹配时有一些问题。例如:
%{} = %{a: "a"}
会匹配,因为左侧的形状是地图而您不需要任何其他内容,因此任何地图都会匹配。然而,这不匹配:
%{a: "a"} = %{}
因为左边的形状表示"给我一张带有原子:a
键的地图。
如果你想匹配一个变量,你可以这样写:
a = 1
{a, b} = {2, 3}
但这会为a
分配值2.而是需要使用pin运算符:
a = 1
{^a, b} = {2, 3} #match fails
我在这个答案中写了更多关于pin运算符的内容:What is the "pin" operator for, and are Elixir variables mutable?
答案 1 :(得分:3)
我开始松开脑袋的原因是为什么最后两行的执行没有给出同样的错误。看起来等号只是一个赋值运算符。
这是因为左侧的变量名称不与其在Elixir中的值匹配。而是将变量重新分配给右侧的匹配值。
这与Erlang的不同之处在于您的期望:
1> X = 4.
4
2> Y = 5.
5
3> 3 = Y.
** exception error: no match of right hand side value 5
4> Y = 3.
** exception error: no match of right hand side value 3
5> Y = X.
** exception error: no match of right hand side value 4
要在Elixir中获得相同的行为,您需要在左侧使用每个要匹配的变量的“pin”运算符:
iex(1)> x = 4
4
iex(2)> y = 5
5
iex(3)> 3 = y
** (MatchError) no match of right hand side value: 5
iex(3)> ^y = 3
** (MatchError) no match of right hand side value: 3
iex(3)> ^y = x
** (MatchError) no match of right hand side value: 4
答案 2 :(得分:0)
两种情况:
1)<head>
是占位符/变量:
示例:
Left hand side
2)x = 5
y = x (y gets value 5)
x = y (x gets value 5)
是值
示例:
Left hand side