6

I am trying to learn Nim and its features, such Iterators; and i found that the following example works fine.

for i in countup(1,10):   # Or its equivalent 'for i in 1..10:' 
 echo($i)

However, The following do not works:

var 
 counter = countup(1,10) # THIS DO NOT WORK !
 # counter = 1..10   # This works

for i in counter :  
 echo($i)

The Nim Compiler reports the following error :

Error: attempting to call undeclared routine: 'countup'

How countup is undeclared routine , where it is a built-in iterator !?

Or it is a bug to report about ?

What are the solutions to enforce a custom iterator in variable declaration, such countup or countdown ?

NOTE: I am using Nim 0.13.0 on Windows platform.

Grzegorz Adam Hankiewicz
  • 7,349
  • 1
  • 36
  • 78
GeoObserver
  • 128
  • 6

2 Answers2

7

That happens because countup is an inline iterator only. There is a definition for .. as an inline iterator as well as a Slice:

Inline iterators are 0-cost abstractions. Instead you could use a first-class closure iterator by converting the inline iterator to one:

template toClosure*(i): auto =
  ## Wrap an inline iterator in a first-class closure iterator.
  iterator j: type(i) {.closure.} =
    for x in i:
      yield x
  j

var counter = toClosure(countup(1,10))

for i in counter():
  echo i
def-
  • 5,275
  • 20
  • 18
1

There are two ways for that. You can use toSeq procedure from sequtils module.

    import sequtils
    let x = toSeq(1..5)
    let y = toSeq(countdown(5, 1))

Or you can define a new procedure, using accumulateResult template from system module (imported implicitly)

    proc countup(a, b: int, step = 1): seq[int] =
      accumulateResult(countup(a, b, step))

    let x = countup(1, 5)
planhths
  • 11
  • 2