summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorTimothee Cour <timothee.cour2@gmail.com>2018-08-16 14:19:36 -0700
committerAndreas Rumpf <rumpf_a@web.de>2018-08-16 23:19:36 +0200
commitaf037546b0b8fb77a9bd33c6f75f6c7c216fa9bb (patch)
treefed4c8f29e51af1b491ba72b6d276493be13e39d /lib/pure
parent3ca8ebe778cb82cdbd97d7a9a00015bbeed1a696 (diff)
downloadNim-af037546b0b8fb77a9bd33c6f75f6c7c216fa9bb.tar.gz
fixes #7187 sequtils.toSeq produces the sequence from the iterator twice (#8586)
* cleanups refs #8584
* fixes #7187
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/collections/sequtils.nim40
1 files changed, 26 insertions, 14 deletions
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index c8080546a..612624f1d 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -518,13 +518,17 @@ template toSeq*(iter: untyped): untyped =
   ##         result = true)
   ##   assert odd_numbers == @[1, 3, 5, 7, 9]
 
+  # Note: see also `mapIt` for explanation of some of the implementation
+  # subtleties.
   when compiles(iter.len):
-    var i = 0
-    var result = newSeq[type(iter)](iter.len)
-    for x in iter:
-      result[i] = x
-      inc i
-    result
+    block:
+      evalOnceAs(iter2, iter, true)
+      var result = newSeq[type(iter)](iter2.len)
+      var i = 0
+      for x in iter2:
+        result[i] = x
+        inc i
+      result
   else:
     var result: seq[type(iter)] = @[]
     for x in iter:
@@ -1031,6 +1035,12 @@ when isMainModule:
           result = true)
     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
     let
       numbers = @[5, 9, 11]
@@ -1092,12 +1102,18 @@ when isMainModule:
     doAssert foo1(openArray[int]([identity(1),identity(2)])) == @[10,20]
     doAssert counter == 2
 
+    # Corner cases (openArray litterals should not be common)
     template foo2(x: openArray[int]): seq[int] = x.mapIt(it * 10)
     counter = 0
     doAssert foo2(openArray[int]([identity(1),identity(2)])) == @[10,20]
     # TODO: this fails; not sure how to fix this case
     # 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
     # NOTE: `[].mapIt(it)` is illegal, just as `let a = @[]` is (lacks type
     # of elements)
@@ -1106,16 +1122,12 @@ when isMainModule:
     doAssert newSeq[int](0).mapIt(it) == @[]
 
   block: # mapIt redifinition check, see https://github.com/nim-lang/Nim/issues/8580
-    let t = [1,2].mapIt(it)
-    doAssert t == @[1,2]
+    let s2 = [1,2].mapIt(it)
+    doAssert s2 == @[1,2]
 
   block:
-    var counter = 0
-    proc getInput():auto =
-      counter.inc
-      [1, 2]
-    doAssert getInput().mapIt(it*2).mapIt(it*10) == @[20, 40]
-    # make sure argument evaluated only once, analog to
+    counter = 0
+    doAssert [1,2].identity().mapIt(it*2).mapIt(it*10) == @[20, 40]
     # https://github.com/nim-lang/Nim/issues/7187 test case
     doAssert counter == 1