Nim 中的参数传递


Var parameters


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

例如:


proc divmod(a, b: int; res, remainder: var int) =
  res = a div b
  remainder = a mod b
var
  x, y: int
divmod(8, 5, x, y) # modifies x and y
assert x == 1
assert 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 b

var
  x, y: int
divmod(8, 5, addr(x), addr(y))
assert x == 1
assert 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 == 1
assert t.remainder == 3

var (x, y) = divmod(8, 5) # tuple unpacking
assert x == 1
assert y == 3


Var return type


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

var g = 0

proc WriteAccessToG(): var int =
  result = g

WriteAccessToG() = 6
assert g == 6

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


import strutils

discard """
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 类型的程序的名子都是以 作为前缀。




 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值