summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/src/reference/types.md10
-rw-r--r--src/eval/array.rs12
-rw-r--r--src/eval/methods.rs2
-rw-r--r--tests/typ/compiler/array.typ11
4 files changed, 35 insertions, 0 deletions
diff --git a/docs/src/reference/types.md b/docs/src/reference/types.md
index 24756422..1bae6b75 100644
--- a/docs/src/reference/types.md
+++ b/docs/src/reference/types.md
@@ -620,6 +620,16 @@ for loop.
- returns: array
+### zip()
+Zips the array with another array. If the two arrays are of unequal length, it
+will only zip up until the last element of the smaller array and the remaining
+elements will be ignored. The return value is an array where each element is yet
+another array of size 2.
+
+- other: array (positional, required)
+ The other array which should be zipped with the current one.
+- returns: array
+
### fold()
Folds all items into a single value using an accumulator function.
diff --git a/src/eval/array.rs b/src/eval/array.rs
index 1166ce94..f6e2f2d4 100644
--- a/src/eval/array.rs
+++ b/src/eval/array.rs
@@ -306,6 +306,18 @@ impl Array {
Ok(result)
}
+ /// Zips the array with another array. If the two arrays are of unequal length, it will only
+ /// zip up until the last element of the smaller array and the remaining elements will be
+ /// ignored. The return value is an array where each element is yet another array of size 2.
+ pub fn zip(&self, other: Array) -> Array {
+ self.iter()
+ .zip(other)
+ .map(|(first, second)| {
+ Value::Array(Array::from_vec(eco_vec![first.clone(), second]))
+ })
+ .collect()
+ }
+
/// Return a sorted version of this array, optionally by a given key function.
///
/// Returns an error if two values could not be compared or if the key function (if given)
diff --git a/src/eval/methods.rs b/src/eval/methods.rs
index 29b729cb..3ee4599c 100644
--- a/src/eval/methods.rs
+++ b/src/eval/methods.rs
@@ -118,6 +118,7 @@ pub fn call(
array.join(sep, last).at(span)?
}
"sorted" => Value::Array(array.sorted(vm, span, args.named("key")?)?),
+ "zip" => Value::Array(array.zip(args.expect("other")?)),
"enumerate" => Value::Array(array.enumerate()),
_ => return missing(),
},
@@ -319,6 +320,7 @@ pub fn methods_on(type_name: &str) -> &[(&'static str, bool)] {
("slice", true),
("sorted", false),
("enumerate", false),
+ ("zip", true),
],
"dictionary" => &[
("at", true),
diff --git a/tests/typ/compiler/array.typ b/tests/typ/compiler/array.typ
index c52160b0..5d7e8b63 100644
--- a/tests/typ/compiler/array.typ
+++ b/tests/typ/compiler/array.typ
@@ -224,6 +224,17 @@
#test((2, 1, 3, -10, -5, 8, 6, -7, 2).sorted(key: x => x * x), (1, 2, 2, 3, -5, 6, -7, 8, -10))
---
+// Test the `zip` method.
+#test(().zip(()), ())
+#test((1,).zip(()), ())
+#test((1,).zip((2,)), ((1, 2),))
+#test((1, 2).zip((3, 4)), ((1, 3), (2, 4)))
+#test((1, 2, 3, 4).zip((5, 6)), ((1, 5), (2, 6)))
+#test(((1, 2), 3).zip((4, 5)), (((1, 2), 4), (3, 5)))
+#test((1, "hi").zip((true, false)), ((1, true), ("hi", false)))
+
+
+---
// Error: 32-37 cannot divide by zero
#(1, 2, 0, 3).sorted(key: x => 5 / x)