An iterator is a resumable proc. Iterators are usually invoked in for loops.
We have already seen the built-in iterators items and ..<. If they were not built-in we could easily define them ourselves:
iterator `..<`(a, b: int): int = # 1
var i = a
while i < b:
yield i # 2
inc i # 3
iterator items(s: seq[Point]): Point =
for i in 0 ..< s.len: # 4
yield s[i]
proc. The ..< operator takes two integers and produces an integer.yield it. The for loop that calls the iterator ..< calls ..< again and again, each time the control flow resumes where the iterator left off until the iterator’s while loop finishes. (When i >= b.)inc i means to increment the integer i by 1. It can be also be written as i = i + 1 or i += 1...< iterator. Iterators are called in for loops.A yield statement can be easily understood as a variation of a return statement: A return statement returns the control flow to the caller, potentially producing a value that the caller can receive:
proc find(haystack: string; needle: char): int =
for i in 0 ..< haystack.len:
if haystack[i] == needle: return i # 1
return -1 # 2
let index = find("abcabc", 'c') # 3
i to the caller and do not continue with the execution of find. This implies that the for loop is left too.find returns the index of the first occurrence of needle inside haystack. It is not possible to resume its execution in order to retrieve the possible other occurrences of needle. An iterator like findAll can do that, thanks to the yield keyword:
iterator findAll(haystack: string; needle: char): int =
for i in 0 ..< haystack.len:
if haystack[i] == needle: yield i # 1
# 2
for index in findAll("abcabc", 'c'): discard # 3
i to the caller and continue with the execution of findAll later.yield -1 statement. If the iterator does not yield more values, the calling for loop will stop.findAll and bind the current value to index.