首页 > Erlang快速入门 > 3.10 Erlang快速入门之变量的匹配、限制和作用域
2013
11-01

3.10 Erlang快速入门之变量的匹配、限制和作用域

变量的匹配、限制和作用域
查找一个温度列表中的最高或最底气温是很有用的,在扩展这个程序之前,我们来看一个关于如何在在列表中查看最大值的模块:

-module(tut6).
-export([list_max/1]).

list_max([Head | Rest]) ->
	list_max(Rest, Head).

list_max([], Res) ->
	Res;
list_max([Head | Rest], Result_so_far) when Head >Result_so_far ->
	list_max(Rest, Head);
list_max([Head | Rest], Result_so_far) ->
	list_max(Rest, Result_so_far).

下载代码
编译并运行:

28> c(tut6).
tut6.erl:11: Warning: variable 'Head' is unused
{ok,tut6}
29> tut6:list_max([1,2,3,4,57,1,2]).
57
30> 

首先,注意到这里有两个同名的函数list_max。但是每个函数都拥有不同的参数个数,在Erlang中被当成两个完全不同的函数。我们用name/arity来区别这些函数,name即为函数名,arity为函数参数个数,在这里用list_max/1和list_max/2来表示。

上面的例子接受一个我们构造的列表,我们使用Result_so_far“搬移”一个列表中的值。list_max/1简单的假设列表中最大值是列表的头部元素,并给调用list_max/2来处理剩下的元素来与头部元素进行对比,在上面代码就将是list_max([2,3,4,5,7,4,3,2,1],1)。如果我们尝试使用list_max/1来处理一个空列表,我们将得到一个错误提示。注意这个Erlang体系不能够捕获这种类型的函数错误,但是会有其他的办法来处理,稍后会有详细的讨论。

在list_max/2中我们继续“走完”剩余的列表,当Head>Result_so_far条件满足的时候使用Result_so_far替代原先的Head的值。->前面的when是一个关键词,告诉我们如果条件为真则执行函数的这一部分,我们将这种测试过程称为guard(限制。如果一个条件限制不为真(也就是说限制失败),我们尝试运行函数的另一部分。在这个例子中如果Head不是大于Result_so_far,也就是Head等于或者小于Resutl_so_far,所以我们就不需要在函数的另一部分再加入一个限制来判断执行条件了。

另外,在这里出现了一个Warning,这是RB16情况下出现的,也许你的版本不会出现这个警告,现在我们跳过这个。

一些有用的限制操作符(通常意义上的逻辑运算符):”<"小于,">“大于,”==”等于,”>=”大于等于,”<="小于等于,"/="不等于。

将上面的方法改为求一个列表的最小值,我们只需要把"<"改为">“,另外注意把函数名改为 list_min 会更合适一些哦。

记得我曾经在较早前提起过变量只能在作用域内被赋值一次吗?在上面我们看到,Result_so_far被重复的赋值了很多次,这是合法的,因为每次我们调用list_max/2的时候系统都会新建一个作用域并且每个作用域内的变量都是完全不一样的。

另一种创建和赋值给变量的方法是使用操作符=。所以如果我写下M=5,一个叫做M的变量就会被创建然后被赋值为5.如果我又在同一个作用域中写M=6,我们将得到一个错误提示。在shell中尝试下面的代码:

30> M = 5.
5
31> M = 6.
** exception error: no match of right hand side value 6
32> M = M + 1.
** exception error: no match of right hand side value 6
33> N = M + 1.
6
34> 

匹配操作符在分离和创建新的变量方面有独特的作用:

34> {X, Y} = {paris, {f, 28}}.
{paris,{f,28}}
35> X.
paris
36> Y.
{f,28}
37> 

这里我们的X得到了值pairs,Y得到了{f,28}。
当然,如果我们尝试对其他的城市重复上面的操作又不改变变量,那么会得到出错信息:

37> {X, Y} = {london, {f, 36}}.
** exception error: no match of right hand side value {london,{f,36}}

变量能够用来提高程序的可阅读性,例如,上面的list_max/2函数,我们可以写:

list_max([Head|Rest], Result_so_far) when Head > Result_so_far ->
    New_result_far = Head,
    list_max(Rest, New_result_far);

这样的写法可能更加清晰一点。


留下一个回复

你的email不会被公开。