summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md2
-rw-r--r--lib/pure/collections/sequtils.nim104
-rw-r--r--tests/manyloc/argument_parser/argument_parser.nim2
3 files changed, 66 insertions, 42 deletions
diff --git a/changelog.md b/changelog.md
index c8086fd51..db4e15a67 100644
--- a/changelog.md
+++ b/changelog.md
@@ -9,7 +9,7 @@
 
 - `base64.encode` no longer supports `lineLen` and `newLine` use `base64.encodeMIME` instead.
 - `os.splitPath()` behavior synchronized with `os.splitFile()` to return "/" as the dir component of "/root_sub_dir" instead of the empty string.
-
+- `sequtils.zip` now returns a sequence of anonymous tuples i.e. those tuples now do not have fields named "a" and "b".
 
 ### Breaking changes in the compiler
 
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 9573753ff..f71f13358 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -202,36 +202,49 @@ proc deduplicate*[T](s: openArray[T], isSorted: bool = false): seq[T] =
       for itm in items(s):
         if not result.contains(itm): result.add(itm)
 
-proc zip*[S, T](s1: openArray[S], s2: openArray[T]): seq[tuple[a: S, b: T]] =
-  ## Returns a new sequence with a combination of the two input containers.
-  ##
-  ## The input containers can be of different types.
-  ## If one container is shorter, the remaining items in the longer container
-  ## are discarded.
-  ##
-  ## For convenience you can access the returned tuples through the named
-  ## fields `a` and `b`.
-  ##
-  runnableExamples:
-    let
-      short = @[1, 2, 3]
-      long = @[6, 5, 4, 3, 2, 1]
-      words = @["one", "two", "three"]
-      letters = "abcd"
-      zip1 = zip(short, long)
-      zip2 = zip(short, words)
-      zip3 = zip(long, letters)
-    assert zip1 == @[(1, 6), (2, 5), (3, 4)]
-    assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
-    assert zip3 == @[(a: 6, b: 'a'), (a: 5, b: 'b'), (a: 4, b: 'c'),
-                     (a: 3, b: 'd')]
-    assert zip1[2].b == 4
-    assert zip2[2].b == "three"
+template zipImpl(s1, s2, retType: untyped): untyped =
+  proc zip*[S, T](s1: openArray[S], s2: openArray[T]): retType =
+    ## Returns a new sequence with a combination of the two input containers.
+    ##
+    ## The input containers can be of different types.
+    ## If one container is shorter, the remaining items in the longer container
+    ## are discarded.
+    ##
+    ## **Note**: For Nim 1.0.x and older version, ``zip`` returned a seq of
+    ## named tuple with fields ``a`` and ``b``. For Nim versions 1.1.x and newer,
+    ## ``zip`` returns a seq of unnamed tuples.
+    runnableExamples:
+      let
+        short = @[1, 2, 3]
+        long = @[6, 5, 4, 3, 2, 1]
+        words = @["one", "two", "three"]
+        letters = "abcd"
+        zip1 = zip(short, long)
+        zip2 = zip(short, words)
+      assert zip1 == @[(1, 6), (2, 5), (3, 4)]
+      assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
+      assert zip1[2][0] == 3
+      assert zip2[1][1] == "two"
+      when (NimMajor, NimMinor) <= (1, 0):
+        let
+          zip3 = zip(long, letters)
+        assert zip3 == @[(a: 6, b: 'a'), (5, 'b'), (4, 'c'), (3, 'd')]
+        assert zip3[0].b == 'a'
+      else:
+        let
+          zip3: seq[tuple[num: int, letter: char]] = zip(long, letters)
+        assert zip3 == @[(6, 'a'), (5, 'b'), (4, 'c'), (3, 'd')]
+        assert zip3[0].letter == 'a'
 
