Elixir中等号的确切含义是什么?

Mel*_*rte 3 functional-programming equals elixir iex

我不明白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
Run Code Online (Sandbox Code Playgroud)

我了解在Elixir中,等于运算符的意思是将=符号的左侧与右侧匹配。前两行对我来说很有意义。x和y是未绑定的变量,因此它们可以匹配任何内容。它们在匹配时受到约束。因此,我了解第三行。您不能将3与5相匹配。

我开始放松的地方是为什么在没有给出相同错误的情况下执行最后两行。看起来等号又回到了仅作为赋值运算符的地步。

在没有充分理解的情况下,我尝试将这种行为视为事实,并尝试进一步学习该语言。但是由于模式匹配是Elixir的核心机制之一,因此我不断锁定并感到应该回到最初的问题。在我完全理解“ =”符号的确切含义以及逻辑之后,我将不做任何进一步的介绍。

tko*_*wal 5

等号表示:“尝试将右边的表达式适合左边的形状,并相应地分配值”。因此左侧和右侧不同,您无法切换它们。在右侧,所有变量都必须绑定,因为它是一个表达式。在左侧,即使您使用已绑定的变量,它们也会被重新分配。

因此,第一件事是,在右侧,您可以具有所需的任何表达式:

{:error, :enoent} = File.open("foo")
Run Code Online (Sandbox Code Playgroud)

但您不能在左侧使用表达式:

iex(1)> File.open("foo") = {:error, :enoent}
** (CompileError) iex:1: cannot invoke remote function File.open/1 inside match
Run Code Online (Sandbox Code Playgroud)

的情况下

y=3
5=y # y gets evaluated to 3 and then you pattern match 3=5
Run Code Online (Sandbox Code Playgroud)

它失败了。但是你可以做

y=3
y=5 # y gets reassigned.
Run Code Online (Sandbox Code Playgroud)

在左侧,您只能使用“形状”,它可以是任意嵌套的数据结构:

[a, b, %{"a" => {1, c}}] = [1, 2, %{"a" => {1, 2}]
# c is now assigned value of 2
Run Code Online (Sandbox Code Playgroud)

因此,模式匹配用于分解数据或声明某些条件,例如

case File.open("foo") do
  {:ok, contents} -> enjoy_the_file(contents)
  {:error, reason} -> print_error(reason)
end
Run Code Online (Sandbox Code Playgroud)

或者,如果您想断言数据库中只有一个实体,而不是先断言它存在,然后才可以模式匹配:

[entity] = Repo.all(query)
Run Code Online (Sandbox Code Playgroud)

如果要断言列表中的第一个值为1,则可以模式匹配:

[1 | rest] = [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

模式匹配时有些陷阱。例如:

%{} = %{a: "a"}
Run Code Online (Sandbox Code Playgroud)

会匹配,因为左侧的形状是地图,并且您不需要任何其他内容,因此任何地图都将匹配。但是,这不匹配:

%{a: "a"} = %{}
Run Code Online (Sandbox Code Playgroud)

因为左边的形状说“给我一张带有原子键的地图:a

如果您想匹配一个变量,则可以编写如下代码:

a = 1
{a, b} = {2, 3}
Run Code Online (Sandbox Code Playgroud)

但这将分配a值2。相反,您需要使用pin运算符:

a = 1
{^a, b} = {2, 3} #match fails
Run Code Online (Sandbox Code Playgroud)

我在此答案中写了更多有关pin运算符的内容:“ pin”运算符的作用是什么,Elixir变量是否可变?