Array.prototype.tap
I think the most common use of this pattern would be debugging, and in this context you don't really care to use a little helper and Array.prototype.map, eg:
const tap = f => ...args => { f(...args); return x; };
[1, 2, 3] .map(num => num * 2) .map(tap(console.log.bind(console))); .reduce((a, b) => a + b);
I think the most common use of this pattern would be debugging, and in this context you don't really care to use a little helper and Array.prototype.map, eg: const tap = f => ...args => { f(...args); return x; }; [1, 2, 3] .map(num => num * 2) .map(tap(console.log.bind(console))); .reduce((a, b) => a + b); On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: > I'd like to propose a `.tap` method on the Array prototype. I was able to > find some previous discussion here but it was off the main topic and seemed > to die out: https://mail.mozilla.org/pipermail/es-discuss/2015-Octo > ber/044454.html > > A tap method enables the user to inspect an array in the chain. > > For example, inspection: > > If you have a chain like this: > > ``` > [1, 2, 3] > .map(num => num * 2) > .reduce((a, b) => a + b); > ``` > > When you want to see what the value of the array is between the map and > reduce, you would typically do this: > > ``` > const value = [1, 2, 3] > .map(num => num * 2); > > console.log(value); > > value.reduce((a, b) => a + b); > ``` > > With `.tap`, you'd be able to do this: > > ``` > [1, 2, 3] > .map(num => num * 2) > .tap(console.log.bind(console)); > .reduce((a, b) => a + b); > ``` > > `.tap` would be called once, passed the entire array as the first argument > to the callback, and would return the array after the callback was finished. > > This isn't something that can cleanly be done with a user-land function > since it would have to wrap the chain, or replace all of the chained > functions like underscore does. > > An example of wrapping the chain: > > ``` > myTap( > ( > [1, 2, 3] > .map(num => num * 2) > ), > console.log.bind(console); > ) > .reduce((a, b) => a + b); > ``` > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/c98b72a2/attachment-0001.html>
Sorry I meant:
const tap = f => x => { f(x); return x; }
Elie ROTENBERG Directeur général adjoint elie.rotenberg at webedia-group.com 336 89 29 98 19 twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg github elierotenberg 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret Cedex - T: 33 811 69 41 42
Sorry I meant: const tap = f => x => { f(x); return x; } Elie ROTENBERG Directeur général adjoint elie.rotenberg at webedia-group.com 336 89 29 98 19 twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg github elierotenberg 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret Cedex - T: 33 811 69 41 42 On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> wrote: > I think the most common use of this pattern would be debugging, and in > this context you don't really care to use a little helper and > Array.prototype.map, eg: > > const tap = f => ...args => { > f(...args); > return x; > }; > > [1, 2, 3] > .map(num => num * 2) > .map(tap(console.log.bind(console))); > .reduce((a, b) => a + b); > > > On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: > >> I'd like to propose a `.tap` method on the Array prototype. I was able to >> find some previous discussion here but it was off the main topic and seemed >> to die out: https://mail.mozilla.org/pipermail/es-discuss/2015-Octo >> ber/044454.html >> >> A tap method enables the user to inspect an array in the chain. >> >> For example, inspection: >> >> If you have a chain like this: >> >> ``` >> [1, 2, 3] >> .map(num => num * 2) >> .reduce((a, b) => a + b); >> ``` >> >> When you want to see what the value of the array is between the map and >> reduce, you would typically do this: >> >> ``` >> const value = [1, 2, 3] >> .map(num => num * 2); >> >> console.log(value); >> >> value.reduce((a, b) => a + b); >> ``` >> >> With `.tap`, you'd be able to do this: >> >> ``` >> [1, 2, 3] >> .map(num => num * 2) >> .tap(console.log.bind(console)); >> .reduce((a, b) => a + b); >> ``` >> >> `.tap` would be called once, passed the entire array as the first >> argument to the callback, and would return the array after the callback was >> finished. >> >> This isn't something that can cleanly be done with a user-land function >> since it would have to wrap the chain, or replace all of the chained >> functions like underscore does. >> >> An example of wrapping the chain: >> >> ``` >> myTap( >> ( >> [1, 2, 3] >> .map(num => num * 2) >> ), >> console.log.bind(console); >> ) >> .reduce((a, b) => a + b); >> ``` >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/f5582e3f/attachment.html>
That leads to a different result. Map is called once for every item in the array.
const tap = f => x => {
f(x);
return x;
}
[1, 2, 3]
.map(num => num * 2)
.map(tap(console.log.bind(console)))
.reduce((a, b) => a + b);
Results in:
2
4
6
Whereas
[1, 2, 3]
.map(num => num * 2)
.tap(console.log.bind(console));
.reduce((a, b) => a + b);
would result in
[2, 4, 6]
This is what makes it hard about being a userland function. Tap enables the developer to act on the entire array, not individual items.
That leads to a different result. Map is called once for every item in the array. ``` const tap = f => x => { f(x); return x; } [1, 2, 3] .map(num => num * 2) .map(tap(console.log.bind(console))) .reduce((a, b) => a + b); ``` Results in: ``` 2 4 6 ``` Whereas ``` [1, 2, 3] .map(num => num * 2) .tap(console.log.bind(console)); .reduce((a, b) => a + b); ``` would result in ``` [2, 4, 6] ``` This is what makes it hard about being a userland function. Tap enables the developer to act on the *entire* array, not individual items. On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> wrote: > Sorry I meant: > > const tap = f => x => { > f(x); > return x; > } > > > Elie ROTENBERG > Directeur général adjoint > elie.rotenberg at webedia-group.com > 336 89 29 98 19 > twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg > github elierotenberg > 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret Cedex - > T: 33 811 69 41 42 > > > On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> wrote: > >> I think the most common use of this pattern would be debugging, and in >> this context you don't really care to use a little helper and >> Array.prototype.map, eg: >> >> const tap = f => ...args => { >> f(...args); >> return x; >> }; >> >> [1, 2, 3] >> .map(num => num * 2) >> .map(tap(console.log.bind(console))); >> .reduce((a, b) => a + b); >> >> >> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: >> >>> I'd like to propose a `.tap` method on the Array prototype. I was able >>> to find some previous discussion here but it was off the main topic and >>> seemed to die out: https://mail.mozilla.org/ >>> pipermail/es-discuss/2015-October/044454.html >>> >>> A tap method enables the user to inspect an array in the chain. >>> >>> For example, inspection: >>> >>> If you have a chain like this: >>> >>> ``` >>> [1, 2, 3] >>> .map(num => num * 2) >>> .reduce((a, b) => a + b); >>> ``` >>> >>> When you want to see what the value of the array is between the map and >>> reduce, you would typically do this: >>> >>> ``` >>> const value = [1, 2, 3] >>> .map(num => num * 2); >>> >>> console.log(value); >>> >>> value.reduce((a, b) => a + b); >>> ``` >>> >>> With `.tap`, you'd be able to do this: >>> >>> ``` >>> [1, 2, 3] >>> .map(num => num * 2) >>> .tap(console.log.bind(console)); >>> .reduce((a, b) => a + b); >>> ``` >>> >>> `.tap` would be called once, passed the entire array as the first >>> argument to the callback, and would return the array after the callback was >>> finished. >>> >>> This isn't something that can cleanly be done with a user-land function >>> since it would have to wrap the chain, or replace all of the chained >>> functions like underscore does. >>> >>> An example of wrapping the chain: >>> >>> ``` >>> myTap( >>> ( >>> [1, 2, 3] >>> .map(num => num * 2) >>> ), >>> console.log.bind(console); >>> ) >>> .reduce((a, b) => a + b); >>> ``` >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/67ef0711/attachment-0001.html>
You could always hack it and use the third argument :D
var tap = f => (v, i, arr) => {
if (i === arr.length - 1) f(arr);
return v;
};
Fine for debugging at least, but not necessarily your overall goal.
You could always hack it and use the third argument :D ``` var tap = f => (v, i, arr) => { if (i === arr.length - 1) f(arr); return v; }; ``` Fine for debugging at least, but not necessarily your overall goal. On Sun, Jul 16, 2017 at 11:20 AM, Eli White <ecma at eli-white.com> wrote: > That leads to a different result. Map is called once for every item in the > array. > > ``` > const tap = f => x => { > f(x); > return x; > } > > [1, 2, 3] > .map(num => num * 2) > .map(tap(console.log.bind(console))) > .reduce((a, b) => a + b); > ``` > > Results in: > > ``` > 2 > 4 > 6 > ``` > > Whereas > > ``` > [1, 2, 3] > .map(num => num * 2) > .tap(console.log.bind(console)); > .reduce((a, b) => a + b); > ``` > > would result in > > ``` > [2, 4, 6] > ``` > > This is what makes it hard about being a userland function. Tap enables > the developer to act on the *entire* array, not individual items. > > On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> > wrote: > >> Sorry I meant: >> >> const tap = f => x => { >> f(x); >> return x; >> } >> >> >> Elie ROTENBERG >> Directeur général adjoint >> elie.rotenberg at webedia-group.com >> 336 89 29 98 19 >> twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg >> github elierotenberg >> 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret Cedex >> - T: 33 811 69 41 42 >> >> >> On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> >> wrote: >> >>> I think the most common use of this pattern would be debugging, and in >>> this context you don't really care to use a little helper and >>> Array.prototype.map, eg: >>> >>> const tap = f => ...args => { >>> f(...args); >>> return x; >>> }; >>> >>> [1, 2, 3] >>> .map(num => num * 2) >>> .map(tap(console.log.bind(console))); >>> .reduce((a, b) => a + b); >>> >>> >>> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: >>> >>>> I'd like to propose a `.tap` method on the Array prototype. I was able >>>> to find some previous discussion here but it was off the main topic and >>>> seemed to die out: https://mail.mozilla.org/ >>>> pipermail/es-discuss/2015-October/044454.html >>>> >>>> A tap method enables the user to inspect an array in the chain. >>>> >>>> For example, inspection: >>>> >>>> If you have a chain like this: >>>> >>>> ``` >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> .reduce((a, b) => a + b); >>>> ``` >>>> >>>> When you want to see what the value of the array is between the map and >>>> reduce, you would typically do this: >>>> >>>> ``` >>>> const value = [1, 2, 3] >>>> .map(num => num * 2); >>>> >>>> console.log(value); >>>> >>>> value.reduce((a, b) => a + b); >>>> ``` >>>> >>>> With `.tap`, you'd be able to do this: >>>> >>>> ``` >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> .tap(console.log.bind(console)); >>>> .reduce((a, b) => a + b); >>>> ``` >>>> >>>> `.tap` would be called once, passed the entire array as the first >>>> argument to the callback, and would return the array after the callback was >>>> finished. >>>> >>>> This isn't something that can cleanly be done with a user-land function >>>> since it would have to wrap the chain, or replace all of the chained >>>> functions like underscore does. >>>> >>>> An example of wrapping the chain: >>>> >>>> ``` >>>> myTap( >>>> ( >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> ), >>>> console.log.bind(console); >>>> ) >>>> .reduce((a, b) => a + b); >>>> ``` >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/9512f020/attachment.html>
Object.defineProperty(Array.prototype, 'tap', {
value: function(fn) { fn(this); return this;}
});
```js Object.defineProperty(Array.prototype, 'tap', { value: function(fn) { fn(this); return this;} }); ``` On Mon, Jul 17, 2017 at 12:15 AM, Logan Smyth <loganfsmyth at gmail.com> wrote: > You could always hack it and use the third argument :D > > ``` > var tap = f => (v, i, arr) => { > if (i === arr.length - 1) f(arr); > > return v; > }; > ``` > > Fine for debugging at least, but not necessarily your overall goal. > > On Sun, Jul 16, 2017 at 11:20 AM, Eli White <ecma at eli-white.com> wrote: > >> That leads to a different result. Map is called once for every item in >> the array. >> >> ``` >> const tap = f => x => { >> f(x); >> return x; >> } >> >> [1, 2, 3] >> .map(num => num * 2) >> .map(tap(console.log.bind(console))) >> .reduce((a, b) => a + b); >> ``` >> >> Results in: >> >> ``` >> 2 >> 4 >> 6 >> ``` >> >> Whereas >> >> ``` >> [1, 2, 3] >> .map(num => num * 2) >> .tap(console.log.bind(console)); >> .reduce((a, b) => a + b); >> ``` >> >> would result in >> >> ``` >> [2, 4, 6] >> ``` >> >> This is what makes it hard about being a userland function. Tap enables >> the developer to act on the *entire* array, not individual items. >> >> On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> >> wrote: >> >>> Sorry I meant: >>> >>> const tap = f => x => { >>> f(x); >>> return x; >>> } >>> >>> >>> Elie ROTENBERG >>> Directeur général adjoint >>> elie.rotenberg at webedia-group.com >>> 336 89 29 98 19 >>> twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg >>> github elierotenberg >>> 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret Cedex >>> - T: 33 811 69 41 42 >>> >>> >>> On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> >>> wrote: >>> >>>> I think the most common use of this pattern would be debugging, and in >>>> this context you don't really care to use a little helper and >>>> Array.prototype.map, eg: >>>> >>>> const tap = f => ...args => { >>>> f(...args); >>>> return x; >>>> }; >>>> >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> .map(tap(console.log.bind(console))); >>>> .reduce((a, b) => a + b); >>>> >>>> >>>> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: >>>> >>>>> I'd like to propose a `.tap` method on the Array prototype. I was able >>>>> to find some previous discussion here but it was off the main topic and >>>>> seemed to die out: https://mail.mozilla.org/ >>>>> pipermail/es-discuss/2015-October/044454.html >>>>> >>>>> A tap method enables the user to inspect an array in the chain. >>>>> >>>>> For example, inspection: >>>>> >>>>> If you have a chain like this: >>>>> >>>>> ``` >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> .reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> When you want to see what the value of the array is between the map >>>>> and reduce, you would typically do this: >>>>> >>>>> ``` >>>>> const value = [1, 2, 3] >>>>> .map(num => num * 2); >>>>> >>>>> console.log(value); >>>>> >>>>> value.reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> With `.tap`, you'd be able to do this: >>>>> >>>>> ``` >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> .tap(console.log.bind(console)); >>>>> .reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> `.tap` would be called once, passed the entire array as the first >>>>> argument to the callback, and would return the array after the callback was >>>>> finished. >>>>> >>>>> This isn't something that can cleanly be done with a user-land >>>>> function since it would have to wrap the chain, or replace all of the >>>>> chained functions like underscore does. >>>>> >>>>> An example of wrapping the chain: >>>>> >>>>> ``` >>>>> myTap( >>>>> ( >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> ), >>>>> console.log.bind(console); >>>>> ) >>>>> .reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss at mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170717/86e4b7f0/attachment-0001.html>
This is definitely something that can be polyfilled (with different levels of naivety) but requires modifying built-ins which is a no-no.
Here is an example that is more valuable in production than just debugging.
Many other languages that support .tap
enable a value to be returned. If
it is, that value is passed down the rest of the chain instead of the
initial value (but the return value is optional). This is also functionally
similar to .tee
in many languages (and bash).
en.wikipedia.org/wiki/Tee_(command)
One of the other common use cases for .tap
is to be able to chain methods
that act on the entire array. For example, if .reverse
wasn't part of
Array.prototype
and instead you had a user function myReverse(arr) => arr'
,
then if you wanted to convert [1,2,3]
into ["6","4","2"]
, then
you'd have to do the following. It is a bit of a contrived example since
I'm avoiding just calling myReverse
before or after the chain. Imagine a
more complex example and longer chain.
const value = [1, 2, 3].map(String);
myReverse(value).map(num => num * 2);
With .tap
, it can be part of the chain:
const value = [1, 2, 3]
.map(String)
.tap(myReverse)
.map(num => num * 2);
Obviously this could be done with reduce, but it would require myReverse
to have a different signature.
Just trying to provide some reasoning why .tap
is for more than just
debugging. :)
This is definitely something that can be polyfilled (with different levels of naivety) but requires modifying built-ins which is a no-no. Here is an example that is more valuable in production than just debugging. Many other languages that support `.tap` enable a value to be returned. If it is, that value is passed down the rest of the chain instead of the initial value (but the return value is optional). This is also functionally similar to `.tee` in many languages (and bash). https://en.wikipedia.org/wiki/Tee_(command) One of the other common use cases for `.tap` is to be able to chain methods that act on the entire array. For example, if `.reverse` wasn't part of `Array.prototype` and instead you had a user function `myReverse(arr) => arr'`, then if you wanted to convert `[1,2,3]` into `["6","4","2"]`, then you'd have to do the following. It is a bit of a contrived example since I'm avoiding just calling `myReverse` before or after the chain. Imagine a more complex example and longer chain. ``` const value = [1, 2, 3].map(String); myReverse(value).map(num => num * 2); ``` With `.tap`, it can be part of the chain: ``` const value = [1, 2, 3] .map(String) .tap(myReverse) .map(num => num * 2); ``` Obviously this could be done with reduce, but it would require `myReverse` to have a different signature. Just trying to provide some reasoning why `.tap` is for more than just debugging. :) On Sun, Jul 16, 2017 at 12:00 PM, Bob Myers <rtm at gol.com> wrote: > ```js > Object.defineProperty(Array.prototype, 'tap', { > value: function(fn) { fn(this); return this;} > }); > ``` > > On Mon, Jul 17, 2017 at 12:15 AM, Logan Smyth <loganfsmyth at gmail.com> > wrote: > >> You could always hack it and use the third argument :D >> >> ``` >> var tap = f => (v, i, arr) => { >> if (i === arr.length - 1) f(arr); >> >> return v; >> }; >> ``` >> >> Fine for debugging at least, but not necessarily your overall goal. >> >> On Sun, Jul 16, 2017 at 11:20 AM, Eli White <ecma at eli-white.com> wrote: >> >>> That leads to a different result. Map is called once for every item in >>> the array. >>> >>> ``` >>> const tap = f => x => { >>> f(x); >>> return x; >>> } >>> >>> [1, 2, 3] >>> .map(num => num * 2) >>> .map(tap(console.log.bind(console))) >>> .reduce((a, b) => a + b); >>> ``` >>> >>> Results in: >>> >>> ``` >>> 2 >>> 4 >>> 6 >>> ``` >>> >>> Whereas >>> >>> ``` >>> [1, 2, 3] >>> .map(num => num * 2) >>> .tap(console.log.bind(console)); >>> .reduce((a, b) => a + b); >>> ``` >>> >>> would result in >>> >>> ``` >>> [2, 4, 6] >>> ``` >>> >>> This is what makes it hard about being a userland function. Tap enables >>> the developer to act on the *entire* array, not individual items. >>> >>> On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> >>> wrote: >>> >>>> Sorry I meant: >>>> >>>> const tap = f => x => { >>>> f(x); >>>> return x; >>>> } >>>> >>>> >>>> Elie ROTENBERG >>>> Directeur général adjoint >>>> elie.rotenberg at webedia-group.com >>>> 336 89 29 98 19 >>>> twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg >>>> github elierotenberg >>>> 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret >>>> Cedex - T: 33 811 69 41 42 >>>> >>>> >>>> On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> >>>> wrote: >>>> >>>>> I think the most common use of this pattern would be debugging, and in >>>>> this context you don't really care to use a little helper and >>>>> Array.prototype.map, eg: >>>>> >>>>> const tap = f => ...args => { >>>>> f(...args); >>>>> return x; >>>>> }; >>>>> >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> .map(tap(console.log.bind(console))); >>>>> .reduce((a, b) => a + b); >>>>> >>>>> >>>>> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> wrote: >>>>> >>>>>> I'd like to propose a `.tap` method on the Array prototype. I was >>>>>> able to find some previous discussion here but it was off the main topic >>>>>> and seemed to die out: https://mail.mozilla.org/ >>>>>> pipermail/es-discuss/2015-October/044454.html >>>>>> >>>>>> A tap method enables the user to inspect an array in the chain. >>>>>> >>>>>> For example, inspection: >>>>>> >>>>>> If you have a chain like this: >>>>>> >>>>>> ``` >>>>>> [1, 2, 3] >>>>>> .map(num => num * 2) >>>>>> .reduce((a, b) => a + b); >>>>>> ``` >>>>>> >>>>>> When you want to see what the value of the array is between the map >>>>>> and reduce, you would typically do this: >>>>>> >>>>>> ``` >>>>>> const value = [1, 2, 3] >>>>>> .map(num => num * 2); >>>>>> >>>>>> console.log(value); >>>>>> >>>>>> value.reduce((a, b) => a + b); >>>>>> ``` >>>>>> >>>>>> With `.tap`, you'd be able to do this: >>>>>> >>>>>> ``` >>>>>> [1, 2, 3] >>>>>> .map(num => num * 2) >>>>>> .tap(console.log.bind(console)); >>>>>> .reduce((a, b) => a + b); >>>>>> ``` >>>>>> >>>>>> `.tap` would be called once, passed the entire array as the first >>>>>> argument to the callback, and would return the array after the callback was >>>>>> finished. >>>>>> >>>>>> This isn't something that can cleanly be done with a user-land >>>>>> function since it would have to wrap the chain, or replace all of the >>>>>> chained functions like underscore does. >>>>>> >>>>>> An example of wrapping the chain: >>>>>> >>>>>> ``` >>>>>> myTap( >>>>>> ( >>>>>> [1, 2, 3] >>>>>> .map(num => num * 2) >>>>>> ), >>>>>> console.log.bind(console); >>>>>> ) >>>>>> .reduce((a, b) => a + b); >>>>>> ``` >>>>>> >>>>>> _______________________________________________ >>>>>> es-discuss mailing list >>>>>> es-discuss at mozilla.org >>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>> >>>>>> >>>>> >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/b851d73c/attachment-0001.html>
I have been reading over the .forEach
with a return value discussion. I
imagine if that was added it would work with chaining and do everything
that .tap
would be capable of. Unless I have missed something?
I have been reading over the `.forEach` with a return value discussion. I imagine if that was added it would work with chaining and do everything that `.tap` would be capable of. Unless I have missed something? On Jul 16, 2017 3:55 PM, "Eli White" <ecma at eli-white.com> wrote: > This is definitely something that can be polyfilled (with different levels > of naivety) but requires modifying built-ins which is a no-no. > > Here is an example that is more valuable in production than just debugging. > > Many other languages that support `.tap` enable a value to be returned. If > it is, that value is passed down the rest of the chain instead of the > initial value (but the return value is optional). This is also functionally > similar to `.tee` in many languages (and bash). > https://en.wikipedia.org/wiki/Tee_(command) > > One of the other common use cases for `.tap` is to be able to chain > methods that act on the entire array. For example, if `.reverse` wasn't > part of `Array.prototype` and instead you had a user function > `myReverse(arr) => arr'`, then if you wanted to convert `[1,2,3]` into > `["6","4","2"]`, then you'd have to do the following. It is a bit of a > contrived example since I'm avoiding just calling `myReverse` before or > after the chain. Imagine a more complex example and longer chain. > > ``` > const value = [1, 2, 3].map(String); > myReverse(value).map(num => num * 2); > ``` > > With `.tap`, it can be part of the chain: > > ``` > const value = [1, 2, 3] > .map(String) > .tap(myReverse) > .map(num => num * 2); > ``` > > Obviously this could be done with reduce, but it would require `myReverse` > to have a different signature. > > Just trying to provide some reasoning why `.tap` is for more than just > debugging. :) > > > On Sun, Jul 16, 2017 at 12:00 PM, Bob Myers <rtm at gol.com> wrote: > >> ```js >> Object.defineProperty(Array.prototype, 'tap', { >> value: function(fn) { fn(this); return this;} >> }); >> ``` >> >> On Mon, Jul 17, 2017 at 12:15 AM, Logan Smyth <loganfsmyth at gmail.com> >> wrote: >> >>> You could always hack it and use the third argument :D >>> >>> ``` >>> var tap = f => (v, i, arr) => { >>> if (i === arr.length - 1) f(arr); >>> >>> return v; >>> }; >>> ``` >>> >>> Fine for debugging at least, but not necessarily your overall goal. >>> >>> On Sun, Jul 16, 2017 at 11:20 AM, Eli White <ecma at eli-white.com> wrote: >>> >>>> That leads to a different result. Map is called once for every item in >>>> the array. >>>> >>>> ``` >>>> const tap = f => x => { >>>> f(x); >>>> return x; >>>> } >>>> >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> .map(tap(console.log.bind(console))) >>>> .reduce((a, b) => a + b); >>>> ``` >>>> >>>> Results in: >>>> >>>> ``` >>>> 2 >>>> 4 >>>> 6 >>>> ``` >>>> >>>> Whereas >>>> >>>> ``` >>>> [1, 2, 3] >>>> .map(num => num * 2) >>>> .tap(console.log.bind(console)); >>>> .reduce((a, b) => a + b); >>>> ``` >>>> >>>> would result in >>>> >>>> ``` >>>> [2, 4, 6] >>>> ``` >>>> >>>> This is what makes it hard about being a userland function. Tap enables >>>> the developer to act on the *entire* array, not individual items. >>>> >>>> On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> >>>> wrote: >>>> >>>>> Sorry I meant: >>>>> >>>>> const tap = f => x => { >>>>> f(x); >>>>> return x; >>>>> } >>>>> >>>>> >>>>> Elie ROTENBERG >>>>> Directeur général adjoint >>>>> elie.rotenberg at webedia-group.com >>>>> 336 89 29 98 19 >>>>> twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg >>>>> github elierotenberg >>>>> 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret >>>>> Cedex - T: 33 811 69 41 42 >>>>> >>>>> >>>>> On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> >>>>> wrote: >>>>> >>>>>> I think the most common use of this pattern would be debugging, and >>>>>> in this context you don't really care to use a little helper and >>>>>> Array.prototype.map, eg: >>>>>> >>>>>> const tap = f => ...args => { >>>>>> f(...args); >>>>>> return x; >>>>>> }; >>>>>> >>>>>> [1, 2, 3] >>>>>> .map(num => num * 2) >>>>>> .map(tap(console.log.bind(console))); >>>>>> .reduce((a, b) => a + b); >>>>>> >>>>>> >>>>>> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> >>>>>> wrote: >>>>>> >>>>>>> I'd like to propose a `.tap` method on the Array prototype. I was >>>>>>> able to find some previous discussion here but it was off the main topic >>>>>>> and seemed to die out: https://mail.mozilla.org/ >>>>>>> pipermail/es-discuss/2015-October/044454.html >>>>>>> >>>>>>> A tap method enables the user to inspect an array in the chain. >>>>>>> >>>>>>> For example, inspection: >>>>>>> >>>>>>> If you have a chain like this: >>>>>>> >>>>>>> ``` >>>>>>> [1, 2, 3] >>>>>>> .map(num => num * 2) >>>>>>> .reduce((a, b) => a + b); >>>>>>> ``` >>>>>>> >>>>>>> When you want to see what the value of the array is between the map >>>>>>> and reduce, you would typically do this: >>>>>>> >>>>>>> ``` >>>>>>> const value = [1, 2, 3] >>>>>>> .map(num => num * 2); >>>>>>> >>>>>>> console.log(value); >>>>>>> >>>>>>> value.reduce((a, b) => a + b); >>>>>>> ``` >>>>>>> >>>>>>> With `.tap`, you'd be able to do this: >>>>>>> >>>>>>> ``` >>>>>>> [1, 2, 3] >>>>>>> .map(num => num * 2) >>>>>>> .tap(console.log.bind(console)); >>>>>>> .reduce((a, b) => a + b); >>>>>>> ``` >>>>>>> >>>>>>> `.tap` would be called once, passed the entire array as the first >>>>>>> argument to the callback, and would return the array after the callback was >>>>>>> finished. >>>>>>> >>>>>>> This isn't something that can cleanly be done with a user-land >>>>>>> function since it would have to wrap the chain, or replace all of the >>>>>>> chained functions like underscore does. >>>>>>> >>>>>>> An example of wrapping the chain: >>>>>>> >>>>>>> ``` >>>>>>> myTap( >>>>>>> ( >>>>>>> [1, 2, 3] >>>>>>> .map(num => num * 2) >>>>>>> ), >>>>>>> console.log.bind(console); >>>>>>> ) >>>>>>> .reduce((a, b) => a + b); >>>>>>> ``` >>>>>>> >>>>>>> _______________________________________________ >>>>>>> es-discuss mailing list >>>>>>> es-discuss at mozilla.org >>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>> >>>>>>> >>>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >>> _______________________________________________ >>> es-discuss mailing list >>> es-discuss at mozilla.org >>> https://mail.mozilla.org/listinfo/es-discuss >>> >>> >> > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/7d3cb3e9/attachment-0001.html>
I do not believe .forEach
with a return value would satisfy this usage
because with .tap
, the callback is called only once, with the first
argument being the entire array.
I do not believe `.forEach` with a return value would satisfy this usage because with `.tap`, the callback is called only once, with the first argument being the *entire* array. On Sun, Jul 16, 2017 at 3:37 PM, Vinnymac <vinnymac at gmail.com> wrote: > I have been reading over the `.forEach` with a return value discussion. I > imagine if that was added it would work with chaining and do everything > that `.tap` would be capable of. Unless I have missed something? > > On Jul 16, 2017 3:55 PM, "Eli White" <ecma at eli-white.com> wrote: > >> This is definitely something that can be polyfilled (with different >> levels of naivety) but requires modifying built-ins which is a no-no. >> >> Here is an example that is more valuable in production than just >> debugging. >> >> Many other languages that support `.tap` enable a value to be returned. >> If it is, that value is passed down the rest of the chain instead of the >> initial value (but the return value is optional). This is also functionally >> similar to `.tee` in many languages (and bash). >> https://en.wikipedia.org/wiki/Tee_(command) >> >> One of the other common use cases for `.tap` is to be able to chain >> methods that act on the entire array. For example, if `.reverse` wasn't >> part of `Array.prototype` and instead you had a user function >> `myReverse(arr) => arr'`, then if you wanted to convert `[1,2,3]` into >> `["6","4","2"]`, then you'd have to do the following. It is a bit of a >> contrived example since I'm avoiding just calling `myReverse` before or >> after the chain. Imagine a more complex example and longer chain. >> >> ``` >> const value = [1, 2, 3].map(String); >> myReverse(value).map(num => num * 2); >> ``` >> >> With `.tap`, it can be part of the chain: >> >> ``` >> const value = [1, 2, 3] >> .map(String) >> .tap(myReverse) >> .map(num => num * 2); >> ``` >> >> Obviously this could be done with reduce, but it would require >> `myReverse` to have a different signature. >> >> Just trying to provide some reasoning why `.tap` is for more than just >> debugging. :) >> >> >> On Sun, Jul 16, 2017 at 12:00 PM, Bob Myers <rtm at gol.com> wrote: >> >>> ```js >>> Object.defineProperty(Array.prototype, 'tap', { >>> value: function(fn) { fn(this); return this;} >>> }); >>> ``` >>> >>> On Mon, Jul 17, 2017 at 12:15 AM, Logan Smyth <loganfsmyth at gmail.com> >>> wrote: >>> >>>> You could always hack it and use the third argument :D >>>> >>>> ``` >>>> var tap = f => (v, i, arr) => { >>>> if (i === arr.length - 1) f(arr); >>>> >>>> return v; >>>> }; >>>> ``` >>>> >>>> Fine for debugging at least, but not necessarily your overall goal. >>>> >>>> On Sun, Jul 16, 2017 at 11:20 AM, Eli White <ecma at eli-white.com> wrote: >>>> >>>>> That leads to a different result. Map is called once for every item in >>>>> the array. >>>>> >>>>> ``` >>>>> const tap = f => x => { >>>>> f(x); >>>>> return x; >>>>> } >>>>> >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> .map(tap(console.log.bind(console))) >>>>> .reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> Results in: >>>>> >>>>> ``` >>>>> 2 >>>>> 4 >>>>> 6 >>>>> ``` >>>>> >>>>> Whereas >>>>> >>>>> ``` >>>>> [1, 2, 3] >>>>> .map(num => num * 2) >>>>> .tap(console.log.bind(console)); >>>>> .reduce((a, b) => a + b); >>>>> ``` >>>>> >>>>> would result in >>>>> >>>>> ``` >>>>> [2, 4, 6] >>>>> ``` >>>>> >>>>> This is what makes it hard about being a userland function. Tap >>>>> enables the developer to act on the *entire* array, not individual items. >>>>> >>>>> On Sun, Jul 16, 2017 at 11:10 AM, Elie Rotenberg <elie at rotenberg.io> >>>>> wrote: >>>>> >>>>>> Sorry I meant: >>>>>> >>>>>> const tap = f => x => { >>>>>> f(x); >>>>>> return x; >>>>>> } >>>>>> >>>>>> >>>>>> Elie ROTENBERG >>>>>> Directeur général adjoint >>>>>> elie.rotenberg at webedia-group.com >>>>>> 336 89 29 98 19 >>>>>> twitter elierotenberg facebook elie.rotenberg skype elie.rotenberg >>>>>> github elierotenberg >>>>>> 2, rue Paul Vaillant Couturier - CS 60102 - 92532 Levallois-Perret >>>>>> Cedex - T: 33 811 69 41 42 >>>>>> >>>>>> >>>>>> On Sun, Jul 16, 2017 at 8:09 PM, Elie Rotenberg <elie at rotenberg.io> >>>>>> wrote: >>>>>> >>>>>>> I think the most common use of this pattern would be debugging, and >>>>>>> in this context you don't really care to use a little helper and >>>>>>> Array.prototype.map, eg: >>>>>>> >>>>>>> const tap = f => ...args => { >>>>>>> f(...args); >>>>>>> return x; >>>>>>> }; >>>>>>> >>>>>>> [1, 2, 3] >>>>>>> .map(num => num * 2) >>>>>>> .map(tap(console.log.bind(console))); >>>>>>> .reduce((a, b) => a + b); >>>>>>> >>>>>>> >>>>>>> On Sun, Jul 16, 2017 at 8:00 PM, Eli White <ecma at eli-white.com> >>>>>>> wrote: >>>>>>> >>>>>>>> I'd like to propose a `.tap` method on the Array prototype. I was >>>>>>>> able to find some previous discussion here but it was off the main topic >>>>>>>> and seemed to die out: https://mail.mozilla.org/ >>>>>>>> pipermail/es-discuss/2015-October/044454.html >>>>>>>> >>>>>>>> A tap method enables the user to inspect an array in the chain. >>>>>>>> >>>>>>>> For example, inspection: >>>>>>>> >>>>>>>> If you have a chain like this: >>>>>>>> >>>>>>>> ``` >>>>>>>> [1, 2, 3] >>>>>>>> .map(num => num * 2) >>>>>>>> .reduce((a, b) => a + b); >>>>>>>> ``` >>>>>>>> >>>>>>>> When you want to see what the value of the array is between the map >>>>>>>> and reduce, you would typically do this: >>>>>>>> >>>>>>>> ``` >>>>>>>> const value = [1, 2, 3] >>>>>>>> .map(num => num * 2); >>>>>>>> >>>>>>>> console.log(value); >>>>>>>> >>>>>>>> value.reduce((a, b) => a + b); >>>>>>>> ``` >>>>>>>> >>>>>>>> With `.tap`, you'd be able to do this: >>>>>>>> >>>>>>>> ``` >>>>>>>> [1, 2, 3] >>>>>>>> .map(num => num * 2) >>>>>>>> .tap(console.log.bind(console)); >>>>>>>> .reduce((a, b) => a + b); >>>>>>>> ``` >>>>>>>> >>>>>>>> `.tap` would be called once, passed the entire array as the first >>>>>>>> argument to the callback, and would return the array after the callback was >>>>>>>> finished. >>>>>>>> >>>>>>>> This isn't something that can cleanly be done with a user-land >>>>>>>> function since it would have to wrap the chain, or replace all of the >>>>>>>> chained functions like underscore does. >>>>>>>> >>>>>>>> An example of wrapping the chain: >>>>>>>> >>>>>>>> ``` >>>>>>>> myTap( >>>>>>>> ( >>>>>>>> [1, 2, 3] >>>>>>>> .map(num => num * 2) >>>>>>>> ), >>>>>>>> console.log.bind(console); >>>>>>>> ) >>>>>>>> .reduce((a, b) => a + b); >>>>>>>> ``` >>>>>>>> >>>>>>>> _______________________________________________ >>>>>>>> es-discuss mailing list >>>>>>>> es-discuss at mozilla.org >>>>>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>>>>> >>>>>>>> >>>>>>> >>>>>> >>>>> >>>>> _______________________________________________ >>>>> es-discuss mailing list >>>>> es-discuss at mozilla.org >>>>> https://mail.mozilla.org/listinfo/es-discuss >>>>> >>>>> >>>> >>>> _______________________________________________ >>>> es-discuss mailing list >>>> es-discuss at mozilla.org >>>> https://mail.mozilla.org/listinfo/es-discuss >>>> >>>> >>> >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> >> -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/2282e3ae/attachment-0001.html>
@Vinnymac the distinction is that the tap
proposed here is not called
per-member, I think.
It has nothing specifically to do with arrays (or iterables generally);
they just happen to be the most common chaining targets. (See the example
implementation from Bob Myers above — could as readily be plopped on
Object.prototype
, provided you are feeling naughty).
Because tap isn’t particular to arrays, I think this is a good example of
something one of the proposed chain-oriented operators would be good for.
That is, ::bind
(which should be called ::call
probably?) or the more
general |>
which unpacks nested calls into a linear readable chain.
@Vinnymac the distinction is that the `tap` proposed here is not called per-member, I think. It has nothing _specifically_ to do with arrays (or iterables generally); they just happen to be the most common chaining targets. (See the example implementation from Bob Myers above). Because tap isn’t particular to arrays, I think this is a good example of something one of the proposed chain-oriented operators would be good for. That is, `::bind` (which should be called `::call` probably?) or the more general `|>` which unpacks nested calls into a linear readable chain. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/197d6a0e/attachment.html>
I don't see the point in this tap
. The myReverse
example can be written as
const value = myReverse([1, 2, 3].map(String)).map(num => num * 2);
If you don't want to write myReverse
at the beginning, you might like the pipeline proposal: gilbert/es-pipeline-operator
I think it would be something like
const value = [1, 2, 3]
.map(String)
|> myReverse
|> arr => arr.map(num => num * 2);
And similarly for the console.log
example:
[1, 2, 3]
.map(num => num * 2)
|> arr => { console.log(arr); return arr; }
|> arr => arr.reduce((a, b) => a + b);
I don't see the point in this `tap`. The `myReverse` example can be written as ```js const value = myReverse([1, 2, 3].map(String)).map(num => num * 2); ``` If you don't want to write `myReverse` at the beginning, you might like the pipeline proposal: https://github.com/gilbert/es-pipeline-operator I think it would be something like ```js const value = [1, 2, 3] .map(String) |> myReverse |> arr => arr.map(num => num * 2); ``` And similarly for the `console.log` example: ```js [1, 2, 3] .map(num => num * 2) |> arr => { console.log(arr); return arr; } |> arr => arr.reduce((a, b) => a + b); ``` --Oriol -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/c15bfef4/attachment.html>
@Eli you are correct, my mistake. I have not heard of the pipeline operator proposal before, I use a similar syntax in Elixir and enjoy it thoroughly.
@Eli you are correct, my mistake. I have not heard of the pipeline operator proposal before, I use a similar syntax in Elixir and enjoy it thoroughly. On Jul 16, 2017 7:14 PM, "Oriol _" <oriol-bugzilla at hotmail.com> wrote: > I don't see the point in this `tap`. The `myReverse` example can be > written as > > ```js > const value = myReverse([1, 2, 3].map(String)).map(num => num * 2); > ``` > > If you don't want to write `myReverse` at the beginning, you might like > the pipeline proposal: https://github.com/gilbert/es-pipeline-operator > I think it would be something like > > ```js > const value = [1, 2, 3] > .map(String) > |> myReverse > |> arr => arr.map(num => num * 2); > ``` > > And similarly for the `console.log` example: > > ```js > [1, 2, 3] > .map(num => num * 2) > |> arr => { console.log(arr); return arr; } > |> arr => arr.reduce((a, b) => a + b); > ``` > > --Oriol > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/dff6c28d/attachment.html>
This is definitely something that can be polyfilled (with different levels of naivety) but requires modifying built-ins which is a no-no.
You can safely modify Object.prototype
using Symbol
.
export const tap = Symbol('tap');
Object.prototype[tap] = function tap(f) {
f(this);
return this;
}
[1, 2, 3]
.map(n => n * 2)
[tap](console.log.bind(console))
.reduce((a, b) => a + b);
No need to add a new method to Array.prototype
and you can use it with
any type.
> This is definitely something that can be polyfilled (with different levels of naivety) but requires modifying built-ins which is a no-no. You can safely modify `Object.prototype` using `Symbol`. ```js export const tap = Symbol('tap'); Object.prototype[tap] = function tap(f) { f(this); return this; } [1, 2, 3] .map(n => n * 2) [tap](console.log.bind(console)) .reduce((a, b) => a + b); ``` No need to add a new method to `Array.prototype` and you can use it with any type. -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/c59cf282/attachment.html>
It's still extra code for mostly a debugging situation.
It's still extra code for mostly a debugging situation. On Sun, Jul 16, 2017 at 6:54 PM, Gabe Johnson <gijohnson105 at gmail.com> wrote: > > This is definitely something that can be polyfilled (with different > levels of naivety) but requires modifying built-ins which is a no-no. > > You can safely modify `Object.prototype` using `Symbol`. > > ```js > export const tap = Symbol('tap'); > > Object.prototype[tap] = function tap(f) { > f(this); > return this; > } > > [1, 2, 3] > .map(n => n * 2) > [tap](console.log.bind(console)) > .reduce((a, b) => a + b); > ``` > > No need to add a new method to `Array.prototype` and you can use it with > any type. > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss > > -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170716/0e5e2046/attachment.html>
I seriously dislike this overall proposal, and in my experience, you'd
be hard-pressed to garner any TC39 support. I could see use with
something like Array.prototype.each
being effectively
Array.prototype.forEach
, but returning the instance instead, but for
a function to basically do func(this); return this
, I don't see the
use nor need, because it's not actually solving any substantial
problem.
I personally use sequence expressions to solve this problem. It's not something that requires a builtin to do in a simpler way.
foo.then(x => (console.log(x), x))
foo.then(x => { debugger; return x })
// Once `do` expressions stabilize, it becomes simpler:
foo.then(x => (do { debugger }, x))
Isiah Meadows me at isiahmeadows.com
Looking for web consulting? Or a new website? Send me an email and we can get started. www.isiahmeadows.com
I seriously dislike this overall proposal, and in my experience, you'd be hard-pressed to garner any TC39 support. I could see use with something like `Array.prototype.each` being effectively `Array.prototype.forEach`, but returning the instance instead, but for a function to basically do `func(this); return this`, I don't see the use nor need, because it's not actually solving any substantial problem. I personally use sequence expressions to solve this problem. It's not something that *requires* a builtin to do in a simpler way. ```js foo.then(x => (console.log(x), x)) foo.then(x => { debugger; return x }) // Once `do` expressions stabilize, it becomes simpler: foo.then(x => (do { debugger }, x)) ``` ----- Isiah Meadows me at isiahmeadows.com Looking for web consulting? Or a new website? Send me an email and we can get started. www.isiahmeadows.com On Sun, Jul 16, 2017 at 11:58 PM, Frankie Bagnardi <f.bagnardi at gmail.com> wrote: > It's still extra code for mostly a debugging situation. > > On Sun, Jul 16, 2017 at 6:54 PM, Gabe Johnson <gijohnson105 at gmail.com> > wrote: >> >> > This is definitely something that can be polyfilled (with different >> > levels of naivety) but requires modifying built-ins which is a no-no. >> >> You can safely modify `Object.prototype` using `Symbol`. >> >> ```js >> export const tap = Symbol('tap'); >> >> Object.prototype[tap] = function tap(f) { >> f(this); >> return this; >> } >> >> [1, 2, 3] >> .map(n => n * 2) >> [tap](console.log.bind(console)) >> .reduce((a, b) => a + b); >> ``` >> >> No need to add a new method to `Array.prototype` and you can use it with >> any type. >> >> _______________________________________________ >> es-discuss mailing list >> es-discuss at mozilla.org >> https://mail.mozilla.org/listinfo/es-discuss >> > > > _______________________________________________ > es-discuss mailing list > es-discuss at mozilla.org > https://mail.mozilla.org/listinfo/es-discuss >
I'd like to propose a
.tap
method on the Array prototype. I was able to find some previous discussion here but it was off the main topic and seemed to die out: esdiscuss/2015- October/044454.htmlA tap method enables the user to inspect an array in the chain.
For example, inspection:
If you have a chain like this:
When you want to see what the value of the array is between the map and reduce, you would typically do this:
With
.tap
, you'd be able to do this:.tap
would be called once, passed the entire array as the first argument to the callback, and would return the array after the callback was finished.This isn't something that can cleanly be done with a user-land function since it would have to wrap the chain, or replace all of the chained functions like underscore does.
An example of wrapping the chain: