Skip to content

Commit 6ecd696

Browse files
committed
Add zip function to standard library (#127)
1 parent 4bcc40a commit 6ecd696

File tree

6 files changed

+131
-0
lines changed

6 files changed

+131
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Version ?????? (??????????)
88
* added tuple to smooth language
99
* extended smooth syntax: Allow omitting parentheses in function type when it has one parameter
1010
* added standard library function `fold`
11+
* added standard library function `zip`
1112

1213
Version 0.23.0 (2025.03.20)
1314
---------------------------

doc/api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
| [toBlob](api/toBlob.md) | Converts String to Blob using UTF-8 encoding. |
2929
| [toString](api/toString.md) | Converts Blob to String using UTF-8 encoding. |
3030
| [unjar](api/unjar.md) | Unjars (uncompresses) files from given jar file. |
31+
| [zip](api/zip.md) | Combines two arrays into a single array of tuples. |
3132

3233
| value | definition |
3334
|-------|----------------------------|

doc/api/zip.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
## [{A,B}] zip<A,B>([A] first, [B] second)
2+
3+
Combines two arrays into a single array of tuples, where each tuple contains elements from both arrays at the same position.
4+
5+
| Name | Type | Default | Description |
6+
|--------|------|---------|--------------------------------------------|
7+
| first | [A] | | First array to be zipped. |
8+
| second | [B] | | Second array to be zipped. |
9+
10+
Returns __[{A,B}]__ array of tuples where each tuple contains elements from both arrays at the same position. The length of the result array is equal to the minimum length of the input arrays.
11+
12+
### examples
13+
14+
Zipping two arrays of different types:
15+
```
16+
[{String,Int}] zipped = zip(["a", "b", "c"], [1, 2, 3]);
17+
// Result: [{"a", 1}, {"b", 2}, {"c", 3}]
18+
```
19+
20+
Zipping arrays of different lengths (the shorter array determines the result length):
21+
```
22+
[{String,Int}] zipped = zip(["a", "b"], [1, 2, 3, 4]);
23+
// Result: [{"a", 1}, {"b", 2}]
24+
```
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package org.smoothbuild.stdlib.array;
2+
3+
import static org.smoothbuild.common.collect.List.list;
4+
5+
import org.smoothbuild.virtualmachine.bytecode.BytecodeException;
6+
import org.smoothbuild.virtualmachine.bytecode.expr.base.BArray;
7+
import org.smoothbuild.virtualmachine.bytecode.expr.base.BTuple;
8+
import org.smoothbuild.virtualmachine.bytecode.expr.base.BValue;
9+
import org.smoothbuild.virtualmachine.evaluate.plugin.NativeApi;
10+
11+
public class ZipFunc {
12+
public static BValue func(NativeApi nativeApi, BTuple args) throws BytecodeException {
13+
BArray firstArray = (BArray) args.get(0);
14+
BArray secondArray = (BArray) args.get(1);
15+
16+
var factory = nativeApi.factory();
17+
var firstElementType = firstArray.evaluationType().element();
18+
var secondElementType = secondArray.evaluationType().element();
19+
20+
// Create a tuple type for the result elements
21+
var tupleType = factory.tupleType(firstElementType, secondElementType);
22+
23+
// Create an array builder for the result
24+
var arrayType = factory.arrayType(tupleType);
25+
var resultBuilder = factory.arrayBuilder(arrayType);
26+
27+
// Get the elements from both arrays
28+
var firstElements = firstArray.elements(BValue.class);
29+
var secondElements = secondArray.elements(BValue.class);
30+
31+
// Determine the minimum size of the two arrays
32+
long minSize = Math.min(firstArray.size(), secondArray.size());
33+
34+
// Zip the elements together
35+
for (int i = 0; i < minSize; i++) {
36+
BValue firstElement = firstElements.get(i);
37+
BValue secondElement = secondElements.get(i);
38+
39+
// Create a tuple for each pair of elements
40+
BTuple tuple = factory.tuple(list(firstElement, secondElement));
41+
42+
// Add the tuple to the result array
43+
resultBuilder.add(tuple);
44+
}
45+
46+
return resultBuilder.build();
47+
}
48+
}

src/standard-library/src/main/smooth/std_lib.smooth

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ A if<A>(Bool condition, A then, A else);
9393
@Bytecode("org.smoothbuild.stdlib.core.MapFunc")
9494
[R] map<S,R>([S] array, (S)->R mapper);
9595

96+
@Native("org.smoothbuild.stdlib.array.ZipFunc")
97+
[{A,B}] zip<A,B>([A] first, [B] second);
98+
9699
@Bytecode("org.smoothbuild.stdlib.core.FoldFunc")
97100
A fold<A,E>([E] array, A initial, (A,E)->A folder);
98101

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.smoothbuild.stdlib.array;
2+
3+
import static com.google.common.truth.Truth.assertThat;
4+
5+
import org.junit.jupiter.api.Test;
6+
import org.smoothbuild.stdlib.StandardLibraryTestContext;
7+
8+
public class ZipTest extends StandardLibraryTestContext {
9+
@Test
10+
void zip_empty_arrays() throws Exception {
11+
var userModule = """
12+
[{Int,String}] result = zip([], []);
13+
""";
14+
createUserModule(userModule);
15+
evaluate("result");
16+
assertThat(artifact()).isEqualTo(bArray(bTupleType(bIntType(), bStringType())));
17+
}
18+
19+
@Test
20+
void zip_arrays_of_same_length() throws Exception {
21+
var userModule = """
22+
result = zip([1, 2, 3], ["a", "b", "c"]);
23+
""";
24+
createUserModule(userModule);
25+
evaluate("result");
26+
assertThat(artifact())
27+
.isEqualTo(bArray(
28+
bTuple(bInt(1), bString("a")),
29+
bTuple(bInt(2), bString("b")),
30+
bTuple(bInt(3), bString("c"))));
31+
}
32+
33+
@Test
34+
void zip_first_array_shorter() throws Exception {
35+
var userModule = """
36+
result = zip([1, 2], ["a", "b", "c"]);
37+
""";
38+
createUserModule(userModule);
39+
evaluate("result");
40+
assertThat(artifact())
41+
.isEqualTo(bArray(bTuple(bInt(1), bString("a")), bTuple(bInt(2), bString("b"))));
42+
}
43+
44+
@Test
45+
void zip_second_array_shorter() throws Exception {
46+
var userModule = """
47+
result = zip([1, 2, 3], ["a", "b"]);
48+
""";
49+
createUserModule(userModule);
50+
evaluate("result");
51+
assertThat(artifact())
52+
.isEqualTo(bArray(bTuple(bInt(1), bString("a")), bTuple(bInt(2), bString("b"))));
53+
}
54+
}

0 commit comments

Comments
 (0)