T.J. Crowder (2017-08-03T11:00:24.000Z)
tj.crowder at farsightsoftware.com (2017-08-03T14:46:46.298Z)
On Thu, Aug 3, 2017 at 10:18 AM, James Browning <thejamesernator at gmail.com> wrote: > > The 1, 1 would happen if you decided that `[a, ...rest, b]` read > in both directions (although personally I'm not a fan of this > approach)... Gotcha. Yeah, having it duplicate things would seem wrong. :-) > One option could be (although I don't like it either) to allow > the rest operator to have a direction... I'd say: Keep it simple. Left-to-right, non-duplicating, non-greedy with respect to non-rest bindings, greedy otherwise: ```js function *source(len) { for (let n = 1; n <= len; ++n) { yield n; } } function test(len) { const [ a, ...rest, b, c ] = source(len); console.log("With " + len + ":", a, rest, b, c); } test(0); // With 0: undefined, [], undefined, undefined test(1); // With 1: 1, [], undefined, undefined test(2); // With 2: 1, [], 2, undefined test(3); // With 3: 1, [], 2, 3 test(4); // With 4: 1, [2], 3, 4 test(5); // With 5: 1, [2, 3], 4, 5 ``` On Thu, Aug 3, 2017 at 10:29 AM, Andy Earnshaw <andyearnshaw at gmail.com> wrote: > > If you think of rest as "everything else" (which is what it already is) > then this feels pretty natural and is easy to reason about. Exactly. (And as you say, hardly original with me.) A pragmatic approach could simply consume the rest of the iterable into the rest binding and then if there are more bindings after it, move those entries into them: ```js 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; } ``` [Fiddle with examples/tests](https://jsfiddle.net/p35vt5yc/). -- T.J. Crowder