Eli White (2017-07-16T19:54:59.000Z)
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>
github at eli-white.com (2017-07-16T19:59:47.390Z)
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. :)