diff --git a/program.own b/program.own index f62f0e9..11aafe2 100644 --- a/program.own +++ b/program.own @@ -130,6 +130,8 @@ nums = [[1, 2], [3], [], [4, 5]] nums = flatmap(nums, IDENTITY) println "flatmap" foreach(nums, ::echo) +println "sort" +foreach(sort(nums, def(a,b) = b - a), ::echo) use "http" diff --git a/src/com/annimon/ownlang/lib/ArrayValue.java b/src/com/annimon/ownlang/lib/ArrayValue.java index 4183c50..ad593d0 100644 --- a/src/com/annimon/ownlang/lib/ArrayValue.java +++ b/src/com/annimon/ownlang/lib/ArrayValue.java @@ -48,6 +48,12 @@ public final class ArrayValue implements Value, Iterable { public ArrayValue(ArrayValue array) { this(array.elements); } + + public Value[] getCopyElements() { + final Value[] result = new Value[elements.length]; + System.arraycopy(elements, 0, result, 0, elements.length); + return result; + } @Override public int type() { @@ -97,6 +103,15 @@ public final class ArrayValue implements Value, Iterable { final ArrayValue other = (ArrayValue) obj; return Arrays.deepEquals(this.elements, other.elements); } + + @Override + public int compareTo(Value o) { + if (o.type() == Types.ARRAY) { + final int lengthCompare = Integer.compare(size(), ((ArrayValue) o).size()); + if (lengthCompare != 0) return lengthCompare; + } + return asString().compareTo(o.asString()); + } @Override public String toString() { diff --git a/src/com/annimon/ownlang/lib/FunctionValue.java b/src/com/annimon/ownlang/lib/FunctionValue.java index 8ef1aa0..1896795 100644 --- a/src/com/annimon/ownlang/lib/FunctionValue.java +++ b/src/com/annimon/ownlang/lib/FunctionValue.java @@ -53,6 +53,11 @@ public final class FunctionValue implements Value { return Objects.equals(this.value, other.value); } + @Override + public int compareTo(Value o) { + return asString().compareTo(o.asString()); + } + @Override public String toString() { return asString(); diff --git a/src/com/annimon/ownlang/lib/MapValue.java b/src/com/annimon/ownlang/lib/MapValue.java index 369102d..d8cc3b9 100644 --- a/src/com/annimon/ownlang/lib/MapValue.java +++ b/src/com/annimon/ownlang/lib/MapValue.java @@ -77,6 +77,15 @@ public class MapValue implements Value, Iterable> { return Objects.equals(this.map, other.map); } + @Override + public int compareTo(Value o) { + if (o.type() == Types.MAP) { + final int lengthCompare = Integer.compare(size(), ((MapValue) o).size()); + if (lengthCompare != 0) return lengthCompare; + } + return asString().compareTo(o.asString()); + } + @Override public String toString() { return asString(); diff --git a/src/com/annimon/ownlang/lib/NumberValue.java b/src/com/annimon/ownlang/lib/NumberValue.java index 5744790..3f43f76 100644 --- a/src/com/annimon/ownlang/lib/NumberValue.java +++ b/src/com/annimon/ownlang/lib/NumberValue.java @@ -51,7 +51,13 @@ public final class NumberValue implements Value { return Double.doubleToLongBits(this.value) == Double.doubleToLongBits(other.value); } - + @Override + public int compareTo(Value o) { + if (o.type() == Types.NUMBER) { + return Double.compare(value, ((NumberValue)o).value); + } + return asString().compareTo(o.asString()); + } @Override public String toString() { diff --git a/src/com/annimon/ownlang/lib/StringValue.java b/src/com/annimon/ownlang/lib/StringValue.java index f38206f..39d83e1 100644 --- a/src/com/annimon/ownlang/lib/StringValue.java +++ b/src/com/annimon/ownlang/lib/StringValue.java @@ -54,6 +54,14 @@ public final class StringValue implements Value { return Objects.equals(this.value, other.value); } + @Override + public int compareTo(Value o) { + if (o.type() == Types.STRING) { + return value.compareTo(((StringValue) o).value); + } + return asString().compareTo(o.asString()); + } + @Override public String toString() { return asString(); diff --git a/src/com/annimon/ownlang/lib/Value.java b/src/com/annimon/ownlang/lib/Value.java index 7f09b5f..832e9f7 100644 --- a/src/com/annimon/ownlang/lib/Value.java +++ b/src/com/annimon/ownlang/lib/Value.java @@ -4,7 +4,7 @@ package com.annimon.ownlang.lib; * * @author aNNiMON */ -public interface Value { +public interface Value extends Comparable { double asNumber(); diff --git a/src/com/annimon/ownlang/lib/modules/functional.java b/src/com/annimon/ownlang/lib/modules/functional.java index 8d3126c..526ecba 100644 --- a/src/com/annimon/ownlang/lib/modules/functional.java +++ b/src/com/annimon/ownlang/lib/modules/functional.java @@ -16,6 +16,7 @@ public final class functional implements Module { Functions.set("flatmap", new functional_flatmap()); Functions.set("reduce", new functional_reduce()); Functions.set("filter", new functional_filter()); + Functions.set("sortby", new functional_sortby()); Functions.set("combine", new functional_combine()); diff --git a/src/com/annimon/ownlang/lib/modules/functions/functional_sortby.java b/src/com/annimon/ownlang/lib/modules/functions/functional_sortby.java new file mode 100644 index 0000000..2115c17 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/functions/functional_sortby.java @@ -0,0 +1,27 @@ +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.Arrays; + +public final class functional_sortby implements Function { + + @Override + public Value execute(Value... args) { + if (args.length != 2) throw new ArgumentsMismatchException("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 Value[] elements = ((ArrayValue) args[0]).getCopyElements(); + final Function function = ((FunctionValue) args[1]).getValue(); + Arrays.sort(elements, (o1, o2) -> function.execute(o1).compareTo(function.execute(o2))); + return new ArrayValue(elements); + } + +} \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/functions/std_sort.java b/src/com/annimon/ownlang/lib/modules/functions/std_sort.java new file mode 100644 index 0000000..edd0e40 --- /dev/null +++ b/src/com/annimon/ownlang/lib/modules/functions/std_sort.java @@ -0,0 +1,36 @@ +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.Arrays; + +public final class std_sort implements Function { + + @Override + public Value execute(Value... args) { + if (args.length < 1) throw new ArgumentsMismatchException("At least one argument expected"); + if (args[0].type() != Types.ARRAY) { + throw new TypeException("Array expected in first argument"); + } + final Value[] elements = ((ArrayValue) args[0]).getCopyElements(); + + switch (args.length) { + case 1: + Arrays.sort(elements); + break; + case 2: + if (args[1].type() != Types.FUNCTION) { + throw new TypeException("Function expected in second argument"); + } + final Function comparator = ((FunctionValue) args[1]).getValue(); + Arrays.sort(elements, (o1, o2) -> (int) comparator.execute(o1, o2).asNumber()); + break; + default: + throw new ArgumentsMismatchException("Wrong number of arguments"); + } + + return new ArrayValue(elements); + } + +} \ No newline at end of file diff --git a/src/com/annimon/ownlang/lib/modules/std.java b/src/com/annimon/ownlang/lib/modules/std.java index d5e7746..fe986ea 100644 --- a/src/com/annimon/ownlang/lib/modules/std.java +++ b/src/com/annimon/ownlang/lib/modules/std.java @@ -13,6 +13,7 @@ public final class std implements Module { public void init() { Functions.set("echo", new std_echo()); Functions.set("newarray", new std_newarray()); + Functions.set("sort", new std_sort()); Functions.set("length", new std_length()); Functions.set("rand", new std_rand()); Functions.set("sleep", new std_sleep());