You are not alone.
Though in my case I wanted to remove copies when safe and it seemed like seq
wrapped in objects always triggered copies.
Anyway, relevant issues:
* Return by let/const values
[#6793](https://github.com/nim-lang/Nim/issues/6793)
* Distinguish let/var in assignment
Yes, I understand. Indeed, it seemed to me it was an issue quite difficult to
solve. But, it is something very unlikely to happen in real programs and, so
far, nobody has encountered these problems. I have built these examples when I
have suspected that something may be wrong in some cases and
`let` was designed to replicate parameter passing semantics so that a
`template` can more easily do "evaluate once" for its parameters. Parameter
passing also does not involve (deep) copies. Fixing/changing it will cause
performance problems so it's not clear what to do.
Yes, I think the last example is the most annoying one as, to solve it, we have
to do a copy which is just something we don't want to do for obvious
performance reasons. I have tried to change the parameter type from sequence to
openarray with same result. And with an array instead of a
For global variable example, I tried to modify the s and it cannot be compiled.
Since s is considered immutable, so s is shared. However the member is mutable
so it becomes like that.
I think the only way to do it is to keep separation between mutable and
immutable variable. That's why we can
Just thinking out loud:
I image how difficult it would be to fix this one:
var a = @[0, 1, 2, 3]
proc p(s: seq[int]) =
echo s # @[0, 1, 2, 3]
a[^1] = 4
echo s # @[0, 1, 2, 4]
p(a)
Global alias analysis would be required or tons of not
Yes, I know it works with **var**. I have once written a statement let b = a
in a program, **a** being a sequence, with a comment # No copy. Reading this
some months later, I was not sure that there is actually no copy (and I thought
that, in fact, a copy is needed). So I done some checks and
Interestingly, this seems to work correctly:
proc p() =
var a = @[0, 1, 2, 3]
discard a.pop
var b = a # note the change from `let` to `var`
a.add(5)
echo a # @[0, 1, 2, 5]
echo b # @[0, 1, 2]
p()
Looks like an optimization gone
I use 0.18.0, so the results may differ, of course. When running in the
browser, I get the same results as with version 0.18.0.
Maybe the compiler does some optimization but it cannot consider that _a_ and
_b_ are not used in another place: they are used by _echo_.
Assigning with **var**
I ran your code, using 0.17.2, it gave wrong seq in example 1, other than that
it's same with your result.
Is that because the compiler infer that variable a and b didn't used at other
place so it's safe to be shared? Just a guess tho
I would like to discuss a problem I have encountered and for which I have
submitted a report on the bug tracker with a different version using
_newSeqOfCap_.
Here is a simple program:
proc p() =
var a = @[0, 1, 2]
let b = a
a.add(3)
echo a # @[0, 1, 2, 3]
11 matches
Mail list logo