-  var m = min(s1.len, s2.len)
-  newSeq(result, m)
-  for i in 0 ..< m:
-    result[i] = (s1[i], s2[i])
+    var m = min(s1.len, s2.len)
+    newSeq(result, m)
+    for i in 0 ..< m:
+      result[i] = (s1[i], s2[i])
+
+when (NimMajor, NimMinor) <= (1, 0):
+  zipImpl(s1, s2, seq[tuple[a: S, b: T]])
+else:
+  zipImpl(s1, s2, seq[(S, T)])
 
 proc distribute*[T](s: seq[T], num: Positive, spread = true): seq[seq[T]] =
   ## Splits and distributes a sequence `s` into `num` sub-sequences.
@@ -1070,18 +1083,29 @@ when isMainModule:
       zip1 = zip(short, long)
       zip2 = zip(short, words)
       zip3 = zip(ashort, along)
-      zip4 = zip(ashort, awords)
-      zip5 = zip(ashort, words)
     assert zip1 == @[(1, 6), (2, 5), (3, 4)]
     assert zip2 == @[(1, "one"), (2, "two"), (3, "three")]
     assert zip3 == @[(1, 6), (2, 5), (3, 4)]
-    assert zip4 == @[(1, "one"), (2, "two"), (3, "three")]
-    assert zip5 == @[(1, "one"), (2, "two"), (3, "three")]
-    assert zip1[2].b == 4
-    assert zip2[2].b == "three"
-    assert zip3[2].b == 4
-    assert zip4[2].b == "three"
-    assert zip5[2].b == "three"
+    assert zip1[2][1] == 4
+    assert zip2[2][1] == "three"
+    assert zip3[2][1] == 4
+    when (NimMajor, NimMinor) <= (1, 0):
+      let
+        # In Nim 1.0.x and older, zip returned a seq of tuple strictly
+        # with fields named "a" and "b".
+        zipAb = zip(ashort, awords)
+      assert zipAb == @[(a: 1, b: "one"), (2, "two"), (3, "three")]
+      assert zipAb[2].b == "three"
+    else:
+      let
+        # As zip returns seq of anonymous tuples, they can be assigned
+        # to any variable that's a sequence of named tuples too.
+        zipXy: seq[tuple[x: int, y: string]] = zip(ashort, awords)
+        zipMn: seq[tuple[m: int, n: string]] = zip(ashort, words)
+      assert zipXy == @[(x: 1, y: "one"), (2, "two"), (3, "three")]
+      assert zipMn == @[(m: 1, n: "one"), (2, "two"), (3, "three")]
+      assert zipXy[2].y == "three"
+      assert zipMn[2].n == "three"
 
   block: # distribute tests
     let numbers = @[1, 2, 3, 4, 5, 6, 7]
@@ -1228,10 +1252,10 @@ when isMainModule:
     block:
       let
         numeric = @[1, 2, 3, 4, 5, 6, 7, 8, 9]
-        odd_numbers = toSeq(filter(numeric) do (x: int) -> bool:
+        oddNumbers = toSeq(filter(numeric) do (x: int) -> bool:
           if x mod 2 == 1:
             result = true)
-      assert odd_numbers == @[1, 3, 5, 7, 9]
+      assert oddNumbers == @[1, 3, 5, 7, 9]
 
     block:
       doAssert [1, 2].toSeq == @[1, 2]
diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim
index 9a37ef8c9..9cea59477 100644
--- a/tests/manyloc/argument_parser/argument_parser.nim
+++ b/tests/manyloc/argument_parser/argument_parser.nim
@@ -471,7 +471,7 @@ proc build_help*(expected: seq[Tparameter_specification] = @[],
   let width = prefixes.map(proc (x: string): int = 3 + len(x)).max
 
   for line in zip(prefixes, helps):
-    result.add(line.a & spaces(width - line.a.len) & line.b)
+    result.add(line[0] & spaces(width - line[0].len) & line[1])
 
 
 proc echo_help*(expected: seq[Tparameter_specification] = @[],