JSFiddle - React, Tailwind, and code Playground
JavaScript
function *source(len) {
for (let n = 1; n <= len; ++n) {
yield n;
}
}
function assert(value, message) {
if (!value) {
throw new Error("Assertion failure:" + message);
}
}
function assignToBindings(bindings, iterator) {
let bindingIndex = 0;
let currentBinding;
let e;
// Consume bindings prior to rest
while ((currentBinding = bindings[bindingIndex++]) && !currentBinding.isRest) {
e = iterator.next();
if (e.done) {
return;
}
currentBinding.value = e.value;
}
if (!currentBinding) {
return; // Out of bindings
}
// Read to the end into the rest binding
assert(currentBinding.isRest, "hit rest binding");
const rest = currentBinding.value;
while (!(e = iterator.next()).done) {
rest.push(e.value);
}
if (bindingIndex >= bindings.length) {
return; // rest binding was last binding
}
// Move trailing entries out of the rest binding into the trailing bindings
const restLength = Math.max(0, rest.length - (bindings.length - bindingIndex));
for (let restIndex = restLength; restIndex < rest.length; ++restIndex) {
bindings[bindingIndex++].value = rest[restIndex];
}
rest.length = restLength;
}
function b(name, isRest = false) {
return {name, isRest, value: isRest ? [] : undefined};
}
function test(bindings, len) {
console.log(` iterable with ${len} item(s):`);
assignToBindings(bindings, source(len));
for (const binding of bindings) {
console.log(" ", binding.name, binding.value);
}
}
console.log("const [a, b, ...rest, c, d] = ");
test([b("a"), b("b"), b("rest", true), b("c"), b("d")], 0);
test([b("a"), b("b"), b("rest", true), b("c"), b("d")], 1);
test([b("a"), b("b"), b("rest", true), b("c"), b("d")], 2);
test([b("a"), b("b"), b("rest", true), b("c"), b("d")], 3);
test([b("a"), b("b"), b("rest", true), b("c"), b("d")], 4);
test([b("a"), b("b"), b("rest",...