fixes #7187 sequtils.toSeq produces the sequence from the iterator twice (#8586)

* cleanups refs #8584
* fixes #7187
This commit is contained in:
Timothee Cour 2018-08-16 14:19:36 -07:00 • committed by Andreas Rumpf
commit af037546b0

View file

@ -518,13 +518,17 @@ template toSeq*(iter: untyped): untyped =
## result = true) ## result = true)
## assert odd_numbers == @[1, 3, 5, 7, 9] ## assert odd_numbers == @[1, 3, 5, 7, 9]
# Note: see also `mapIt` for explanation of some of the implementation
# subtleties.
when compiles(iter.len): when compiles(iter.len):
var i = 0 block:
var result = newSeq[type(iter)](iter.len) evalOnceAs(iter2, iter, true)
for x in iter: var result = newSeq[type(iter)](iter2.len)
result[i] = x var i = 0
inc i for x in iter2:
result result[i] = x
inc i
result
else: else:
var result: seq[type(iter)] = @[] var result: seq[type(iter)] = @[]
for x in iter: for x in iter:
@ -1031,6 +1035,12 @@ when isMainModule:
result = true) result = true)
assert odd_numbers == @[1, 3, 5, 7, 9] assert odd_numbers == @[1, 3, 5, 7, 9]
block:
# tests https://github.com/nim-lang/Nim/issues/7187
counter = 0
let ret = toSeq(@[1, 2, 3].identity().filter(proc (x: int): bool = x < 3))
doAssert ret == @[1, 2]
doAssert counter == 1
block: # foldl tests block: # foldl tests
let let
numbers = @[5, 9, 11] numbers = @[5, 9, 11]
@ -1092,12 +1102,18 @@ when isMainModule:
doAssert foo1(openArray[int]([identity(1),identity(2)])) == @[10,20] doAssert foo1(openArray[int]([identity(1),identity(2)])) == @[10,20]
doAssert counter == 2 doAssert counter == 2
# Corner cases (openArray litterals should not be common)
template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10) template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10)
counter = 0 counter = 0
doAssert foo2(openArray[int]([identity(1),identity(2)])) == @[10,20] doAssert foo2(openArray[int]([identity(1),identity(2)])) == @[10,20]
# TODO: this fails; not sure how to fix this case # TODO: this fails; not sure how to fix this case
# doAssert counter == 2 # doAssert counter == 2
counter = 0
doAssert openArray[int]([identity(1), identity(2)]).mapIt(it) == @[1,2]
# ditto
# doAssert counter == 2
block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468 block: # mapIt empty test, see https://github.com/nim-lang/Nim/pull/8584#pullrequestreview-144723468
# NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type # NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type
# of elements) # of elements)
@ -1106,16 +1122,12 @@ when isMainModule:
doAssert newSeq[int](0).mapIt(it) == @[] doAssert newSeq[int](0).mapIt(it) == @[]
block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580 block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580
let t = [1,2].mapIt(it) let s2 = [1,2].mapIt(it)
doAssert t == @[1,2] doAssert s2 == @[1,2]
block: block:
var counter = 0 counter = 0
proc getInput():auto = doAssert [1,2].identity().mapIt(it*2).mapIt(it*10) == @[20, 40]
counter.inc
[1, 2]
doAssert getInput().mapIt(it*2).mapIt(it*10) == @[20, 40]
# make sure argument evaluated only once, analog to
# https://github.com/nim-lang/Nim/issues/7187 test case # https://github.com/nim-lang/Nim/issues/7187 test case
doAssert counter == 1 doAssert counter == 1