变量作用域

变量作用域

子句中变量的生存期从它首次被绑定处开始,到子句中对该变量的最后一个引用处结束。变量的绑定只会在模式匹配中发生;可以将之认作是一个变量产生过程。后续对变量的所有引用都是对变量的值的使用 。表达式中的变量必须是经过绑定的 。变量第一次出现时就被用在表达式中是非法的。比如:

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原语的两个分支中都有定义。

脚注

[1] 附录A给出了Erlang的形式语法。
[2] 许多人认为破坏性赋值会导致难以理解和易错的不清晰的程序。
--- ---
[3] 标记Var→Value表示变量Var的值为Value。
--- ---
[4] 假设所有函数调用都结束。
--- ---
[5] 即是说函数的值 与调用上下文无关。
--- ---
[6] 有时被称为垃圾箱。
--- ---
[7] 好吧,几乎是 ——想想看factorial(-1)?
--- ---
[8] 如果不知道选哪个,选最漂亮的那个!
--- ---
[*] 译者注:list/1在较新版本的Erlang中已经不推荐使用,应使用is_list/1。感谢网友孔雀翎指出。
--- ---