初学erlang,这里对erlang的模式匹配进行记录一下,当然下面是我从各个不同的网站摘取的一些值得注意的地方,主要方便自己以后的查阅。下面总结了几点需要注意的地方:
1:模式匹配为变量赋值提供了基本的机制。被赋值后,变量便被绑定——否则便是未绑定变量。给变量赋值的动作称作“绑定”。变量一旦被绑定便不可更改。这种变量属性被称为一次性绑定或单次赋值。这种属性与传统命令式语言的破坏性赋值[2]相反。这一点区别其他编程语言;
2:如果一个模式与一个项式在结构上同构,且在模式中任一位置出现的原子数据类型也都在项式的相应位置上出现,则称他们它们相互匹配;
3:如果模式中包含未绑定变量,则该变量在匹配过程中将被绑定到项式中相应的元素。如果在模式中相同的变量多次出现,则项式中对应位置的元素也必须相同;
{Element, Element, _} = {1,1,2}.
{1,1,2}
如果是{Element, Element, _} = {1,2,2}. 这样子就会报错
4:模式匹配[A,B,C,D] = [1,2,3]则会失败。虽然它们两个都是列表类型,但是左边的列表有4个元素,而右边一个列表只有3个元素。一个常见的误解是D可以设置为空列表,然后模式匹配应该成功。在这个例子中这是不可能的,因为C和D之间由逗号而不是构造器操作符分隔开。[A,B,C|D]=[1,2,3]的模式匹配就会成功,变量A、B和C分别绑定到整数1、2和3,变量D则绑定到尾部,在这里就是空列表。如果我们尝试[A,B|C]=[1,2,3,4,5,6,7],A和B将分别绑定到1和2,而C则会绑定到一个包含[3,4,5,6,7]的列表;
5:最后一个例子,[H|T]=[]会失败,因为[H|T]意味着这个列表至少要有一个元素,而我们右边其实是一个空列表;
6:变量可以用下划线开始,下划线是一个特殊的标记,它告诉编译器,这些变量是无关紧要的,它们只是作为程序中不需要的变量的占位符。“无关紧要的”变量的功能跟普通变量一样,可以检查、使用和比较它们的值。唯一不同的是,普通变量的值如果从未使用过,编译器将会发出警告,而使用“无关紧要的”变量则不会。使用“无关紧要的”变量是一种很好的编程实践,这告诉阅读代码的人应该忽略掉这个值。为了提高可读性和维护性,程序员经常以“无关紧要的”变量的形式引入值和类型。下划线本身也是个“无关紧要的”变量,但不能访问其内容:因为它的值被忽略了而且从未绑定。
当模式匹配的时候,请注意“无关紧要的”变量的使用,让我们来看下面的具体例子:
{A, _, [B|_], {B}} = {abc, 23, [22, 23], {22}}
由于_变量从不绑定,因此它的值匹配不匹配都是无关的。但是,如果我们这么写:
{A, _int, [B|_int], {B}} = {abc, 23, [22, 23], {22}}
这就彻底改变了程序的语义。该变量_int先绑定到整数23,随后和一个包含整数23的列表相比较。这将导致这个模式匹配失败。
****当然你有可能想问为什么这样不行。这要考虑到erlang的特性,_int = 23,这样_int就被绑定了数据23,而[B|_int] = [22,23],这样B = 22,但是_int = [23],这是_int是列表了,所以不行。
下面给出一个模式匹配的例子:
-module(mySet).
-export([new/0,add_element/2,del_element/2,is_element/2,is_empty/1,union/2,intersection/2]).
new() ->
[].
add_element(X,Set) ->
case is_element(X,Set) of
true ->
Set;
false ->
[X | Set]
end.
is_element(X,[X | _]) ->
true;
is_element(X,[_ | T]) ->
is_element(X,T);
is_element(_,[]) ->
false.
del_element(X,[X | Set]) ->
Set;
del_element(X,[_ | Set]) ->
del_element(X,Set);
del_element(_,[]) ->
[].
is_empty([]) ->
true;
is_empty(_) ->
false.
union([H | T],Set) ->
union(T,add_element(H,Set));
union([],Set) ->
Set.
intersection(S1,S2) ->
intersection(S1,S2,[]).
intersection([],_,S3) ->
S3;
intersection([X|H],S2,S3) ->
case is_element(X,S2) of
true ->
intersection(H,S2,[X|S3]);
false ->
intersection(H,S2,S3)
end.