Skip to content

sequtils.toSeq produces the sequence from the iterator twice if compiles(iter.len) == true #7187

@skilchen

Description

@skilchen

In the doc comment for sequtils.toSeq we find this example:

let
  numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
  odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
         if x mod 2 == 1:
           result = true)

If you run this, the filtered sequence is produced twice, as can be seen here on the nim playground with my instrumented copies of filter and toSeq. I think its the same problem that was fixed eg. in mapIt by copying the iterable to a local variable and therefore forcing the iteration to take place.

My proposed fix looks like this:

template toSeqFixed*(iter: untyped): untyped =
  when compiles(iter.len):
    iter
  else:
    var result: seq[type(iter)] = @[]
    for x in iter:
      result.add(x)
    result

but, as usual, i am not sure if this fix is correct...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions