Mutable Bindings.
Racket 支持使用 assignment statement set! (set-bang) 来 mutate bindings。
注意区分 mutate 与 shadow:若 x 在环境中,使用 (set! x 13) 将 mutate the binding so that x maps to the value 13. Doing so affects all code that has this x in its environment. 这也就是说,在 mutate x 之后,在所有的环境中 (而不仅仅是 mutate 之后的环境),x 都将与 13 对应。
1 | (define b 3) |
在上例中,我们依次对 bindings 进行求值 (就和在 ML 中一样):
bbound to 3.fbound to(lambda (x) (* 1 (+ x b))): 正如之前强调的,在f被调用之前不会执行函数体。c: 在环境中寻找b=>bbound to 3 =>cbound to 7.- mutate
b: 此时在所有环境中bbound to 5. z: 调用函数f=> 参数xbound to 4 => 在环境中寻找b=>bbound to 5 =>zbound to 9.w: 在环境中寻找c=>cbound to 7 =>wbound to 7.
在 functional programming 中,使用 mutation 通常是非常 error-prone 的。举例来说,可能函数 f 在定义时想要使用的是 b 之前的值。然而 b 在之后发生了 mutate,这时调用 f 结果会与预期不一致。
General technique in software development. If something might get mutated and you need the old value, make a copy before mutation can occur.
1 | (define f |
This code makes the b in the function body refer to a local b that is initialized to the global b.