Skip to content

Commit 89d48f7

Browse files
committed
Модуль functional с функциональными операторами для данных
1 parent 1fd2dd8 commit 89d48f7

File tree

9 files changed

+213
-1
lines changed

9 files changed

+213
-1
lines changed

program.own

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use "math"
22
use "std"
3+
use "functional"
4+
35
word = 2 + 2
46
word2 = PI + word
57
str = "a" * 5 + "ba" * 7 + "\n"
@@ -117,3 +119,9 @@ thread(::inthread)
117119
def inthread() = echo("this is a thread")
118120
thread(def (str) { println str }, "this is a thread with arguments")
119121

122+
println "functional"
123+
nums = [1,2,3,4,5,6,7,8,9,10]
124+
nums = filter(nums, def(x) = x % 2 == 0)
125+
squares = map(nums, def(x) = x * x)
126+
foreach(squares, ::echo)
127+
println "Sum: " + reduce(squares, 0, def(x, y) = x + y)

src/com/annimon/ownlang/lib/ArrayValue.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ public int type() {
4747
return Types.ARRAY;
4848
}
4949

50+
public int size() {
51+
return elements.length;
52+
}
53+
5054
public Value get(int index) {
5155
return elements[index];
5256
}

src/com/annimon/ownlang/lib/MapValue.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ public MapValue(Map<Value, Value> map) {
2525
public int type() {
2626
return Types.MAP;
2727
}
28+
29+
public int size() {
30+
return map.size();
31+
}
2832

2933
public Value get(Value key) {
3034
return map.get(key);
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.annimon.ownlang.lib.modules;
2+
3+
import com.annimon.ownlang.lib.*;
4+
import com.annimon.ownlang.lib.modules.functions.*;
5+
6+
/**
7+
*
8+
* @author aNNiMON
9+
*/
10+
public final class functional implements Module {
11+
12+
@Override
13+
public void init() {
14+
Functions.set("foreach", new functional_foreach());
15+
Functions.set("map", new functional_map());
16+
Functions.set("reduce", new functional_reduce());
17+
Functions.set("filter", new functional_filter());
18+
}
19+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.annimon.ownlang.lib.modules.functions;
2+
3+
import com.annimon.ownlang.lib.*;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
7+
import java.util.Map;
8+
9+
public final class functional_filter implements Function {
10+
11+
@Override
12+
public Value execute(Value... args) {
13+
if (args.length < 2) throw new RuntimeException("At least two args expected");
14+
15+
if (args[1].type() != Types.FUNCTION) {
16+
throw new RuntimeException("Function expected in second arg");
17+
}
18+
final Value container = args[0];
19+
final Function consumer = ((FunctionValue) args[1]).getValue();
20+
if (container.type() == Types.ARRAY) {
21+
return filterArray((ArrayValue) container, consumer);
22+
}
23+
24+
if (container.type() == Types.MAP) {
25+
return filterMap((MapValue) container, consumer);
26+
}
27+
28+
throw new RuntimeException("Invalid first argument. Array or map exprected");
29+
}
30+
31+
private Value filterArray(ArrayValue array, Function predicate) {
32+
final int size = array.size();
33+
final List<Value> values = new ArrayList<Value>(size);
34+
for (Value value : array) {
35+
if (predicate.execute(value) != NumberValue.ZERO) {
36+
values.add(value);
37+
}
38+
}
39+
final int newSize = values.size();
40+
return new ArrayValue(values.toArray(new Value[newSize]));
41+
}
42+
43+
private Value filterMap(MapValue map, Function predicate) {
44+
final MapValue result = new MapValue(map.size());
45+
for (Map.Entry<Value, Value> element : map) {
46+
if (predicate.execute(element.getKey(), element.getValue()) != NumberValue.ZERO) {
47+
result.set(element.getKey(), element.getValue());
48+
}
49+
}
50+
return result;
51+
}
52+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.annimon.ownlang.lib.modules.functions;
2+
3+
import com.annimon.ownlang.lib.*;
4+
5+
import java.util.Map;
6+
7+
public final class functional_foreach implements Function {
8+
9+
@Override
10+
public Value execute(Value... args) {
11+
if (args.length != 2) throw new RuntimeException("Two args expected");
12+
13+
if (args[1].type() != Types.FUNCTION) {
14+
throw new RuntimeException("Function expected in second arg");
15+
}
16+
final Value container = args[0];
17+
final Function consumer = ((FunctionValue) args[1]).getValue();
18+
if (container.type() == Types.ARRAY) {
19+
final ArrayValue array = (ArrayValue) container;
20+
for (Value element : array) {
21+
consumer.execute(element);
22+
}
23+
return NumberValue.ZERO;
24+
}
25+
if (container.type() == Types.MAP) {
26+
final MapValue map = (MapValue) container;
27+
for (Map.Entry<Value, Value> element : map) {
28+
consumer.execute(element.getKey(), element.getValue());
29+
}
30+
return NumberValue.ZERO;
31+
}
32+
throw new RuntimeException("Invalid first argument. Array or map exprected");
33+
}
34+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.annimon.ownlang.lib.modules.functions;
2+
3+
import com.annimon.ownlang.lib.*;
4+
5+
import java.util.Map;
6+
7+
public final class functional_map implements Function {
8+
9+
@Override
10+
public Value execute(Value... args) {
11+
if (args.length < 2) throw new RuntimeException("At least two args expected");
12+
13+
final Value container = args[0];
14+
if (container.type() == Types.ARRAY) {
15+
if (args[1].type() != Types.FUNCTION) {
16+
throw new RuntimeException("Function expected in second arg");
17+
}
18+
final Function mapper = ((FunctionValue) args[1]).getValue();
19+
return mapArray((ArrayValue) container, mapper);
20+
}
21+
22+
if (container.type() == Types.MAP) {
23+
if (args[1].type() != Types.FUNCTION) {
24+
throw new RuntimeException("Function expected in second arg");
25+
}
26+
if (args[2].type() != Types.FUNCTION) {
27+
throw new RuntimeException("Function expected in third arg");
28+
}
29+
final Function keyMapper = ((FunctionValue) args[1]).getValue();
30+
final Function valueMapper = ((FunctionValue) args[2]).getValue();
31+
return mapMap((MapValue) container, keyMapper, valueMapper);
32+
}
33+
34+
throw new RuntimeException("Invalid first argument. Array or map exprected");
35+
}
36+
37+
private Value mapArray(ArrayValue array, Function mapper) {
38+
final int size = array.size();
39+
final ArrayValue result = new ArrayValue(size);
40+
for (int i = 0; i < size; i++) {
41+
result.set(i, mapper.execute(array.get(i)));
42+
}
43+
return result;
44+
}
45+
46+
private Value mapMap(MapValue map, Function keyMapper, Function valueMapper) {
47+
final MapValue result = new MapValue(map.size());
48+
for (Map.Entry<Value, Value> element : map) {
49+
final Value newKey = keyMapper.execute(element.getKey());
50+
final Value newValue = valueMapper.execute(element.getValue());
51+
result.set(newKey, newValue);
52+
}
53+
return result;
54+
}
55+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.annimon.ownlang.lib.modules.functions;
2+
3+
import com.annimon.ownlang.lib.*;
4+
5+
import java.util.Map;
6+
7+
public final class functional_reduce implements Function {
8+
9+
@Override
10+
public Value execute(Value... args) {
11+
if (args.length != 3) throw new RuntimeException("Three args expected");
12+
13+
if (args[2].type() != Types.FUNCTION) {
14+
throw new RuntimeException("Function expected in third arg");
15+
}
16+
final Value container = args[0];
17+
final Value identity = args[1];
18+
final Function accumulator = ((FunctionValue) args[2]).getValue();
19+
if (container.type() == Types.ARRAY) {
20+
Value result = identity;
21+
final ArrayValue array = (ArrayValue) container;
22+
for (Value element : array) {
23+
result = accumulator.execute(result, element);
24+
}
25+
return result;
26+
}
27+
if (container.type() == Types.MAP) {
28+
Value result = identity;
29+
final MapValue map = (MapValue) container;
30+
for (Map.Entry<Value, Value> element : map) {
31+
result = accumulator.execute(result, element.getKey(), element.getValue());
32+
}
33+
return result;
34+
}
35+
throw new RuntimeException("Invalid first argument. Array or map exprected");
36+
}
37+
}

src/com/annimon/ownlang/lib/modules/std.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public final class std implements Module {
1212
@Override
1313
public void init() {
1414
Functions.set("echo", new std_echo());
15-
Functions.set("foreach", new std_foreach());
1615
Functions.set("newarray", new std_newarray());
1716
Functions.set("rand", new std_rand());
1817
Functions.set("sleep", new std_sleep());

0 commit comments

Comments
 (0)