To avoid copies and index computation when mutating slices of sequence, I would
need to use iterator that yields mutable values. This closure iterator will be
passed to another zip iterator so I can iterate on 2 iterators at the same time
and modify the values yielded by the first one.
1\. Small example of an inline iterator
Please note that in my full use case, some values will be skipped or iteration
may not be in order.
var s = @[1, 2, 3, 4]
## inline iterator with mutable output
for val in s.mitems:
val *= 2
echo s #@[2, 4, 6, 8]
2\. A closure iterator with immutable yield can be written like this
proc values*[T](s: seq[T]): auto {.noSideEffect.}=
return iterator(): T =
for val in s:
yield val
let it = s.values
for val in it():
echo val
3\. Now this is not working (expression has no address)
proc mvalues[T](s: var seq[T]): auto {.noSideEffect.}=
return iterator(): var T =
for val in s:
yield val
var mit = s.mvalues
4\. Now this is my target goal. (Reminder, "mvalues" and "values" iterator in
the full case will have a non-trivial iteration logic)
for old_val, val in zip(seq1.mvalues, seq2.values):
old_val = val
5\. For reference this is the zip iterator that accepts 2 closure iterators
iterator zip[T1, T2](inp1: iterator(): T1, inp2: iterator(): T2): (T1, T2)
{.noSideEffect.} =
## Inline iteration on 2 closure iterators at the same time
let it1 = inp1
let it2 = inp2
while true:
let val1 = it1()
let val2 = it2()
if finished(it1) or finished(it2):
break
yield (val1, val2)
Is there a way to make 4 works by modifying 3 and 5? I suspect it's not
possible for a closure iterator to borrow a var seq.