Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nim: How to iterate over a slice?

I'm puzzled by the following observation. On the one hand, this works:

for i in 5..10:
  echo i

But as soon as I store the slice in a variable, I can no longer iterate over it, i.e., this fails:

var slice = 5..10
for i in slice:
  echo i

The error is type mismatch: got (Slice[system.int]), and apparently there is no overloaded signature of the system.items iterator for Slice[T]. This raises the questions:

  • Why does it work at all in the first case?
  • Is there a workaround to iterate over a slice in the second case?
like image 465
bluenote10 Avatar asked Apr 03 '15 08:04

bluenote10


1 Answers

With for i in 5..10: you invoke the iterator .. (doc), which is just an alias for countup. Since this is an inline iterator it transforms the for-loop into a while-loop over the values 5 to 10. But inline iterators cannot be assigned to a variable, other than closure iterators.

With var slice = 5..10 you invoke the proc .. (doc), which generates a Slice(a: 5, b: 10). But Slices don't have a default items iterator defined.

You could iterate from slice.a to slice.b, like this:

var slice = 5..10
for i in slice.a .. slice.b:
  echo i

Since this is not very nice, the proper solution is to define your own items iterator, like this:

iterator items*[T](s: Slice[T]): T =
  for i in s.a .. s.b:
    yield i

var slice = 5..10
for i in slice:
  echo i

Since this seems pretty reasonable to me, I made a pull request to have this included in the system module: https://github.com/nim-lang/Nim/pull/2449

like image 140
def- Avatar answered Oct 20 '22 11:10

def-