Could you bring that up in a different thread instead of driving this
off-topic? Also, please don't forget that a *very* significant chunk
of JS doesn't even run in a GUI environment (consider: servers, IoT,
satellites, etc.).

-----

Isiah Meadows
cont...@isiahmeadows.com
www.isiahmeadows.com

On Wed, Dec 19, 2018 at 1:33 AM kai zhu <kaizhu...@gmail.com> wrote:
>>
>> I could go with an iterator equivalent, but I'd like to defer that to
>> the seemingly-planned "iterlib" thing that's been considered since
>> before ES2015 was released.
>
>
> i'm against iterator-based design-patterns and libraries, as they lack a 
> clear fit in most javascript solutions.  the vast majority of looping in 
> UX-workflows (javascript’s primary problem-domain) are over [serializable] 
> JSON lists/dicts/strings, where Array/Object/String looping-methods will 
> suffice.
>
> all other use-cases are uncommon/complicated enough that custom for/while 
> loops are usually better suited than custom-iterators.
>
> -kai
>
>
>
> On 18 Dec 2018, at 16:42, Mike Samuel <mikesam...@gmail.com> wrote:
>
> Fair enough.
>
> On Tue, Dec 18, 2018, 5:29 PM Isiah Meadows <isiahmead...@gmail.com wrote:
>>
>> I could go with an iterator equivalent, but I'd like to defer that to
>> the seemingly-planned "iterlib" thing that's been considered since
>> before ES2015 was released. Something that works with arrays is good
>> enough for now.
>>
>> BTW, your `ziperator` isn't really the same as my `Array.interpolate`
>> (which is better named `Array.interleave`). It needs to be this:
>>
>> ```js
>> function *ziperator(...iters) {
>>     for (let i = 0; i < iters.length; i++) {
>>         iters[i] = iters[i][Symbol.iterator]()
>>     }
>>     while (true) {
>>         for (let i = 0; i < iters.length; i++) {
>>             const {done, value} = iters[i].next()
>>             if (done) return undefined
>>             yield value
>>         }
>>     }
>> }
>> ```
>>
>> The optimized version is pretty straightforward (using private fields
>> + methods here):
>>
>> ```js
>> function ziperator(...iters) { return new InterleavedIterator(iters) }
>>
>> class InterleavedIterator {
>>     #iters, #index
>>     constructor(iters) { this.#iters = iters; this.#index = 0 }
>>     [Symbol.iterator]() { return this }
>>     next(value) { return this.#invoke("next", value) }
>>     throw(value) { return this.#invoke("throw", value) }
>>     return(value) { return this.#invoke("return", value) }
>>     #invoke(method, value) {
>>         if (this.#iters == null) return {done: true, value: undefined}
>>         const index = this.#index
>>         this.#index = (index + 1) % this.#iters.length
>>         const {done, value} = this.#iters[index][method](value)
>>         if (done) this.#iters = undefined
>>         return {done, value}
>>     }
>> }
>> ```
>>
>> -----
>>
>> Isiah Meadows
>> cont...@isiahmeadows.com
>> www.isiahmeadows.com
>> On Fri, Dec 14, 2018 at 2:55 PM Mike Samuel <mikesam...@gmail.com> wrote:
>> >
>> >
>> >
>> > On Fri, Dec 14, 2018 at 2:26 PM Isiah Meadows <isiahmead...@gmail.com> 
>> > wrote:
>> >>
>> >> The main difference with that loop is that it's generalized to any number 
>> >> of arrays, not just two with the second array having length one less than 
>> >> the first. Otherwise, it'd look exactly the same. BTW, I like this route 
>> >> (`Array.interleave`) better since it doesn't have to result in just a 
>> >> single string result - it could just be an array of strings plugged into 
>> >> some API instead, or it could be procedurally streamed out in chunks.
>> >
>> >
>> > Fair enough.
>> > If you're not looking for something template tag specific then a simple 
>> > zip over iterators should do it?
>> >
>> > function *ziperator(iterators) {
>> >     let progressed;
>> >     do {
>> >         progressed = false;
>> >         for (let iterator of iterators) {
>> >             for (let element of iterator) {
>> >                 yield element;
>> >                 progressed = true;
>> >                 break;
>> >             }
>> >         }
>> >     } while (progressed);
>> > }
>> >
>> > console.log(Array.from(ziperator([ ['a', 'b', 'c'][Symbol.iterator](), [1, 
>> > 2][Symbol.iterator]() ])).join(''));
>> > // -> a1b2c
>> >
>> > (but optimized :)
>> >
>> >
>> >
>> >>
>> >> On Fri, Dec 14, 2018 at 14:04 Mike Samuel <mikesam...@gmail.com> wrote:
>> >>>
>> >>>
>> >>>
>> >>> On Fri, Dec 14, 2018 at 12:51 PM Isiah Meadows <isiahmead...@gmail.com> 
>> >>> wrote:
>> >>>>
>> >>>> I'll point out Kai could be on to something, although I disagree `zip` 
>> >>>> would be the right abstraction. Maybe `Array.interleave(...arrays)`? 
>> >>>> You could do `Array.interleave(template, args).map(String).join("")` 
>> >>>> for similar effect, and it'd be more generally useful.
>> >>>>
>> >>>> The key here is that iteration would stop after the index hits any 
>> >>>> array's length, so it'd be polyfilled kinda like this:
>> >>>>
>> >>>> ```js
>> >>>> Array.interpolate = (...args) => {
>> >>>>     let ret = []
>> >>>>     let lengths = []
>> >>>>     let count = 0
>> >>>>     for (let i = 0; i < args.length; i++) {
>> >>>>         lengths[i] = args[i].count
>> >>>>     }
>> >>>>     for (let index = 0; ; index++) {
>> >>>>         for (let i = 0; i < args.length; i++) {
>> >>>>             if (index === lengths[i]) return ret
>> >>>>             ret[count++] = args[i][index]
>> >>>>         }
>> >>>>     }
>> >>>> }
>> >>>> ```
>> >>>>
>> >>>> (This could be optimized, though.)
>> >>>
>> >>>
>> >>> As a data point, something like this loop appears in most of the 
>> >>> template tags I've written but
>> >>> it's never had these precise semantics so I didn't bother putting it 
>> >>> into template-tag-common.
>> >>>
>> >>> That library makes it easy to split the operation of a template tag into 
>> >>> 3 stages:
>> >>> 1. An optional configuration stage accessed by calling the template tag 
>> >>> as a regular function: mytag({ /* options */)`...`
>> >>> 2. Static analysis over the strings.   This is memoized.
>> >>> 3. Computing a result from (options, strings, results of step 2, 
>> >>> interoplated values)
>> >>>
>> >>> The final loop (step 3) in the template tags I maintain tends to looks 
>> >>> like
>> >>>
>> >>> function computeResult(options, staticState /* from step 2 */, strings, 
>> >>> ...values) {
>> >>>   let n = values.length;  // Could do Math.max(strings.length - 1, 
>> >>> values.length);
>> >>>   let result = strings[0];  // Usually strings.raw
>> >>>   for (let i = 0; i < n;) {
>> >>>     const interpolatedValue = f(options, staticState[i], values[i]);
>> >>>     // Sometimes code here looks backwards at the result to see if it 
>> >>> needs to avoid token-merging hazards.
>> >>>     result += interpolatedValue;
>> >>>     result += strings[++i];
>> >>>   }
>> >>>   return wrapResult(result);  // Produce a value of a type that 
>> >>> encapsulates the tag's security guarantees.
>> >>> }
>> >>>
>> >>>
>> >>>
>> >>>
>
>
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to