mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 08:44:20 +03:00
Модуль functional с функциональными операторами для данных
This commit is contained in:
parent
1fd2dd8e87
commit
89d48f7737
@ -1,5 +1,7 @@
|
|||||||
use "math"
|
use "math"
|
||||||
use "std"
|
use "std"
|
||||||
|
use "functional"
|
||||||
|
|
||||||
word = 2 + 2
|
word = 2 + 2
|
||||||
word2 = PI + word
|
word2 = PI + word
|
||||||
str = "a" * 5 + "ba" * 7 + "\n"
|
str = "a" * 5 + "ba" * 7 + "\n"
|
||||||
@ -117,3 +119,9 @@ thread(::inthread)
|
|||||||
def inthread() = echo("this is a thread")
|
def inthread() = echo("this is a thread")
|
||||||
thread(def (str) { println str }, "this is a thread with arguments")
|
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;
|
return Types.ARRAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return elements.length;
|
||||||
|
}
|
||||||
|
|
||||||
public Value get(int index) {
|
public Value get(int index) {
|
||||||
return elements[index];
|
return elements[index];
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,10 @@ public class MapValue implements Value, Iterable<Map.Entry<Value, Value>> {
|
|||||||
return Types.MAP;
|
return Types.MAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return map.size();
|
||||||
|
}
|
||||||
|
|
||||||
public Value get(Value key) {
|
public Value get(Value key) {
|
||||||
return map.get(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
|
@Override
|
||||||
public void init() {
|
public void init() {
|
||||||
Functions.set("echo", new std_echo());
|
Functions.set("echo", new std_echo());
|
||||||
Functions.set("foreach", new std_foreach());
|
|
||||||
Functions.set("newarray", new std_newarray());
|
Functions.set("newarray", new std_newarray());
|
||||||
Functions.set("rand", new std_rand());
|
Functions.set("rand", new std_rand());
|
||||||
Functions.set("sleep", new std_sleep());
|
Functions.set("sleep", new std_sleep());
|
||||||
|
Loading…
Reference in New Issue
Block a user