aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkostya-sh <kostya-sh@users.noreply.github.com>2017-10-18 19:41:49 +0100
committeralandonovan <adonovan@google.com>2017-10-18 14:41:49 -0400
commit5cb1ab577184d6f26040b58b71de23f1ff20035c (patch)
tree9b9854b206d60320e75bf13199d35a550c2f24e4
parent23d0c969dd9f6077e524930b96b0c2707a16d361 (diff)
downloadstarlark-go-5cb1ab577184d6f26040b58b71de23f1ff20035c.tar.gz
skylark: zip: support iterables of unknown length (#24)
-rw-r--r--library.go40
-rw-r--r--testdata/builtins.sky6
2 files changed, 30 insertions, 16 deletions
diff --git a/library.go b/library.go
index b8f4b15..5f88c32 100644
--- a/library.go
+++ b/library.go
@@ -1117,23 +1117,35 @@ func zip(thread *Thread, _ *Builtin, args Tuple, kwargs []Tuple) (Value, error)
}
iters[i] = it
n := Len(seq)
- if n < 0 {
- // TODO(adonovan): support iterables of unknown length.
- return nil, fmt.Errorf("zip: argument #%d has unknown length", i+1)
- }
if i == 0 || n < rows {
- rows = n
+ rows = n // possibly -1
+ }
+ }
+ var result []Value
+ if rows >= 0 {
+ // length known
+ result = make([]Value, rows)
+ array := make(Tuple, cols*rows) // allocate a single backing array
+ for i := 0; i < rows; i++ {
+ tuple := array[:cols:cols]
+ array = array[cols:]
+ for j, iter := range iters {
+ iter.Next(&tuple[j])
+ }
+ result[i] = tuple
}
- }
- result := make([]Value, rows)
- array := make(Tuple, cols*rows) // allocate a single backing array
- for i := 0; i < rows; i++ {
- tuple := array[:cols:cols]
- array = array[cols:]
- for j, iter := range iters {
- iter.Next(&tuple[j])
+ } else {
+ // length not known
+ outer:
+ for {
+ tuple := make(Tuple, cols)
+ for i, iter := range iters {
+ if !iter.Next(&tuple[i]) {
+ break outer
+ }
+ }
+ result = append(result, tuple)
}
- result[i] = tuple
}
return NewList(result), nil
}
diff --git a/testdata/builtins.sky b/testdata/builtins.sky
index d6774a8..d5f8f04 100644
--- a/testdata/builtins.sky
+++ b/testdata/builtins.sky
@@ -129,10 +129,12 @@ assert.eq(enumerate([False, True, None], 42), [(42, False), (43, True), (44, Non
# zip
assert.eq(zip(), [])
+assert.eq(zip([]), [])
assert.eq(zip([1, 2, 3]), [(1,), (2,), (3,)])
-assert.eq(zip(list("abc".split_bytes()),
+assert.eq(zip("".split_bytes()), [])
+assert.eq(zip("abc".split_bytes(),
list("def".split_bytes()),
- list("hijk".split_bytes())),
+ "hijk".split_bytes()),
[("a", "d", "h"), ("b", "e", "i"), ("c", "f", "j")])
z1 = [1]
assert.eq(zip(z1), [(1,)])