Make zip functions (and joinPath, concat) compatible with apply. Close #19
This commit is contained in:
@@ -56,11 +56,9 @@ class Kiss {
|
|||||||
"print" => Symbol("Prelude.print"),
|
"print" => Symbol("Prelude.print"),
|
||||||
"sort" => Symbol("Prelude.sort"),
|
"sort" => Symbol("Prelude.sort"),
|
||||||
"groups" => Symbol("Prelude.groups"),
|
"groups" => Symbol("Prelude.groups"),
|
||||||
"concat" => Symbol("Prelude.concat"),
|
|
||||||
"pairs" => Symbol("Prelude.pairs"), // TODO test pairs
|
"pairs" => Symbol("Prelude.pairs"), // TODO test pairs
|
||||||
"reversed" => Symbol("Prelude.reversed"), // TODO test reversed
|
"reversed" => Symbol("Prelude.reversed"), // TODO test reversed
|
||||||
"memoize" => Symbol("Prelude.memoize"), // TODO test memoize
|
"memoize" => Symbol("Prelude.memoize"), // TODO test memoize
|
||||||
"joinPath" => Symbol("Prelude.joinPath"),
|
|
||||||
"symbolName" => Symbol("Prelude.symbolName"),
|
"symbolName" => Symbol("Prelude.symbolName"),
|
||||||
"symbolNameValue" => Symbol("Prelude.symbolNameValue"),
|
"symbolNameValue" => Symbol("Prelude.symbolNameValue"),
|
||||||
"symbol" => Symbol("Prelude.symbol"),
|
"symbol" => Symbol("Prelude.symbol"),
|
||||||
@@ -70,11 +68,12 @@ class Kiss {
|
|||||||
"flatten" => Symbol("Lambda.flatten"),
|
"flatten" => Symbol("Lambda.flatten"),
|
||||||
"has" => Symbol("Lambda.has"),
|
"has" => Symbol("Lambda.has"),
|
||||||
"count" => Symbol("Lambda.count"),
|
"count" => Symbol("Lambda.count"),
|
||||||
|
// These work with (apply) because they are added as "opAliases" in Macros.kiss:
|
||||||
"min" => Symbol("Prelude.min"),
|
"min" => Symbol("Prelude.min"),
|
||||||
"max" => Symbol("Prelude.max")
|
"max" => Symbol("Prelude.max"),
|
||||||
],
|
],
|
||||||
// These ones won't conflict with variables and might commonly be used with (apply)
|
|
||||||
identAliases: [
|
identAliases: [
|
||||||
|
// These ones won't conflict with variables and might commonly be used with (apply)
|
||||||
"+" => Symbol("Prelude.add"),
|
"+" => Symbol("Prelude.add"),
|
||||||
"-" => Symbol("Prelude.subtract"),
|
"-" => Symbol("Prelude.subtract"),
|
||||||
"*" => Symbol("Prelude.multiply"),
|
"*" => Symbol("Prelude.multiply"),
|
||||||
@@ -85,7 +84,13 @@ class Kiss {
|
|||||||
">=" => Symbol("Prelude.greaterEqual"),
|
">=" => Symbol("Prelude.greaterEqual"),
|
||||||
"<" => Symbol("Prelude.lessThan"),
|
"<" => Symbol("Prelude.lessThan"),
|
||||||
"<=" => Symbol("Prelude.lesserEqual"),
|
"<=" => Symbol("Prelude.lesserEqual"),
|
||||||
"=" => Symbol("Prelude.areEqual")
|
"=" => Symbol("Prelude.areEqual"),
|
||||||
|
// These ones *probably* won't conflict with variables and might commonly be used with (apply) because they are variadic
|
||||||
|
"concat" => Symbol("Prelude.concat"),
|
||||||
|
"zipKeep" => Symbol("Prelude.zipKeep"),
|
||||||
|
"zipDrop" => Symbol("Prelude.zipDrop"),
|
||||||
|
"zipThrow" => Symbol("Prelude.zipThrow"),
|
||||||
|
"joinPath" => Symbol("Prelude.joinPath"),
|
||||||
],
|
],
|
||||||
fields: [],
|
fields: [],
|
||||||
loadingDirectory: "",
|
loadingDirectory: "",
|
||||||
|
@@ -110,12 +110,6 @@ class Macros {
|
|||||||
b.callSymbol("Prelude.range", [min, max, step]);
|
b.callSymbol("Prelude.range", [min, max, step]);
|
||||||
};
|
};
|
||||||
|
|
||||||
macros["zip"] = (wholeExp:ReaderExp, exps:kiss.List<ReaderExp>, k) -> {
|
|
||||||
wholeExp.checkNumArgs(3, null, '(zip [listA] [listB] [moreLists...] [extraHandling])');
|
|
||||||
var b = wholeExp.expBuilder();
|
|
||||||
return b.callSymbol("Prelude.zip", [b.list(exps.slice(0, -1)), exps[-1]]);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Most conditional compilation macros are based on this macro:
|
// Most conditional compilation macros are based on this macro:
|
||||||
macros["#if"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
macros["#if"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
|
||||||
wholeExp.checkNumArgs(2, 3, '(#if [cond] [then] [?else])');
|
wholeExp.checkNumArgs(2, 3, '(#if [cond] [then] [?else])');
|
||||||
|
@@ -181,47 +181,51 @@ class Prelude {
|
|||||||
|
|
||||||
public static var concat:Function = Reflect.makeVarArgs(_concat);
|
public static var concat:Function = Reflect.makeVarArgs(_concat);
|
||||||
|
|
||||||
public static function zip(arrays:Array<Array<Dynamic>>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
|
static function _zip(iterables:Array<Dynamic>, extraHandling:ExtraElementHandling):Array<Array<Dynamic>> {
|
||||||
var lengthsAreEqual = true;
|
var lists = [];
|
||||||
var lengths = [for (arr in arrays) arr.length];
|
var iterators = [for (iterable in iterables) iterable.iterator()];
|
||||||
for (idx in 1...lengths.length) {
|
|
||||||
if (lengths[idx] != lengths[idx - 1]) {
|
|
||||||
lengthsAreEqual = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var max = Math.floor(if (!lengthsAreEqual) {
|
|
||||||
switch (extraHandling) {
|
|
||||||
case Throw:
|
|
||||||
throw 'zip was given lists of mis-matched size: $arrays';
|
|
||||||
case Keep:
|
|
||||||
Prelude._max(lengths);
|
|
||||||
case Drop:
|
|
||||||
Prelude._min(lengths);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lengths[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
return [
|
while (true) {
|
||||||
for (idx in 0...max) {
|
var zipped:Array<Dynamic> = [];
|
||||||
var zipped:Array<Dynamic> = [];
|
|
||||||
|
|
||||||
for (arr in arrays) {
|
var someNonNull = false;
|
||||||
zipped.push(
|
for (it in iterators) {
|
||||||
if (idx < arr.length) {
|
switch (extraHandling) {
|
||||||
arr[idx];
|
case Keep:
|
||||||
} else {
|
zipped.push(
|
||||||
null;
|
if (it.hasNext()) {
|
||||||
}
|
someNonNull = true;
|
||||||
);
|
it.next();
|
||||||
|
} else {
|
||||||
|
null;
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
if (it.hasNext())
|
||||||
|
zipped.push(it.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
zipped;
|
|
||||||
}
|
}
|
||||||
];
|
|
||||||
|
switch (extraHandling) {
|
||||||
|
case _ if (zipped.length == 0):
|
||||||
|
break;
|
||||||
|
case Keep if (!someNonNull):
|
||||||
|
break;
|
||||||
|
case Drop if (zipped.length != iterators.length):
|
||||||
|
break;
|
||||||
|
case Throw if (zipped.length != iterators.length):
|
||||||
|
throw 'zip${extraHandling} was given iterables of mis-matched size: $iterables';
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
lists.push(zipped);
|
||||||
|
}
|
||||||
|
return lists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static var zipKeep:Function = Reflect.makeVarArgs(_zip.bind(_, Keep));
|
||||||
|
public static var zipDrop:Function = Reflect.makeVarArgs(_zip.bind(_, Drop));
|
||||||
|
public static var zipThrow:Function = Reflect.makeVarArgs(_zip.bind(_, Throw));
|
||||||
|
|
||||||
public static function pairs(l:kiss.List<Dynamic>, loopAround = false):kiss.List<kiss.List<Dynamic>> {
|
public static function pairs(l:kiss.List<Dynamic>, loopAround = false):kiss.List<kiss.List<Dynamic>> {
|
||||||
var l1 = l.slice(0, l.length - 1);
|
var l1 = l.slice(0, l.length - 1);
|
||||||
var l2 = l.slice(1, l.length);
|
var l2 = l.slice(1, l.length);
|
||||||
@@ -229,7 +233,7 @@ class Prelude {
|
|||||||
l1.push(l[-1]);
|
l1.push(l[-1]);
|
||||||
l2.unshift(l[0]);
|
l2.unshift(l[0]);
|
||||||
}
|
}
|
||||||
return zip([l1, l2]);
|
return zipThrow(l1, l2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function reversed<T>(l:kiss.List<T>):kiss.List<T> {
|
public static function reversed<T>(l:kiss.List<T>):kiss.List<T> {
|
||||||
|
@@ -119,14 +119,16 @@
|
|||||||
(catch [error] (Assert.pass))))
|
(catch [error] (Assert.pass))))
|
||||||
|
|
||||||
(defun _testZip []
|
(defun _testZip []
|
||||||
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (zip [1 3] [2 4] Throw)))
|
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (zipThrow [1 3] [2 4])))
|
||||||
(Assert.equals (.toString [[1 2] [3 null]]) (.toString (zip [1 3] [2] Keep)))
|
(Assert.equals (.toString [[1 2] [3 null]]) (.toString (zipKeep [1 3] [2])))
|
||||||
(Assert.equals (.toString [[1 2] [null 4]]) (.toString (zip [1 null] [2 4] Keep)))
|
(Assert.equals (.toString [[1 2] [null 4]]) (.toString (zipKeep [1 null] [2 4])))
|
||||||
(try (begin (zip [1 3] [2] Throw) (Assert.fail))
|
(try (begin (zipThrow [1 3] [2]) (Assert.fail))
|
||||||
(catch [error] (Assert.pass)))
|
(catch [error] (Assert.pass)))
|
||||||
(try (begin (zip [1] [2 4] Throw) (Assert.fail))
|
(try (begin (zipThrow [1] [2 4]) (Assert.fail))
|
||||||
(catch [error] (Assert.pass)))
|
(catch [error] (Assert.pass)))
|
||||||
(Assert.equals (.toString [[1 2 3] [2 null 3]]) (.toString (zip [1 2] [2] [3 3] Keep))))
|
(Assert.equals (.toString [[1 2 3] [2 null 3]]) (.toString (zipKeep [1 2] [2] [3 3])))
|
||||||
|
(Assert.equals (.toString [[1 2]]) (.toString (zipDrop [1 2 3 4] [2])))
|
||||||
|
(Assert.equals (.toString [[1 2] [3 4]]) (.toString (apply zipThrow [[1 3] [2 4]]))))
|
||||||
|
|
||||||
(defun _testLet []
|
(defun _testLet []
|
||||||
(let [a 5
|
(let [a 5
|
||||||
|
@@ -35,9 +35,9 @@
|
|||||||
// TODO rectangle type
|
// TODO rectangle type
|
||||||
// TODO optional source rectangle argument
|
// TODO optional source rectangle argument
|
||||||
(defmethod blitSurface [:Surface surface x y]
|
(defmethod blitSurface [:Surface surface x y]
|
||||||
(doFor [srcX destX] (zip (collect (range 0 surface.width)) (collect (range x (+ x surface.width))) Drop)
|
(doFor [srcX destX] (zipDrop (range surface.width) (range x (+ x surface.width)))
|
||||||
(when (< -1 destX width)
|
(when (< -1 destX width)
|
||||||
(doFor [srcY destY] (zip (collect (range 0 surface.height)) (collect (range y (+ y surface.height))) Drop)
|
(doFor [srcY destY] (zipDrop (range 0 surface.height) (range y (+ y surface.height)))
|
||||||
(when (< -1 destY height)
|
(when (< -1 destY height)
|
||||||
(when (surface.isCellOpaque srcX srcY)
|
(when (surface.isCellOpaque srcX srcY)
|
||||||
(setBackgroundColor destX destY (surface.getBackgroundColor srcX srcY))
|
(setBackgroundColor destX destY (surface.getBackgroundColor srcX srcY))
|
||||||
|
Reference in New Issue
Block a user