variadic zip. Close #9
This commit is contained in:
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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> {
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user