diff --git a/program.own b/program.own index bc1bbb5..f62f0e9 100644 --- a/program.own +++ b/program.own @@ -126,6 +126,11 @@ squares = map(nums, def(x) = x * x) foreach(squares, ::echo) println "Sum: " + reduce(squares, 0, def(x, y) = x + y) +nums = [[1, 2], [3], [], [4, 5]] +nums = flatmap(nums, IDENTITY) +println "flatmap" +foreach(nums, ::echo) + use "http" /*http("http://jsonplaceholder.typicode.com/users", "POST", {"name": "OwnLang", "versionCode": 10}, def(v) { @@ -164,4 +169,13 @@ def fact2(n) = match n { } println fact1(6) -println fact2(6) \ No newline at end of file +println fact2(6) + +class = { + "add": def(a, b) = a + b, + "sub": def(a, b) = a - b, + "mul": def(a, b) = a * b, + "div": def(a, b) = a / b +} + +println class.add(2, class.mul(2, 2)) \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/ArrayValue.java b/src/com/annimon/ownlang/lib/ArrayValue.java index fb28e8c..4183c50 100644 --- a/src/com/annimon/ownlang/lib/ArrayValue.java +++ b/src/com/annimon/ownlang/lib/ArrayValue.java @@ -3,6 +3,7 @@ package com.annimon.ownlang.lib; import com.annimon.ownlang.exceptions.TypeException; import java.util.Arrays; import java.util.Iterator; +import java.util.List; /** * @@ -39,6 +40,11 @@ public final class ArrayValue implements Value, Iterable { System.arraycopy(elements, 0, this.elements, 0, elements.length); } + public ArrayValue(List values) { + final int size = values.size(); + this.elements = values.toArray(new Value[size]); + } + public ArrayValue(ArrayValue array) { this(array.elements); } diff --git a/src/com/annimon/ownlang/lib/modules/functional.java b/src/com/annimon/ownlang/lib/modules/functional.java index e5bc229..8d3126c 100644 --- a/src/com/annimon/ownlang/lib/modules/functional.java +++ b/src/com/annimon/ownlang/lib/modules/functional.java @@ -13,7 +13,12 @@ public final class functional implements Module { public void init() { Functions.set("foreach", new functional_foreach()); Functions.set("map", new functional_map()); + Functions.set("flatmap", new functional_flatmap()); Functions.set("reduce", new functional_reduce()); Functions.set("filter", new functional_filter()); + + Functions.set("combine", new functional_combine()); + + Variables.set("IDENTITY", new FunctionValue(args -> args[0])); } } diff --git a/src/com/annimon/ownlang/lib/modules/functions/functional_combine.java b/src/com/annimon/ownlang/lib/modules/functions/functional_combine.java index 980106c..1d127df 100644 --- a/src/com/annimon/ownlang/lib/modules/functions/functional_combine.java +++ b/src/com/annimon/ownlang/lib/modules/functions/functional_combine.java @@ -1,55 +1,29 @@ package com.annimon.ownlang.lib.modules.functions; +import com.annimon.ownlang.exceptions.ArgumentsMismatchException; +import com.annimon.ownlang.exceptions.TypeException; import com.annimon.ownlang.lib.*; -import java.util.Map; - -public final class functional_map implements Function { +public final class functional_combine implements Function { @Override public Value execute(Value... args) { - if (args.length < 2) throw new RuntimeException("At least two args expected"); + if (args.length < 1) throw new ArgumentsMismatchException("At least one arg 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"); + Function result = null; + for (Value arg : args) { + if (arg.type() != Types.FUNCTION) { + throw new TypeException(arg.toString() + " is not a function"); } - final Function mapper = ((FunctionValue) args[1]).getValue(); - return mapArray((ArrayValue) container, mapper); + final Function current = result; + final Function next = ((FunctionValue) arg).getValue(); + result = fArgs -> { + if (current == null) return next.execute(fArgs); + return next.execute(current.execute(fArgs)); + }; } - 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"); + return new FunctionValue(result); } - 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 element : map) { - final Value newKey = keyMapper.execute(element.getKey()); - final Value newValue = valueMapper.execute(element.getValue()); - result.set(newKey, newValue); - } - return result; - } } \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/functions/functional_flatmap.java b/src/com/annimon/ownlang/lib/modules/functions/functional_flatmap.java new file mode 100644 index 0000000..c933892 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/functions/functional_flatmap.java @@ -0,0 +1,40 @@ +package com.annimon.ownlang.lib.modules.functions; + +import com.annimon.ownlang.exceptions.ArgumentsMismatchException; +import com.annimon.ownlang.exceptions.TypeException; +import com.annimon.ownlang.lib.*; +import java.util.ArrayList; +import java.util.List; + +public final class functional_flatmap implements Function { + + @Override + public Value execute(Value... args) { + if (args.length < 2) throw new ArgumentsMismatchException("At least two arguments expected"); + + if (args[0].type() != Types.ARRAY) { + throw new TypeException("Array expected in first argument"); + } + if (args[1].type() != Types.FUNCTION) { + throw new TypeException("Function expected in second argument"); + } + + final Function mapper = ((FunctionValue) args[1]).getValue(); + return flatMapArray((ArrayValue) args[0], mapper); + } + + private Value flatMapArray(ArrayValue array, Function mapper) { + final List values = new ArrayList<>(); + final int size = array.size(); + for (int i = 0; i < size; i++) { + final Value inner = mapper.execute(array.get(i)); + if (inner.type() != Types.ARRAY) { + throw new TypeException("Array expected " + inner); + } + for (Value value : (ArrayValue) inner) { + values.add(value); + } + } + return new ArrayValue(values); + } +} \ No newline at end of file