Elixir-模式匹配与不可变性

模式匹配

赋值并非如你所料

1
2
3
4
iex> a = 1
1
iex> a + 3
4

看下以上代码,很简单吧?
把 1 赋值给 a,然后 a 加上 3 返回 4 。

但是在Elixir里面不是这样,等号更像一种 断言(assertion) ,如果可以找到一种方式让左边等于右边,则执行成功;在Elixir里面可以称之为匹配运算符 match operator,参考如下代码:

1
2
3
4
5
6
iex> a = 1
1
iex> 1 = a
1
iex> 2 = a
** (MatchError) no match of right hand side vlaue: 1

模式匹配 必须值与模式的结构相同,而且模式中项目与值中对应的项目都匹配时才算成功。

1
2
3
4
5
6
7
8
iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 2, b] = list
[1, 2, 3]
iex> a
1
iex> b
3

下面匹配失败:

1
2
3
4
iex> list = [1, 2, 3]
[1, 2, 3]
iex> [a, 1, b] = list
**(MatchError) no match of right hand side vlaue: [1, 2, 3]

匹配过程中,变量一旦绑定某个值,在匹配其余部分的时候就会保持不变;如果想强制让已有的值参与匹配,用 ^(脱字符)前缀。

1
2
3
4
5
6
iex> a = 1
1
iex> a = 2
2
iex> ^a = 1
** (MatchError) no match of right hand side vlaue: 1

不可变性

Elixir的数据一旦创建就不能被改变。

在函数式语言里,我们总是转换数据,我们从不就地修改它。

在大数据编程语言里,大多数复合类型是可变的,你可以修改它们的全部或者部分内容。这种情况当在并行的时候发生,那么受伤的总是你。例如Java中,由于可变性,多线程访问一个变量的时候我们总要考虑到共享变量的状态,然后通过锁等机制去保证数据准确性。

不可变的数据才是已知的

“编程就是形式数据转换”。
比如当更新[1, 2, 3]时,我们不是在原址修改它,而是将它转换成新数据。

复制数据

凭借常识,大家会认为每次修改都要拷贝一份副本这种数据的复制是抵消的;但其实相反,Elixir知道已有数据是不可变的,所以当创建新的结构时,它可以重用这些数据的部分或者全部。
简而言之,不用考虑数据复制在Elixir中的效率问题。

垃圾回收

Elixir 最酷的地方是可以在代码中使用许许多多的进程,而每个进程都有自己的堆,应用程序的数据都由这些进程分摊,跟所有把所有的数据放在一个堆里的情况相比,每个单独的堆是非常小的。
因此Elixir里面垃圾回收速度回更快。
当一个进程在其堆饱和前,终止时,它所有的数据都会被删除,没有必要进行垃圾回收。

看官赏点饭钱可好~