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

时间:2019-02-23 20:36:33

标签: functional-programming elixir

关于Elixir的所有内容,我都认为分配应该被认为是模式匹配。如果是这样,那么为什么x = x + 1在Elixir中起作用?没有x = x + 1的x值。

3 个答案:

答案 0 :(得分: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赋一个新值,因此该行是对模式进行匹配的尝试({{ 1}}),它将始终失败。

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

15 = 15 + 1

在Elixir中变量不是单一赋值这一事实意味着在编写时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)> 

选择1)第二行是否应解释为对x = 10 x = x + 1 #or even x = 15 的赋值?
选择2)第二行是否应该解释为尝试模式匹配(即x)?

Elixir具有选择1。这意味着使用Elixir中的所谓模式匹配运算符实际执行模式匹配会更加困难:您必须将pin运算符(10 = 11)与match运算符结合使用(^

=

现在,第二行将始终失败。如果您想在不使用pin运算符的情况下执行模式匹配,还有一种技巧在某些情况下会起作用:

x = 10
^x = x + 1  

在第二行中,将变量放在右侧。我认为规则可以这样表示:在模式匹配运算符(x = 10 12 = x )的右侧,总是对变量求值,即用其值替换。始终在左侧分配变量-除非使用pin运算符,否则在这种情况下,固定变量将替换为其当前值,然后在右侧进行模式匹配。结果,将Elixir的=运算符称为混合分配/模式匹配运算符可能更准确。

答案 1 :(得分: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/

答案 2 :(得分: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,这是您期望的失败条件。