Nim 中的参数传递

来源:互联网 发布:韩国淘宝模特孙允珠 编辑:程序博客网 时间:2024/04/27 22:21


Var parameters


在 Nim 中过程或方法有两种参数类型,一种是前面有 var 关键字 的参数,另一种是不带 var 的参数。

例如:


proc divmod(a, b: int; res, remainder: var int) =  res = a div b  remainder = a mod bvar  x, y: intdivmod(8, 5, x, y) # modifies x and yassert x == 1assert y == 3

在上面的例子中,a,b是不带 var 的参数,它们在过程中是不允许改变的,而 res, remainder 在过程中是能够改变其值的。 传递给 var 参数的必须是一个 l-value.


l-value 介绍:

     一个表达式能指定一个产生一个值或位置的计算。产生位置的表达式就是 l-values。(比如:var x = 5 中的 就是一个l-value。 就不是)。一个 l-value 能够表示一个位置或者这个位置包含的值,这取决于语境。表达式的值能够被静态确定的被称为常量表达式。它们不是 l-valueslet 声明的变量不是 l-values


var 参数是作为隐式的指针实现的,上面的例子与这个例子是等价的:

proc divmod(a, b: int; res, remainder: ptr int) =  res[] = a div b  remainder[] = a mod bvar  x, y: intdivmod(8, 5, addr(x), addr(y))assert x == 1assert y == 3


Nim 中的参数传递传的是地址,var 参数类型允许过程改变其值,是通过隐式的指针实现的,指针指向了变量的地址,所以改变的是原来变量的内容。不是var 参数的不允许改变其值。

变量在内存中的存储:




上面的例子可以通过返回一个元组的方式来实现:


proc divmod(a, b: int): tuple[res, remainder: int] =  (a div b, a mod b)var t = divmod(8, 5)assert t.res == 1assert t.remainder == 3var (x, y) = divmod(8, 5) # tuple unpackingassert x == 1assert y == 3


Var return type


一个过程、转换器或者迭代器可能返回一个 var 类型,这意味着 这个返回值是一个 l-value 和能够被调用者改变:

var g = 0proc WriteAccessToG(): var int =  result = gWriteAccessToG() = 6assert g == 6

要注意赋给 result 的值得是一个 l-value .


import strutilsdiscard """proc WriteAccessToG(): var int =  var g = 0  result = g # Error!              Error: address of 'g' may not escape its stack frame"""  discard """proc WriteAccessToG(g:int): var int =  result = g # Error!               Error: expression has no address"""proc WriteAccessToG(g:var int): var int =  result = g   proc WriteAccessToG2(g:ptr int): var int =  result = g[]   proc WriteAccessToG3(g:ptr string):  var string =     #带var 和不带是不一样的。 带var 是隐式的指针操作, result 与 g 指向同一位置。  echo "repr g = ",repr(g)                               #不带 var, result 在栈中重新分配一个空间。  #echo "repr result = ",repr(result)  result = g[]  echo "repr result = ",repr(result)  g[0] = 'a'  var   var1 = 5  var2 = "yrs"echo WriteAccessToG(var1)echo WriteAccessToG2(addr(var1))echo "addr(var2) = ",BiggestInt(cast[int](addr(var2))).toHex(12)echo "repr var2 = ",repr(var2)echo "returned = ", repr(WriteAccessToG3(addr(var2)))echo "repr var2 = ",repr(var2)


对于迭代器,一个元组的一部分返回类型可以有一个var 类型:


iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =  for i in 0..a.high:    yield (i, a[i])var  x:seq[string]x = @["a","b","c"]for m in mpairs(x):  echo m


在标准库里每一个返回一个 var 类型的程序的名子都是以 作为前缀。




 

1 0