等号的意思是:“尝试拟合表达式的值在右边shape在左边并相应地赋值”。所以左边和右边是不同的,你不能切换它们。在右边,所有变量都必须绑定,因为它是一个表达式。在左边,即使你使用的变量是已经绑定的它们将被重新分配。
首先,在右侧你可以有任何你想要的表达:
{: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 运算符的内容:“pin”运算符的用途是什么?Elixir 变量是否可变?