mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Модуль functional с функциональными операторами для данных
This commit is contained in:
parent
1fd2dd8e87
commit
89d48f7737
@ -1,5 +1,7 @@
|
||||
use "math"
|
||||
use "std"
|
||||
use "functional"
|
||||
|
||||
word = 2 + 2
|
||||
word2 = PI + word
|
||||
str = "a" * 5 + "ba" * 7 + "\n"
|
||||
@ -117,3 +119,9 @@ thread(::inthread)
|
||||
def inthread() = echo("this is a thread")
|
||||
thread(def (str) { println str }, "this is a thread with arguments")
|
||||
|
||||
println "functional"
|
||||
nums = [1,2,3,4,5,6,7,8,9,10]
|
||||
nums = filter(nums, def(x) = x % 2 == 0)
|
||||
squares = map(nums, def(x) = x * x)
|
||||
foreach(squares, ::echo)
|
||||
println "Sum: " + reduce(squares, 0, def(x, y) = x + y)
|
@ -47,6 +47,10 @@ public final class ArrayValue implements Value, Iterable<Value> {
|
||||
return Types.ARRAY;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return elements.length;
|
||||
}
|
||||
|
||||
public Value get(int index) {
|
||||
return elements[index];
|
||||
}
|
||||
|
@ -26,6 +26,10 @@ public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> {
|
||||
return Types.MAP;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public Value get(Value key) {
|
||||
return map.get(key);
|
||||
}
|
||||
|
19
src/com/annimon/ownlang/lib/modules/functional.java
Normal file
19
src/com/annimon/ownlang/lib/modules/functional.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.annimon.ownlang.lib.modules;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import com.annimon.ownlang.lib.modules.functions.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class functional implements Module {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Functions.set("foreach", new functional_foreach());
|
||||
Functions.set("map", new functional_map());
|
||||
Functions.set("reduce", new functional_reduce());
|
||||
Functions.set("filter", new functional_filter());
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.annimon.ownlang.lib.modules.functions;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class functional_filter implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
if (args.length < 2) throw new RuntimeException("At least two args expected");
|
||||
|
||||
if (args[1].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in second arg");
|
||||
}
|
||||
final Value container = args[0];
|
||||
final Function consumer = ((FunctionValue) args[1]).getValue();
|
||||
if (container.type() == Types.ARRAY) {
|
||||
return filterArray((ArrayValue) container, consumer);
|
||||
}
|
||||
|
||||
if (container.type() == Types.MAP) {
|
||||
return filterMap((MapValue) container, consumer);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Invalid first argument. Array or map exprected");
|
||||
}
|
||||
|
||||
private Value filterArray(ArrayValue array, Function predicate) {
|
||||
final int size = array.size();
|
||||
final List<Value> values = new ArrayList<Value>(size);
|
||||
for (Value value : array) {
|
||||
if (predicate.execute(value) != NumberValue.ZERO) {
|
||||
values.add(value);
|
||||
}
|
||||
}
|
||||
final int newSize = values.size();
|
||||
return new ArrayValue(values.toArray(new Value[newSize]));
|
||||
}
|
||||
|
||||
private Value filterMap(MapValue map, Function predicate) {
|
||||
final MapValue result = new MapValue(map.size());
|
||||
for (Map.Entry<Value, Value> element : map) {
|
||||
if (predicate.execute(element.getKey(), element.getValue()) != NumberValue.ZERO) {
|
||||
result.set(element.getKey(), element.getValue());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package com.annimon.ownlang.lib.modules.functions;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class functional_foreach implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
if (args.length != 2) throw new RuntimeException("Two args expected");
|
||||
|
||||
if (args[1].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in second arg");
|
||||
}
|
||||
final Value container = args[0];
|
||||
final Function consumer = ((FunctionValue) args[1]).getValue();
|
||||
if (container.type() == Types.ARRAY) {
|
||||
final ArrayValue array = (ArrayValue) container;
|
||||
for (Value element : array) {
|
||||
consumer.execute(element);
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
if (container.type() == Types.MAP) {
|
||||
final MapValue map = (MapValue) container;
|
||||
for (Map.Entry<Value, Value> element : map) {
|
||||
consumer.execute(element.getKey(), element.getValue());
|
||||
}
|
||||
return NumberValue.ZERO;
|
||||
}
|
||||
throw new RuntimeException("Invalid first argument. Array or map exprected");
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package com.annimon.ownlang.lib.modules.functions;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class functional_map implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
if (args.length < 2) throw new RuntimeException("At least two args expected");
|
||||
|
||||
final Value container = args[0];
|
||||
if (container.type() == Types.ARRAY) {
|
||||
if (args[1].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in second arg");
|
||||
}
|
||||
final Function mapper = ((FunctionValue) args[1]).getValue();
|
||||
return mapArray((ArrayValue) container, mapper);
|
||||
}
|
||||
|
||||
if (container.type() == Types.MAP) {
|
||||
if (args[1].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in second arg");
|
||||
}
|
||||
if (args[2].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in third arg");
|
||||
}
|
||||
final Function keyMapper = ((FunctionValue) args[1]).getValue();
|
||||
final Function valueMapper = ((FunctionValue) args[2]).getValue();
|
||||
return mapMap((MapValue) container, keyMapper, valueMapper);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Invalid first argument. Array or map exprected");
|
||||
}
|
||||
|
||||
private Value mapArray(ArrayValue array, Function mapper) {
|
||||
final int size = array.size();
|
||||
final ArrayValue result = new ArrayValue(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
result.set(i, mapper.execute(array.get(i)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Value mapMap(MapValue map, Function keyMapper, Function valueMapper) {
|
||||
final MapValue result = new MapValue(map.size());
|
||||
for (Map.Entry<Value, Value> element : map) {
|
||||
final Value newKey = keyMapper.execute(element.getKey());
|
||||
final Value newValue = valueMapper.execute(element.getValue());
|
||||
result.set(newKey, newValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.annimon.ownlang.lib.modules.functions;
|
||||
|
||||
import com.annimon.ownlang.lib.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class functional_reduce implements Function {
|
||||
|
||||
@Override
|
||||
public Value execute(Value... args) {
|
||||
if (args.length != 3) throw new RuntimeException("Three args expected");
|
||||
|
||||
if (args[2].type() != Types.FUNCTION) {
|
||||
throw new RuntimeException("Function expected in third arg");
|
||||
}
|
||||
final Value container = args[0];
|
||||
final Value identity = args[1];
|
||||
final Function accumulator = ((FunctionValue) args[2]).getValue();
|
||||
if (container.type() == Types.ARRAY) {
|
||||
Value result = identity;
|
||||
final ArrayValue array = (ArrayValue) container;
|
||||
for (Value element : array) {
|
||||
result = accumulator.execute(result, element);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (container.type() == Types.MAP) {
|
||||
Value result = identity;
|
||||
final MapValue map = (MapValue) container;
|
||||
for (Map.Entry<Value, Value> element : map) {
|
||||
result = accumulator.execute(result, element.getKey(), element.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
throw new RuntimeException("Invalid first argument. Array or map exprected");
|
||||
}
|
||||
}
|
@ -12,7 +12,6 @@ public final class std implements Module {
|
||||
@Override
|
||||
public void init() {
|
||||
Functions.set("echo", new std_echo());
|
||||
Functions.set("foreach", new std_foreach());
|
||||
Functions.set("newarray", new std_newarray());
|
||||
Functions.set("rand", new std_rand());
|
||||
Functions.set("sleep", new std_sleep());
|
||||
|
Loading…
Reference in New Issue
Block a user