Skip to content

Commit 2bb5e45

Browse files
committed
[functional] Move indexed variant of Stream.forEach to Stream,forEachIndexed
1 parent d643f59 commit 2bb5e45

File tree

5 files changed

+62
-24
lines changed

5 files changed

+62
-24
lines changed

modules/main/src/main/java/com/annimon/ownlang/modules/functional/StreamValue.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ private void init() {
3030

3131
set("reduce", wrapTerminal(new functional_reduce()));
3232
set("forEach", wrapTerminal(new functional_forEach()));
33+
set("forEachIndexed", wrapTerminal(new functional_forEachIndexed()));
3334
set("toArray", args -> container);
3435
set("joining", container::joinToString);
3536
set("count", args -> NumberValue.of(container.size()));

modules/main/src/main/java/com/annimon/ownlang/modules/functional/functional_forEach.java

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,16 @@ public Value execute(Value[] args) {
1515
}
1616

1717
static Value forEach(Value container, Function consumer) {
18-
final int argsCount = consumer.getArgsCount();
1918
return switch (container.type()) {
20-
case Types.STRING -> forEachString((StringValue) container, argsCount, consumer);
21-
case Types.ARRAY -> forEachArray((ArrayValue) container, argsCount, consumer);
19+
case Types.STRING -> forEachString((StringValue) container, consumer);
20+
case Types.ARRAY -> forEachArray((ArrayValue) container, consumer);
2221
case Types.MAP -> forEachMap((MapValue) container, consumer);
2322
default -> throw new TypeException("Cannot iterate " + Types.typeToString(container.type()));
2423
};
2524
}
2625

27-
static StringValue forEachString(StringValue string, int argsCount, Function consumer) {
28-
if (argsCount == 2) {
26+
static StringValue forEachString(StringValue string, Function consumer) {
27+
if (consumer.getArgsCount() == 2) {
2928
for (char ch : string.asString().toCharArray()) {
3029
consumer.execute(new StringValue(String.valueOf(ch)), NumberValue.of(ch));
3130
}
@@ -37,16 +36,9 @@ static StringValue forEachString(StringValue string, int argsCount, Function con
3736
return string;
3837
}
3938

40-
static ArrayValue forEachArray(ArrayValue array, int argsCount, Function consumer) {
41-
if (argsCount == 2) {
42-
int index = 0;
43-
for (Value element : array) {
44-
consumer.execute(element, NumberValue.of(index++));
45-
}
46-
} else {
47-
for (Value element : array) {
48-
consumer.execute(element);
49-
}
39+
static ArrayValue forEachArray(ArrayValue array, Function consumer) {
40+
for (Value element : array) {
41+
consumer.execute(element);
5042
}
5143
return array;
5244
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.annimon.ownlang.modules.functional;
2+
3+
import com.annimon.ownlang.exceptions.TypeException;
4+
import com.annimon.ownlang.lib.*;
5+
6+
public final class functional_forEachIndexed implements Function {
7+
8+
@Override
9+
public Value execute(Value[] args) {
10+
Arguments.check(2, args.length);
11+
final Value container = args[0];
12+
final Function consumer = ValueUtils.consumeFunction(args[1], 1);
13+
return forEachIndexed(container, consumer);
14+
}
15+
16+
static Value forEachIndexed(Value container, Function consumer) {
17+
if (container.type() == Types.ARRAY) {
18+
return forEachIndexedArray((ArrayValue) container, consumer);
19+
}
20+
// Only used in Streams -> no Map implementation
21+
throw new TypeException("Cannot iterate " + Types.typeToString(container.type()));
22+
}
23+
24+
static ArrayValue forEachIndexedArray(ArrayValue array, Function consumer) {
25+
int index = 0;
26+
for (Value element : array) {
27+
consumer.execute(element, NumberValue.of(index++));
28+
}
29+
return array;
30+
}
31+
}

ownlang-parser/src/test/resources/modules/functional/foreach.own

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
use std, functional
22

3-
def testArrayForeach1Arg() {
3+
def testArrayForeachArg() {
44
sum = 0
55
foreach([1, 2, 3], def(v) {
66
sum += v
77
})
88
assertEquals(6, sum)
99
}
1010

11-
def testArrayForeach2Args() {
12-
sum = 0
13-
foreach([1, 2, 3], def(v, index) {
14-
sum += v * index
15-
})
16-
assertEquals(1 * 0 + 2 * 1 + 3 * 2, sum)
17-
}
18-
1911
def testStringForeach1Arg() {
2012
sum = 0
2113
foreach("abcd", def(s) {

ownlang-parser/src/test/resources/modules/functional/stream.own

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,28 @@ def testSorted() {
7979
assertEquals([-2,3,4,-5,6,6,-8], stream(data).sorted(def(a,b) = abs(a) - abs(b)).toArray())
8080
}
8181

82+
def testForEachArrayIndexed() {
83+
data = [1, 2, 3]
84+
sum = 0
85+
stream(data)
86+
.forEachIndexed(def(v, index) {
87+
sum += (v * index)
88+
})
89+
assertEquals(1 * 0 + 2 * 1 + 3 * 2, sum)
90+
}
91+
92+
def testForEachMapIndexed() {
93+
data = {"a": "1", "b": 2}
94+
result = ""
95+
stream(data)
96+
.sorted()
97+
.forEachIndexed(def(entry, index) {
98+
extract(key, value) = entry
99+
result += "" + key + value + index
100+
})
101+
assertEquals("a10b21", result)
102+
}
103+
82104
def reverse(container) {
83105
size = length(container)
84106
result = newarray(size)

0 commit comments

Comments
 (0)