Skip to content

Commit 2de94d9

Browse files
committed
[functional] Unify functional operators
1 parent 110aa62 commit 2de94d9

File tree

9 files changed

+112
-88
lines changed

9 files changed

+112
-88
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ private void init() {
2020
set("map", wrapIntermediate(new functional_map()));
2121
set("flatMap", wrapIntermediate(new functional_flatmap()));
2222
set("sorted", this::sorted);
23-
set("sortBy", wrapIntermediate(new functional_sortby()));
23+
set("sortBy", wrapIntermediate(new functional_sortBy()));
2424
set("takeWhile", wrapIntermediate(new functional_takeWhile()));
25-
set("dropWhile", wrapIntermediate(new functional_dropwhile()));
26-
set("peek", wrapIntermediate(new functional_foreach()));
25+
set("dropWhile", wrapIntermediate(new functional_dropWhile()));
26+
set("peek", wrapIntermediate(new functional_forEach()));
2727
set("skip", this::skip);
2828
set("limit", this::limit);
2929
set("custom", this::custom);
3030

3131
set("reduce", wrapTerminal(new functional_reduce()));
32-
set("forEach", wrapTerminal(new functional_foreach()));
32+
set("forEach", wrapTerminal(new functional_forEach()));
3333
set("toArray", args -> container);
3434
set("joining", container::joinToString);
3535
set("count", args -> NumberValue.of(container.size()));

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ public Map<String, Value> constants() {
1919
@Override
2020
public Map<String, Function> functions() {
2121
final var result = new HashMap<String, Function>(15);
22-
result.put("foreach", new functional_foreach());
22+
result.put("foreach", new functional_forEach());
2323
result.put("map", new functional_map());
2424
result.put("flatmap", new functional_flatmap());
2525
result.put("reduce", new functional_reduce());
2626
result.put("filter", new functional_filter());
27-
result.put("sortby", new functional_sortby());
27+
result.put("sortby", new functional_sortBy());
2828
result.put("takewhile", new functional_takeWhile());
29-
result.put("dropwhile", new functional_dropwhile());
29+
result.put("dropwhile", new functional_dropWhile());
3030

3131
result.put("chain", new functional_chain());
3232
result.put("stream", new functional_stream());

modules/main/src/main/java/com/annimon/ownlang/modules/functional/functional_dropwhile.java renamed to modules/main/src/main/java/com/annimon/ownlang/modules/functional/functional_dropWhile.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@
99
import com.annimon.ownlang.lib.Value;
1010
import com.annimon.ownlang.lib.ValueUtils;
1111

12-
public final class functional_dropwhile implements Function {
12+
public final class functional_dropWhile implements Function {
1313

1414
@Override
1515
public Value execute(Value[] args) {
1616
Arguments.check(2, args.length);
17-
if (args[0].type() != Types.ARRAY) {
18-
throw new TypeException("Array expected in first argument");
19-
}
2017
final Value container = args[0];
2118
final Function predicate = ValueUtils.consumeFunction(args[1], 1);
22-
return dropWhileArray((ArrayValue) container, predicate);
19+
return dropWhile(container, predicate);
2320
}
2421

25-
private Value dropWhileArray(ArrayValue array, Function predicate) {
22+
static ArrayValue dropWhile(Value container, Function predicate) {
23+
if (container.type() != Types.ARRAY) {
24+
throw new TypeException("Array expected in first argument");
25+
}
26+
return dropWhileArray((ArrayValue) container, predicate);
27+
}
28+
29+
static ArrayValue dropWhileArray(ArrayValue array, Function predicate) {
2630
int skipCount = 0;
2731
for (Value value : array) {
2832
if (predicate.execute(value) != NumberValue.ZERO)

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,19 @@ public final class functional_flatmap implements Function {
1515
@Override
1616
public Value execute(Value[] args) {
1717
Arguments.check(2, args.length);
18-
if (args[0].type() != Types.ARRAY) {
18+
final Value container = args[0];
19+
final Function mapper = ValueUtils.consumeFunction(args[1], 1);
20+
return flatMap(container, mapper);
21+
}
22+
23+
static Value flatMap(Value container, Function mapper) {
24+
if (container.type() != Types.ARRAY) {
1925
throw new TypeException("Array expected in first argument");
2026
}
21-
final Function mapper = ValueUtils.consumeFunction(args[1], 1);
22-
return flatMapArray((ArrayValue) args[0], mapper);
27+
return flatMapArray((ArrayValue) container, mapper);
2328
}
24-
25-
private Value flatMapArray(ArrayValue array, Function mapper) {
29+
30+
static Value flatMapArray(ArrayValue array, Function mapper) {
2631
final List<Value> values = new ArrayList<>();
2732
final int size = array.size();
2833
for (int i = 0; i < size; i++) {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package com.annimon.ownlang.modules.functional;
2+
3+
import com.annimon.ownlang.exceptions.TypeException;
4+
import com.annimon.ownlang.lib.*;
5+
import java.util.Map;
6+
7+
public final class functional_forEach implements Function {
8+
9+
@Override
10+
public Value execute(Value[] args) {
11+
Arguments.check(2, args.length);
12+
final Value container = args[0];
13+
final Function consumer = ValueUtils.consumeFunction(args[1], 1);
14+
return forEach(container, consumer);
15+
}
16+
17+
static Value forEach(Value container, Function consumer) {
18+
final int argsCount = consumer.getArgsCount();
19+
return switch (container.type()) {
20+
case Types.STRING -> forEachString((StringValue) container, argsCount, consumer);
21+
case Types.ARRAY -> forEachArray((ArrayValue) container, argsCount, consumer);
22+
case Types.MAP -> forEachMap((MapValue) container, consumer);
23+
default -> throw new TypeException("Cannot iterate " + Types.typeToString(container.type()));
24+
};
25+
}
26+
27+
static StringValue forEachString(StringValue string, int argsCount, Function consumer) {
28+
if (argsCount == 2) {
29+
for (char ch : string.asString().toCharArray()) {
30+
consumer.execute(new StringValue(String.valueOf(ch)), NumberValue.of(ch));
31+
}
32+
} else {
33+
for (char ch : string.asString().toCharArray()) {
34+
consumer.execute(new StringValue(String.valueOf(ch)));
35+
}
36+
}
37+
return string;
38+
}
39+
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+
}
50+
}
51+
return array;
52+
}
53+
54+
static MapValue forEachMap(MapValue map, Function consumer) {
55+
for (Map.Entry<Value, Value> element : map) {
56+
consumer.execute(element.getKey(), element.getValue());
57+
}
58+
return map;
59+
}
60+
}

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

Lines changed: 0 additions & 55 deletions
This file was deleted.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public Value execute(Value[] args) {
3131
throw new TypeException("Invalid first argument. Array or map expected");
3232
}
3333

34-
private Value mapArray(ArrayValue array, Function mapper) {
34+
static ArrayValue mapArray(ArrayValue array, Function mapper) {
3535
final int size = array.size();
3636
final ArrayValue result = new ArrayValue(size);
3737
for (int i = 0; i < size; i++) {
@@ -40,7 +40,7 @@ private Value mapArray(ArrayValue array, Function mapper) {
4040
return result;
4141
}
4242

43-
private Value mapMap(MapValue map, Function keyMapper, Function valueMapper) {
43+
static MapValue mapMap(MapValue map, Function keyMapper, Function valueMapper) {
4444
final MapValue result = new MapValue(map.size());
4545
for (Map.Entry<Value, Value> element : map) {
4646
final Value newKey = keyMapper.execute(element.getKey());

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

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,32 @@ public Value execute(Value[] args) {
1919
final Value container = args[0];
2020
final Value identity = args[1];
2121
final Function accumulator = ValueUtils.consumeFunction(args[2], 2);
22+
return reduce(container, identity, accumulator);
23+
}
24+
25+
static Value reduce(Value container, Value identity, Function accumulator) {
2226
if (container.type() == Types.ARRAY) {
23-
Value result = identity;
24-
final ArrayValue array = (ArrayValue) container;
25-
for (Value element : array) {
26-
result = accumulator.execute(result, element);
27-
}
28-
return result;
27+
return reduceArray(identity, (ArrayValue) container, accumulator);
2928
}
3029
if (container.type() == Types.MAP) {
31-
Value result = identity;
32-
final MapValue map = (MapValue) container;
33-
for (Map.Entry<Value, Value> element : map) {
34-
result = accumulator.execute(result, element.getKey(), element.getValue());
35-
}
36-
return result;
30+
return reduceMap(identity, (MapValue) container, accumulator);
3731
}
3832
throw new TypeException("Invalid first argument. Array or map expected");
3933
}
34+
35+
static Value reduceArray(Value identity, ArrayValue array, Function accumulator) {
36+
Value result = identity;
37+
for (Value element : array) {
38+
result = accumulator.execute(result, element);
39+
}
40+
return result;
41+
}
42+
43+
static Value reduceMap(Value identity, MapValue map, Function accumulator) {
44+
Value result = identity;
45+
for (Map.Entry<Value, Value> element : map) {
46+
result = accumulator.execute(result, element.getKey(), element.getValue());
47+
}
48+
return result;
49+
}
4050
}

modules/main/src/main/java/com/annimon/ownlang/modules/functional/functional_sortby.java renamed to modules/main/src/main/java/com/annimon/ownlang/modules/functional/functional_sortBy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import java.util.Arrays;
1111
import java.util.Comparator;
1212

13-
public final class functional_sortby implements Function {
13+
public final class functional_sortBy implements Function {
1414

1515
@Override
1616
public Value execute(Value[] args) {

0 commit comments

Comments
 (0)