Errors when trying to define a mutable variable for a literal value in a proc argument, only seq works right now but only with --gc:arc
Since the value is probably is only going to be used in the procedure, I think it should be mutable with just a var keyword
Example with seq
proc fn(a: var seq[int]):auto = a[0]=1;a # doesn't work
proc fn(a: sink seq[int]):auto = a[0]=1;a # works only with --gc:arc
echo fn @[1,2,3]
Example with array
proc fn[I,T](a: var array[I,T]):auto = a[0]=1;a # doesn't work
proc fn[I,T](a: sink array[I,T]):auto = a[0]=1;a # doesn't work
echo fn [1,2,3]
Output with var:
expression '[1,2,3]' is immutable, not 'var'
Output with sink:
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
Additional information
Nim Compiler Version 1.2.6 [Windows: amd64]
First will not work because "var" expects a mutable sequence, but you're passing a seq literal which is immutable.
The second one with --gc:arc works but will make a copy (sink is allowed to make a copy if the passed argument is immutable)
I see so there is no way to assign the value to a mutable variable directly
I see so there is no way to assign the value to a mutable variable directly
I believe you're looking for C-style function-local modifiable parameters? Then in Nim all you do is to duplicate said variable.
proc fn(a: seq[int]): seq[int] =
var a = a
a[0] = 1
# in idiomatic Nim we would assign `a` to `result` and perform the changes there,
# but I'm showing the shadowing "pattern" to demonstrate what can be done.
result = a
I don't think that would be very efficient, what would happen if I want to pass a very big array just to modify a few positions? Shouldn't there be a way to assign the value directly to the variable memory, I think that is what most languages do like C++ or C#
Does the variable result always copies the returned value? Isn't that avoided with the lent keyword?
I don't think that would be very efficient, what would happen if I want to pass a very big array just to modify a few positions?
Then you use var T. You can use sugar.dup in those cases to make initializing with a literal easier.
proc fn(a: var openArray[int]) = # using openArray since that lets you pass both seqs and arrays
a[0] = 1
import sugar
let b = @[0, 0, 0, 0].dup fn
echo b # prints @[1, 0, 0, 0]
Literals will always have to be copied to the memory before modification can happen (this applies to all languages). So don't sweat it too much (it's very fast unless you have several gigabytes as a literal, usually at that point you're better off storing it in a specialized format and read it back at runtime).
And yes result will always copy the value unless the return type is a var/lent/openArray type (the latter two requires {.experimental: "views".}).