I found these quite useful for particular slicing:
template `..>`*[T, U](a: T, b: U): untyped =
## Binary slice operator constructing an interval based on offsset 'a' and length 'b'.
## 'b' can always be a BackwardsIndex. When combined with [] slicing, 'a' can also be a BackwardsIndex.
## When the length is BackwardsIndex then the resulting interval provides 'b' indeces before (excluding) 'a',
## otherwise the resulting interval provides 'b' indeces starting with (including) 'a'
when b is BackwardsIndex:
when a is BackwardsIndex: ^(a.int + b.int) .. ^(succ(a.int))
else: (a - T(b)) .. pred(a)
else:
when a is BackwardsIndex: a .. ^(U(a) - pred(b))
else: a .. pred(a + b)
iterator `..>`*[T, U](a: T, b: U): T =
# generator of 'b' indeces before or from 'a'
when b is BackwardsIndex:
var i = a - T(b)
while i < a:
yield i
inc i
else:
var i = a
while i < (a + b):
yield i
inc i
let a = ["a0","a1","a2","a3","a4","a5","a6","a7","a8","a9"]
echo a[5 ..> 3] # @["a5", "a6", "a7"]
echo a[5 ..> ^3] # @["a2", "a3", "a4"]
echo a[^4 ..> 3] # @["a6", "a7", "a8"]
echo a[^4 ..> ^6] # @["a0", "a1", "a2", "a3", "a4", "a5"]
for i in 5 ..> 3: echo i
for i in 5 ..> ^7: echo i
I prefer this notation:
a[5 ..+ 3]
a[5 ..- 3]