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 <[email protected]> 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" <[email protected]> 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 <[email protected]> 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 <[email protected]>
>>> 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 <[email protected]> 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 <[email protected]>
>>>>> wrote:
>>>>>
>>>>>> Sorry I meant:
>>>>>>
>>>>>> const tap = f => x => {
>>>>>>   f(x);
>>>>>>   return x;
>>>>>> }
>>>>>>
>>>>>>
>>>>>> Elie ROTENBERG
>>>>>> Directeur général adjoint
>>>>>> [email protected]
>>>>>> 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 <[email protected]>
>>>>>> 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 <[email protected]>
>>>>>>> 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
>>>>>>>> [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
>>
>>
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to