Var parameters

The type of a parameter may be prefixed with the var keyword:

  1. proc divmod(a, b: int; res, remainder: var int) =
  2. res = a div b
  3. remainder = a mod b
  4. var
  5. x, y: int
  6. divmod(8, 5, x, y) # modifies x and y
  7. assert x == 1
  8. assert y == 3

In the example, res and remainder are var parameters. Var parameters can be modified by the procedure and the changes are visible to the caller. The argument passed to a var parameter has to be an l-value. Var parameters are implemented as hidden pointers. The above example is equivalent to:

  1. proc divmod(a, b: int; res, remainder: ptr int) =
  2. res[] = a div b
  3. remainder[] = a mod b
  4. var
  5. x, y: int
  6. divmod(8, 5, addr(x), addr(y))
  7. assert x == 1
  8. assert y == 3

In the examples, var parameters or pointers are used to provide two return values. This can be done in a cleaner way by returning a tuple:

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

One can use tuple unpacking to access the tuple’s fields:

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

Note: var parameters are never necessary for efficient parameter passing. Since non-var parameters cannot be modified the compiler is always free to pass arguments by reference if it considers it can speed up execution.