variadic zip. Close #9

This commit is contained in:
2021-07-12 16:17:38 -06:00
parent 1d863d3ec9
commit 0af3749975
4 changed files with 42 additions and 24 deletions

View File

@@ -55,7 +55,6 @@ 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"),
"zip" => Symbol("Prelude.zip"),
"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

View File

@@ -124,7 +124,8 @@ class Macros {
"<=" => "Prelude.lesserEqual", "<=" => "Prelude.lesserEqual",
"=" => "Prelude.areEqual", "=" => "Prelude.areEqual",
"max" => "Prelude.max", "max" => "Prelude.max",
"min" => "Prelude.min" "min" => "Prelude.min",
"zip" => "Prelude.zip"
]; ];
macros["apply"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> { macros["apply"] = (wholeExp:ReaderExp, exps:Array<ReaderExp>, k) -> {
@@ -166,10 +167,13 @@ class Macros {
var min = if (exps.length > 1) exps[0] else b.symbol("0"); var min = if (exps.length > 1) exps[0] else b.symbol("0");
var max = if (exps.length > 1) exps[1] else exps[0]; var max = if (exps.length > 1) exps[1] else exps[0];
var step = if (exps.length > 2) exps[2] else b.symbol("1"); var step = if (exps.length > 2) exps[2] else b.symbol("1");
b.call( b.callSymbol("Prelude.range", [min, max, step]);
b.symbol("Prelude.range"), [ };
min, max, step
]); macros["zip"] = (wholeExp:ReaderExp, exps:kiss.List<ReaderExp>, k) -> {
wholeExp.checkNumArgs(2, null, '(zip [listA] [listB] [moreLists...])');
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:

View File

@@ -178,31 +178,45 @@ class Prelude {
return fullGroups; return fullGroups;
} }
public static function zip(a:Array<Dynamic>, b:Array<Dynamic>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> { public static function zip(arrays:Array<Array<Dynamic>>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
var max = Math.floor(if (a.length != b.length) { var lengthsAreEqual = true;
var lengths = [for (arr in arrays) arr.length];
var lengthOperands = [for (length in lengths) Operand.fromDynamic(length)];
for (idx in 1...lengths.length) {
if (lengths[idx] != lengths[idx - 1]) {
lengthsAreEqual = false;
break;
}
}
var max = Math.floor(if (!lengthsAreEqual) {
switch (extraHandling) { switch (extraHandling) {
case Throw: case Throw:
throw 'zip was given lists of mis-matched size: $a, $b'; throw 'zip was given lists of mis-matched size: $arrays';
case Keep: case Keep:
Math.max(a.length, b.length); Operand.toDynamic(Prelude.max(lengthOperands));
case Drop: case Drop:
Math.min(a.length, b.length); Operand.toDynamic(Prelude.min(lengthOperands));
} }
} else { } else {
a.length; lengths[0];
}); });
return [ return [
for (idx in 0...max) [ for (idx in 0...max) {
if (idx < a.length) var zipped:Array<Dynamic> = [];
a[idx]
else for (arr in arrays) {
null, zipped.push(
if (idx < b.length) if (idx < arr.length) {
b[idx] arr[idx];
else } else {
null null;
] }
);
}
zipped;
}
]; ];
} }
@@ -213,7 +227,7 @@ class Prelude {
l1.push(l[-1]); l1.push(l[-1]);
l2.unshift(l[0]); l2.unshift(l[0]);
} }
return zip(l1, l2); return zip([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> {

View File

@@ -122,7 +122,8 @@
(try (begin (zip [1 3] [2] Throw) (Assert.fail)) (try (begin (zip [1 3] [2] Throw) (Assert.fail))
(catch [error] (Assert.pass))) (catch [error] (Assert.pass)))
(try (begin (zip [1] [2 4] Throw) (Assert.fail)) (try (begin (zip [1] [2 4] Throw) (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))))
(defun _testLet [] (defun _testLet []
(let [a 5 (let [a 5