变量作用域
子句中变量的生存期从它首次被绑定处开始,到子句中对该变量的最后一个引用处结束。变量的绑定只会在模式匹配中发生;可以将之认作是一个变量产生过程。后续对变量的所有引用都是对变量的值的使用。表达式中的变量必须是经过绑定的。变量第一次出现时就被用在表达式中是非法的。比如:
- 1234
| - f(X) -> Y = g(X), h(Y, X), p(Y).
|
第1行中,定义了变量X(它在进入函数时被绑定)。第2行中,使用了X,定义了Y(首次出现)。第3行中,使用了X和Y,然后在第4行中使用了Y。
if、case和receive的作用域规则
在if、case或receive原语中引入的变量会被隐式导出到原语主体之外。比方我们有:
- f(X) ->
- case g(X) of
- true -> A = h(X);
- false -> A = k(X)
- end,
- ...
变量A在其被定义的case原语之后仍然有效。从if、case或receive原语中导出变量时应注意一些规则:
在if、case或receive原语的不同分支中引入的变量集合必须相同,除非缺少的变量在原语外不再被引用。
例如以下代码:
- f(X) ->
- case g(X) of
- true -> A = h(X), B = A + 7;
- false -> B = 6
- end,
- h(A).
这段代码就是非法的。因为在对true分支求值时定义了变量A和B,而在对false分支求值时只定义了B。在case原语之后,又在调用h(A)中引用了A——如果是fase分支被求值,则A尚未被定义。注意如果调用的不是h(A)而是h(B)则这段代码就是合法的,因为B在case原语的两个分支中都有定义。
脚注
[2] | 许多人认为破坏性赋值会导致难以理解和易错的不清晰的程序。 |
[3] | 标记Var→Value表示变量Var的值为Value。 |
[7] | 好吧,几乎是——想想看factorial(-1)? |
[*] | 译者注:list/1在较新版本的Erlang中已经不推荐使用,应使用is_list/1。感谢网友孔雀翎指出。 |