The proposed pattern is already possible, as demostrated at the code at https://esdiscuss.org/topic/proposal-rest-operator-in-middle-of-array#content-2 .
How does the code at that post specifically not provide the same functionality as proposed? On Mon, Jun 10, 2019 at 9:20 PM Ethan Resnick <[email protected]> wrote: > > This has come up several times and, while it seems pretty intuitive to > me, not everyone seems to agree. You can check the archives for previous > discussions. > > @Andy Perhaps you can provide some links? I found two > <https://esdiscuss.org/topic/an-array-destructing-specification-choice#content-69> > threads <https://esdiscuss.org/topic/early-spread-operator> — both 8 > years old — that talked about this, along with one more recent one > <https://esdiscuss.org/topic/strawman-complete-array-and-object-destructuring> > that didn't get very far. In the first two threads, commenters brought up > one case where the semantics are unclear (i.e., when there are more listed > binding elements than there are elements in the iterable), and there was > some talk about implementation complexity. But there was also some interest > from some big contributors to the spec. So I wonder if it's time to revisit > this? > > > if you want to extend the function with additional args, > > then you'll have to retroactively modify all existing calls to avoid > off-by-one argcount: > > @Kai I'm not sure I follow. If the new argument is required, you have to > modify all existing calls whether the new argument goes at the end or as > the second to last argument. If the new argument is optional, then adding > it as the second to last argument doesn't break existing calls at all, > assuming the function accounts for the fact that the optional arguments are > all the ones after the initial required ones, and up until (but excluding) > the last one. The syntax I'm proposing makes adding such extra arguments > easy. In other words: > > ``` > function pad(targetLength, ...opts, data) { > const [paddingChar = " "] = opts; > // pad data with paddingChar to targetLength; > } > ``` > > would, with the addition of an optional "meta" arg, become: > > ``` > function pad(targetLength, ...opts, data) { > const [paddingChar = " ", meta = { /* some default */ }] = opts; > // pad data with paddingChar to targetLength; > } > ``` > > More importantly, though, this data-last calling pattern has a long > history, and there are some cases where it's the best solution. My use case > was similar to the common one, namely, that I was building a data pipeline, > with the "settings" arguments partially applied from the left to create the > function to use in each step. (And, in my case, I was building each > function in a DSL where it would've been very inconvenient to add > arbitrary-order partial application, even if JS were to add something like > that <https://github.com/tc39/proposal-partial-application>.) > > Given that functions where the last argument is significant probably > aren't going away, it'd be nice imo if the JS syntax supported this better. > > On Fri, Jun 7, 2019 at 7:11 PM kai zhu <[email protected]> wrote: > >> it matters when you have to debug/inherit *other* people's code (and >> clean up their mess). i wouldn't enjoy debugging unfamiliar-code that used >> this feature (admittedly, its my subjective opinion). >> >> the maintainability argument stands -- its counter-intuitive in >> javascript that appending extra args to a function re-arranges >> arg-positioning and invalidates existing calls. >> >> debuggability is subjective i agree. >> >> p.s. - in general, i don't see what *real* painpoint rest-operator >> actually address, that couldn't be solved with `arguments`. >> variable-arg-length functions are not javascripty -- they frequently >> require extra ux-workflow transformations like Function.p.apply or >> Array.p.flatmap to the arguments being passed. >> >> >> On Fri, Jun 7, 2019 at 10:07 AM Isiah Meadows <[email protected]> >> wrote: >> >>> For your maintainability argument: adding extra arguments to those >>> functions is something I almost never do. And you'd have the same >>> exact issue with final rest parameters, just in a different position >>> (in the middle as opposed to in the end). >>> >>> For debuggability, I don't see how it'd be a major issue unless you >>> already have an excessive number of *positional* parameters. In my >>> experience, the debuggability issues arise approximately when there's >>> just too many positional parameters, and factoring out the rest >>> parameter to an array doesn't really help this situation much. (That's >>> when object destructuring comes in handy.) >>> >>> So not convinced either is any different than what it's like today. >>> >>> Also, you aren't obligated to use a feature just because it exists - I >>> hardly ever use proxies, for instance, and I rarely need maps beyond >>> what objects give me, so I don't normally use them unless I need to >>> have reference types or mixed types as keys. >>> >>> ----- >>> >>> Isiah Meadows >>> [email protected] >>> www.isiahmeadows.com >>> >>> On Thu, Jun 6, 2019 at 2:22 PM kai zhu <[email protected]> wrote: >>> > >>> > -1 for maintainability and debuggability >>> > >>> > 1. maintainability >>> > if you want to extend the function with additional args, >>> > then you'll have to retroactively modify all existing calls to avoid >>> off-by-one argcount: >>> > >>> > ```js >>> > // if extending function with additional args >>> > function pad(targetLength, ...opts, data) -> >>> > function pad(targetLength, ...opts, data, meta) >>> > >>> > // then must retroactively append null/undefined to all existing calls >>> > pad(1, opt1, opt2, "data") -> >>> > pad(1, opt1, opt2, "data", null) >>> > ``` >>> > >>> > >>> > >>> > 2. debuggability >>> > when debugging, it takes longer for human to figure out which arg is >>> what: >>> > >>> > ```js >>> > // function pad(targetLength, ...opts, data) >>> > pad(aa, bb, cc, dd); >>> > pad(aa, bb, cc, dd, ee); >>> > >>> > // vs >>> > >>> > // function pad(targetLength, opts, data) >>> > pad(aa, [bb, cc], dd); >>> > pad(aa, [bb, cc, dd], ee); >>> > ``` >>> > >>> > >>> > >>> > On Thu, Jun 6, 2019 at 11:54 AM Ethan Resnick <[email protected]> >>> wrote: >>> >> >>> >> Long-time mostly-lurker on here. I deeply appreciate all the hard >>> work that folks here put into JS. >>> >> >>> >> I've run into a couple cases now where it'd be convenient to use a >>> rest operator at the beginning or middle of an array destructuring, as in: >>> >> >>> >> ``` >>> >> const [...xs, y] = someArray; >>> >> ``` >>> >> >>> >> Or, similarly, in function signatures: >>> >> >>> >> ``` >>> >> function(...xs, y) { } >>> >> ``` >>> >> >>> >> The semantics would be simple: exhaust the iterable to create the >>> array of `xs`, like a standard rest operator would do, but then slice off >>> the last item and put it in `y`. >>> >> >>> >> For example, I was working with some variable argument functions >>> that, in FP style, always take their data last. So I had a function like >>> this: >>> >> >>> >> ``` >>> >> function match(...matchersAndData) { >>> >> const matchers = matchersAndData.slice(0, -1); >>> >> const data = matchersAndData[matchersAndData.length - 1]; >>> >> // do matching against data >>> >> } >>> >> ``` >>> >> >>> >> Under this proposal, the above could be rewritten: >>> >> >>> >> ``` >>> >> function reduce(...matchers, data) { /* ... */ } >>> >> ``` >>> >> >>> >> Another example: a function `pad`, which takes a target length and a >>> string to pad, with an optional padding character argument in between: >>> >> >>> >> ``` >>> >> function pad(targetLength, ...paddingCharAndOrData) { >>> >> const [paddingChar = " "] = paddingCharAndOrData.slice(0, -1); >>> >> const data = paddingCharAndOrData[paddingCharAndOrData.length - 1]; >>> >> >>> >> // pad data with paddingChar to targetLength; >>> >> } >>> >> ``` >>> >> >>> >> With this proposal, that could be rewritten: >>> >> >>> >> ``` >>> >> function pad(targetLength, ...opts, data) { >>> >> const [paddingChar = " "] = opts; >>> >> // pad data with paddingChar to targetLength; >>> >> } >>> >> ``` >>> >> >>> >> I'm curious if this has been considered before, and what people think >>> of the idea. >>> >> >>> >> Obviously, if `...a` appeared at the beginning or middle of a list, >>> there would have to be a fixed number of items following it, so a >>> subsequent rest operator in the same list would not be allowed. >>> >> >>> >> Thanks >>> >> >>> >> _______________________________________________ >>> >> es-discuss mailing list >>> >> [email protected] >>> >> https://mail.mozilla.org/listinfo/es-discuss >>> > >>> > _______________________________________________ >>> > es-discuss mailing list >>> > [email protected] >>> > https://mail.mozilla.org/listinfo/es-discuss >>> >> _______________________________________________ > es-discuss mailing list > [email protected] > https://mail.mozilla.org/listinfo/es-discuss >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

