I was wondering about looping constructs that also include extra information in the predicate such as the index for ordered collections like sequence.
For example, the following code
#filter out the numbers that do not correspond with their index
var s = @[0,1,2,4]
var o = @[]
for i in countup(0,s.high):
if i == s[i]: o.add(i)
It occurs to me that the filterIt method in sequtils would be perfect for this, something like so:
import sequtils
#filter out the numbers that do not correspond with their index
var s = @[0,1,2,4]
var o = filterIt(s, it.index == it)
Looking at the source for filterIt leads me to believe this isn't possible for this particular function since it's an inline iterator (I think, I've been reading up on the iterators).
Obviously the original is just fine, but is there a better way to accomplish this (and things like it) in nim?
You can piece together a solution with other tools, e.g.:
import sequtils
var s = @[0, 1, 2, 4]
let o = mapIt(filterIt(toSeq(s.low .. s.high).zip(s),
it[0] == it[1]),
int, it[0])
echo o
But in reality, the stdlib cannot support all possible ways to iterate over a container and do something with the contents. At some point, you'll just have to write your own module for the functionality that's specific for your needs but not general enough to be put in the stdlib. E.g.
template filterItWithIndex*[T](s: seq[T], pred: expr): seq[T] =
var result {.gensym.}: type(s) = @[]
for index {.inject.}, it {.inject.} in pairs(s):
if pred:
add(result, it)
result
when isMainModule:
var s = @[0, 1, 2, 4]
let p = filterItWithIndex(s, it == index)
echo p
I agree with you in general, but in this case I see no good reason to avoid adding it to stdlib.
Regardless, it looks like doing it manually is the simpler approach in this manner, that's really the info I was looking for :)