I would like to throw in my implementation that is inspired by `std::transform` 
from c++.
    
    
    proc genRangeswap[Coll](data: var Coll; s0, s1, N: Natural): void =
      for i in 0 ..< N:
        swap(data[s0+i], data[s1+i])
    
    proc genTransform[Coll](data: var Coll; first, middle, last: Natural): void 
=
      assert(0 <= first and first <= middle and middle < last and last <= 
data.len)
      if first == middle:
        return
      
      let
        N = middle - first
        M = last - middle
      
      if N < M:
        genRangeswap(data, first  , middle  , N  )
        genTransform(data, first+N, middle+N, last)
      else: # M >= N
        genRangeswap(data, first    , middle  , M )
        genTransform(data, first+M, middle, last)
    
    proc transform*(data: var string; first, middle, last: Natural): void =
      genTransform(data, first, middle, last)
    
    proc transform*(data: var string; middle: Natural): void =
      genTransform(data, 0, middle, data.len)
    
    proc transform*[T](data: var openarray[T]; first, middle, last: Natural): 
void =
      genTransform(data, first, middle, last)
    
    proc transform*[T](data: var openarray[T]; middle: Natural): void =
      genTransform(data, 0, middle, data.len)
    
    

It has a generic core implementation that is not exported, and has a few 
wrappers that are mostly there to prevent false positives in auto completion. 
Everything is based on the rangeswap function that basically swaps two 
subranges of the same sequence. It is implemented in a way that it could easily 
be optimized for some sort of memswap on the string type. I don't know yet how 
safe it is to use memory swapping on other types, but I have a positive feeling 
that it is possible even though it sounds pretty dangerous to do so.

Reply via email to