Elixir 2019-06-21
谈到模式匹配,最开始很容易想到正则上面去,但是在Elixir里面,最基本的等号,以及函数调用都涉及到模式匹配。这到底是怎么回事呢?
以等号为例,在前面简单说过,Elixir里面等号并不代表的是赋值,等号符号是匹配运算符(match operator),
如例子中所示
iex(1)> a=1 1 iex(2)> [x,y,_]=[2017.1,"hello","world"] [2017.1, "hello", "world"] iex(3)> x 2017.1 iex(4)> y "hello"
并不是将右项赋值给左项,而是Elixir试图让等号左边等于等号右边,当等号两边的值以及数据结构完全匹配的时候,才算成功,这个过程叫做模式匹配。
Elixir中最常见到的就是各种函数,下面是一个最简单的函数
iex(1)> swap = fn{a,b}-> {b,a} end #Function<6.50752066/1 in :erl_eval.expr/5> iex(2)> swap.({1,2}) {2, 1}
在调用函数swap的时候,如果是按照原来js或者java的思维,我们可以认为是将1赋值给a,2赋值给b。但Elixir中没有赋值的概念,实际上是对值进行模式进行模式匹配。
下面的例子更好的说明在函数调用时的函数匹配,反复出现的斐波那契数列在elixir的实现
defmodule Factorial do def of(0), do: 1 def of(n), do: n*of(n-1) end
是不是更清晰呀
如果需要在函数调用的参数部分做更多的分支,单靠模式匹配根本不够。这个时候可以找下帮手——哨兵子句。
还是用那个用烂了的例子斐波那契数列,我们希望只对正数处理,当然你可以写成这种
defmodule Factorial do def of(0), do: 1 def of(n), do: n>0&&n*of(n-1)||0 end
在计算部分加入判断的逻辑,还有一种如下
defmodule Factorial do def of(0), do: 1 def of(n) when n>0, do: n*of(n-1) end
这就是哨兵子句,在函数调用时,先执行模式匹配,在模式匹配通过的时候,哨兵子句的条件也满足的状况下,才会执行代码块。
模式匹配很好用,但也不是万能的。