介绍

使用let关键字声明的变量只能在代码块{ ... }中有效。

  1. let x = 0;
  2. {
  3. let y = 1;
  4. };
  5. x + y // ERROR!
  6. // ^ unbound local 'y'

不过{ ... }声明的变量在嵌套{ ... }是可以使用的。

  1. {
  2. let x = 0;
  3. {
  4. let y = x + 1; // valid
  5. }
  6. }

shadowing

如果给同一个变量多次赋值,那么这个变量只保留最新值。这个操作被称作shadowing

  1. let x = 0;
  2. assert!(x == 0, 42);
  3. let x = 1; // x is shadowed
  4. assert!(x == 1, 42);

对于一个 resource 如果没有drop属性,在代码块结束的时候是不会自动销毁的。例如下面代码,我们编辑后使用命令move sandbox publish -v

  1. address 0x1 {
  2. module Shadow {
  3. struct Coin has store { value: u64 }
  4. fun unused_resource() {
  5. let x = Coin { value: 0};
  6. x.value = 1;
  7. x;
  8. }
  9. }
  10. }

控制台将返回:

  1. ability constraint not satisfied
  2. struct Coin has store { value: u64 }
  3. ---- To satisfy the constraint, the 'drop' ability would need to be added here
  4. let x = Coin { value: 0};
  5. ------ The type '0x1::Shadow::Coin' does not have the ability 'drop'
  6. x.value = 1;
  7. x;
  8. ^ Cannot ignore values without the 'drop' ability. The value must be used

如果在嵌套代码块中变量 shadowed ,shadowed 的变量只作用于嵌套代码块中。

  1. script {
  2. use Std::Debug;
  3. fun main() {
  4. let x = 0;
  5. {
  6. let x = 1;
  7. Debug::print(&x);
  8. };
  9. Debug::print(&x);
  10. }
  11. }
  12. // console
  13. [debug] 1
  14. [debug] 0

move 和 copy 属性

Move 中所有变量都拥有两种属性movecopy。如果没有显性使用,Move 编译器会自动识别。

copy会在变量内部创建一个新的副本,可以多次使用copy关键字复制相同的变量。

  1. let x = 0;
  2. let y = copy x + 1;
  3. let z = copy x + 2;

move从局部变量中获取(移动)值,而不会产生新副本,一个变量不能多次move

  1. let x = 1;
  2. let y = move x + 1;
  3. // ------ Local was moved here
  4. let z = move x + 2; // Error!
  5. // ^^^^^^ Invalid usage of local 'x'
  6. y + z

Move 的类型系统不允许一个变量在move后继续使用,可以防止局部变量在赋值之前被使用。