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.

Reply via email to