Var返回类型

proc,转换器或迭代器可能返回一个 var 类型,这意味着返回的值是一个左值,并且可以由调用者修改:

  1. var g = 0
  2.  
  3. proc writeAccessToG(): var int =
  4. result = g
  5.  
  6. writeAccessToG() = 6
  7. assert g == 6

如果隐式引入的指针可用于访问超出其生命周期的位置,则这是一个静态错误:

  1. proc writeAccessToG(): var int =
  2. var g = 0
  3. result = g # Error!

For iterators, a component of a tuple return type can have a var type too:

  1. iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =
  2. for i in 0..a.high:
  3. yield (i, a[i])

在标准库中,返回 var 类型的例程的每个名称都以每个约定的前缀 m 开头。Memory safety for returning by var T is ensured by a simple borrowing rule: If result does not refer to a location pointing to the heap (that is in result = X the X involves a ptr or ref access) then it has to be deviated by the routine's first parameter:

  1. proc forward[T](x: var T): var T =
  2. result = x # ok, deviated from the first parameter.
  3.  
  4. proc p(param: var int): var int =
  5. var x: int
  6. # we know 'forward' provides a view into the location deviated by
  7. # its first argument 'x'.
  8. result = forward(x) # Error: location is derived from ``x``
  9. # which is not p's first parameter and lives
  10. # on the stack.

In other words, the lifetime of what result points to is attached to the lifetime of the first parameter and that is enough knowledge to verify memory safety at the callsite.

未来的方向

Nim的更高版本可以使用如下语法更准确地了解借用规则:

  1. proc foo(other: Y; container: var X): var T from container

这里 var T from container 明确地暴露了该位置不同于第二个形参(在本例中称为'container')。 语法 var T from p 指定一个类型 varTy [T,2] ,它与 varTy [T,1] 不兼容。