variadic zip. Close #9

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

View File

@@ -55,7 +55,6 @@ class Kiss {
"print" => Symbol("Prelude.print"),
"sort" => Symbol("Prelude.sort"),
"groups" => Symbol("Prelude.groups"),
"zip" => Symbol("Prelude.zip"),
"pairs" => Symbol("Prelude.pairs"), // TODO test pairs
"reversed" => Symbol("Prelude.reversed"), // TODO test reversed
"memoize" => Symbol("Prelude.memoize"), // TODO test memoize

View File

@@ -124,7 +124,8 @@ class Macros {
"<=" => "Prelude.lesserEqual",
"=" => "Prelude.areEqual",
"max" => "Prelude.max",
"min" => "Prelude.min"
"min" => "Prelude.min",
"zip" => "Prelude.zip"
];
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 max = if (exps.length > 1) exps[1] else exps[0];
var step = if (exps.length > 2) exps[2] else b.symbol("1");
b.call(
b.symbol("Prelude.range"), [
min, max, step
]);
b.callSymbol("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:

View File

@@ -178,31 +178,45 @@ class Prelude {
return fullGroups;
}
public static function zip(a:Array<Dynamic>, b:Array<Dynamic>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
var max = Math.floor(if (a.length != b.length) {
public static function zip(arrays:Array<Array<Dynamic>>, extraHandling = Drop):kiss.List<kiss.List<Dynamic>> {
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) {
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:
Math.max(a.length, b.length);
Operand.toDynamic(Prelude.max(lengthOperands));
case Drop:
Math.min(a.length, b.length);
Operand.toDynamic(Prelude.min(lengthOperands));
}
} else {
a.length;
lengths[0];
});
return [
for (idx in 0...max) [
if (idx < a.length)
a[idx]
else
null,
if (idx < b.length)
b[idx]
else
null
]
for (idx in 0...max) {
var zipped:Array<Dynamic> = [];
for (arr in arrays) {
zipped.push(
if (idx < arr.length) {
arr[idx];
} else {
null;
}
);
}
zipped;
}
];
}
@@ -213,7 +227,7 @@ class Prelude {
l1.push(l[-1]);
l2.unshift(l[0]);
}
return zip(l1, l2);
return zip([l1, l2]);
}
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))
(catch [error] (Assert.pass)))
(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 []
(let [a 5