为什么x = x +1在Elixir中有效?

问题描述 投票:5回答:3

我读过有关Elixir的所有内容都说应该将赋值视为模式匹配。如果是这样,为什么x = x + 1在Elixir中起作用?没有x的值,x = x + 1。

functional-programming elixir
3个回答
6
投票

我读过有关Elixir的所有内容都说应该将赋值视为模式匹配。

在Elixir中,=称为模式匹配运算符,但它与Erlang中的模式匹配运算符的工作方式不同。那是因为在Elixir中,变量不是像Erlang那样的单一赋值。以下是Erlang的工作方式:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> X = 15.
15

2> X = 100.
** exception error: no match of right hand side value 100

3> X.
15

4> 

因此,在Erlang中失败了:

4> X = X + 1.
** exception error: no match of right hand side value 16

对于Erlang的单一赋值,事情非常简单:因为X已经有了一个值,所以行X = X + 1不能尝试为X赋值,因此该行是模式匹配的尝试(15 = 15 + 1),它总是会失败。

另一方面,在Elixir中,变量不是单一赋值:

Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)

iex(1)> x = 15
15

iex(2)> x = 100
100

iex(3)> x
100

iex(4)> 

Elixir中变量不是单一赋值的事实意味着Elixir在您编写时需要做出选择:

x = 10
x = x + 1  #or even x = 15

选择1)第二行应该被解释为x的赋值吗? 选择2)第二行是否应该被解释为模式匹配的尝试(即10 = 11)?

Elixir选择选择1.这意味着实际上与Elixir中所谓的模式匹配运算符执行模式匹配更加困难:您必须将引脚运算符(^)与匹配运算符(=)结合使用:

x = 10
^x = x + 1  

现在,第二行总是会失败。如果要在不使用pin运算符的情况下执行模式匹配,还有一种技巧可以在某些情况下使用:

x = 10
12 = x

在第二行中,您将变量放在右侧。我认为规则可以这样陈述:在模式匹配运算符(=)的右侧,始终评估变量,即用它们的值替换。在左侧,变量总是分配给 - 除非使用了引脚操作符,在这种情况下,固定变量被其当前值替换,然后模式匹配右侧。因此,将Elixir的=运算符称为混合赋值/模式匹配运算符可能更准确。


5
投票

您可以想象x = x + 1被编译器重写为类似x2 = x1 + 1的东西。

这非常接近它的工作原理。它不像我在这里使用的简单索引号,但概念是相同的。 BEAM看到的变量是不可变的,并且在该级别上没有重新绑定。

在Erlang程序中,你会发现像X2 = X1 + 1这样的代码。这两种方法都有缺点。 JoséValim在设计Elixir时做出了有意识的选择,允许重新绑定变量,并撰写了一篇博文,比较了这两种方法以及您面临的不同错误:

http://blog.plataformatec.com.br/2016/01/comparing-elixir-and-erlang-variables/


4
投票

在模式匹配期间,匹配右侧的值将分配给左侧的匹配变量:

iex(1)> {x, y} = {1, 2}
{1, 2}
iex(2)> x
1
iex(3)> y
2

在右侧,使用匹配前的变量值。在左侧,设置变量。

您可以使用^ pin operator强制左侧使用变量的值:

iex(4)> x = 1
1
iex(5)> ^x = x + 1
** (MatchError) no match of right hand side value: 2

这失败了,因为它等同于1 = 1 + 1,这是你期望的失败条件。

© www.soinside.com 2019 - 2024. All rights reserved.