Re: Re: Array.prototype.tap

2017-07-16 Thread Frankie Bagnardi
It's still extra code for mostly a debugging situation.

On Sun, Jul 16, 2017 at 6:54 PM, Gabe Johnson 
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@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: es-discuss Digest, Vol 125, Issue 51

2017-07-16 Thread David White
Too many operators can become quite confusing, having worked with many 
functional languages I find the number of operators more of a hinder than help. 
I’m very pro functional operators when they help me read the code explicitly 
rather than implicitly, for example with the `|>` pipeline operator, this helps 
you to read the code in the order of execution. With the current `|>` operator 
proposal you could write something similar with:

`const sum = numbers |> (numbers) => reduce(numbers, (a, b) => a + b);`

Passing numbers to an anonymous closure so you can have multiple arguments 
works quite elegantly.

David

> On 17 Jul 2017, at 00:11, es-discuss-requ...@mozilla.org wrote:
> 
> Send es-discuss mailing list submissions to
>   es-discuss@mozilla.org 
> 
> To subscribe or unsubscribe via the World Wide Web, visit
>   https://mail.mozilla.org/listinfo/es-discuss 
> 
> or, via email, send a message with subject or body 'help' to
>   es-discuss-requ...@mozilla.org 
> 
> You can reach the person managing the list at
>   es-discuss-ow...@mozilla.org 
> 
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of es-discuss digest..."
> Today's Topics:
> 
>   1. RE: Re: Functional Operators (doodad-js Admin)
>   2. Re: Array.prototype.tap (Eli White)
> 
> From: "doodad-js Admin" >
> Subject: RE: Re: Functional Operators
> Date: 16 July 2017 at 23:44:53 BST
> To: "'Ron Buckton'"  >, "'Darien Valentine'" 
> >, 
> >
> 
> 
> One question I have: why all these fuzzy (sorry, functional) operators? That 
> could become very hard to know what the code exactly does, and difficult to 
> debug... Are you becoming too “lazy” to type on the keyboard?
>  
>  
> From: Ron Buckton [mailto:ron.buck...@microsoft.com 
> ] 
> Sent: Sunday, July 16, 2017 3:54 PM
> To: Darien Valentine >; 
> es-discuss@mozilla.org 
> Subject: RE: Re: Functional Operators
>  
> (apologies for top posting as I’m replying from my phone)
>  
> Functional operators are not very interesting on their own, but are much more 
> interesting in terms of pipelines and partial application. However, they may 
> be a stretch in either scenario, so I’m not expecting them to be part of any 
> official proposal for pipeline/partial application at this time.
>  
> By ergonomic, I meant that ‘{+}’ is far fewer characters than ‘Math.add’. 
> Also, not every ‘+’ is arithmetic (i.e. string concatenation).
>  
> I can imagine a world where I can do:
>  
> ```js
> const sum = numbers |> reduce(?, {+});
> const joined = strings |> reduce(?, {+});
> ```
>  
> As a shorthand for:
>  
> ```js
> const sum = numbers |> reduce(?, (a, b) => a + b);
> const joined = strings |> reduce(?, (a, b) => a + b);
> ```
>  
> (I’m using `|>` here for pipeline and `?` as a positional argument for 
> partial application here)
>  
> Ron
>  
> From: Darien Valentine 
> Sent: Sunday, July 16, 2017 1:18 AM
> To: es-discuss@mozilla.org 
> Subject: Re: Re: Functional Operators
>  
> If I understand right, Ron, it means a new RHS for PrimaryExpression and 
> would behave like a reference, except that it is (presumably) not a valid 
> assignment target? Can you explain more about the ergonomics — maybe it’s 
> just from lack of familiarity, but to me this seems pretty grawlixy, like 
> something you’d see in Perl. 
>  
> In other words, I’m unsure how `arr.reduce({+})` is more ergonomic than 
> `arr.reduce(Math.add)`\*. Assuming it is and I’m just failing to see it, is 
> the benefit significant enough to merit new syntax?
>  
> (On further consideration, maybe `Reflect.add`, since `+` is not specific to 
> numeric values...)
>  
> On Sun, Jul 16, 2017 at 2:19 AM, Ron Buckton  > wrote:
> I have been looking into functional operators while working on a proposal for 
> pipeline and partial application. I’ve found that a sigil like `{+}` is just 
> as ergonomic as `(+)`, but has fewer lookahead issues with respect to regular 
> expression parsing. While `(/)` is ambiguous as to whether it would be a 
> division function or the start of a parenthesized regular expression literal, 
> `{/` is far less ambiguous in most expression positions. The only ambiguity 
> is at the statement level where `{/` could be interpreted as the start of a 
> block with a regular expression literal. However, it is fairly unlikely this 
> expression would be used in this 

Re: Re: Array.prototype.tap

2017-07-16 Thread Darien Valentine
@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.
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Eli White
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  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"  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  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 
>>> 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  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 
> wrote:
>
>> Sorry I meant:
>>
>> const tap = f => x => {
>>   f(x);
>>   return x;
>> }
>>
>>
>> Elie ROTENBERG
>> Directeur général adjoint
>> elie.rotenb...@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 
>> 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 
>>> 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


RE: Re: Functional Operators

2017-07-16 Thread doodad-js Admin
One question I have: why all these fuzzy (sorry, functional) operators? That
could become very hard to know what the code exactly does, and difficult to
debug... Are you becoming too "lazy" to type on the keyboard?

 

 

From: Ron Buckton [mailto:ron.buck...@microsoft.com] 
Sent: Sunday, July 16, 2017 3:54 PM
To: Darien Valentine ; es-discuss@mozilla.org
Subject: RE: Re: Functional Operators

 

(apologies for top posting as I'm replying from my phone)

 

Functional operators are not very interesting on their own, but are much
more interesting in terms of pipelines and partial application. However,
they may be a stretch in either scenario, so I'm not expecting them to be
part of any official proposal for pipeline/partial application at this time.

 

By ergonomic, I meant that '{+}' is far fewer characters than 'Math.add'.
Also, not every '+' is arithmetic (i.e. string concatenation).

 

I can imagine a world where I can do:

 

```js

const sum = numbers |> reduce(?, {+});

const joined = strings |> reduce(?, {+});

```

 

As a shorthand for:

 

```js

const sum = numbers |> reduce(?, (a, b) => a + b);

const joined = strings |> reduce(?, (a, b) => a + b);

```

 

(I'm using `|>` here for pipeline and `?` as a positional argument for
partial application here)

 

Ron

 

From: Darien Valentine  
Sent: Sunday, July 16, 2017 1:18 AM
To: es-discuss@mozilla.org  
Subject: Re: Re: Functional Operators

 

If I understand right, Ron, it means a new RHS for PrimaryExpression and
would behave like a reference, except that it is (presumably) not a valid
assignment target? Can you explain more about the ergonomics - maybe it's
just from lack of familiarity, but to me this seems pretty grawlixy, like
something you'd see in Perl. 

 

In other words, I'm unsure how `arr.reduce({+})` is more ergonomic than
`arr.reduce(Math.add)`\*. Assuming it is and I'm just failing to see it, is
the benefit significant enough to merit new syntax?

 

(On further consideration, maybe `Reflect.add`, since `+` is not specific to
numeric values...)

 

On Sun, Jul 16, 2017 at 2:19 AM, Ron Buckton  > wrote:

I have been looking into functional operators while working on a proposal
for pipeline and partial application. I've found that a sigil like `{+}` is
just as ergonomic as `(+)`, but has fewer lookahead issues with respect to
regular expression parsing. While `(/)` is ambiguous as to whether it would
be a division function or the start of a parenthesized regular expression
literal, `{/` is far less ambiguous in most expression positions. The only
ambiguity is at the statement level where `{/` could be interpreted as the
start of a block with a regular expression literal. However, it is fairly
unlikely this expression would be used in this position, and this can be
mitigated using parentheses just as we do for object assignment patterns in
destructuring assignments.

 

The other ambiguous case is how to differentiate between overloaded binary
and unary operators. For that, I've considered following the approach taken
by F# and prefixing overloaded unary operators with tilde. As such `{+}`
would always be a binary plus function, while `{~+}` would be the unary plus
function. In the same vein, `{-}` would be binary minus, while `{~-}` would
be the unary minus function. For non-overloaded unary operators the prefix
is unnecessary, so `{~}` and `{!}` would not be prefixed.

 

While built-ins could serve this case, they are far less ergonomic than a
shorthand sigil for an operator. On the other hand, we could have both, with
the operator sigils acting as shorthand for the long-form built-in methods.
Either way, I would expect `{+} === {+}` as there is no sense in allocating
a fresh function object each time it is encountered. Ideally, these would be
frozen functions that are created once per realm and have the same semantics
as an arrow function (i.e. [[Call]] but no [[Construct]], etc.).

 

Ron

 

From: es-discuss [mailto:es-discuss-boun...@mozilla.org
 ] On Behalf Of Darien Valentine
Sent: Monday, July 10, 2017 3:08 PM
To: es-discuss@mozilla.org  
Subject: Re: Re: Functional Operators

 

Minor point regarding the syntax given here: introducing `(/)` would likely
be problematic because it breaks the constraint that there are no positions
in the grammar where both a division operator and a regular expression
literal could be valid continuations.

 

(Perhaps new built-ins like `Math.add` etc might represent a more consistent
approach to the issue of operators not being function references?)

 

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Vinnymac
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"  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  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 
>> 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  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 
 wrote:

> Sorry I meant:
>
> const tap = f => x => {
>   f(x);
>   return x;
> }
>
>
> Elie ROTENBERG
> Directeur général adjoint
> elie.rotenb...@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 
> 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 
>> 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:
>>>
>>> ```

Re: Array.prototype.tap

2017-07-16 Thread Eli White
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  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 
> 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  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 
>>> wrote:
>>>
 Sorry I meant:

 const tap = f => x => {
   f(x);
   return x;
 }


 Elie ROTENBERG
 Directeur général adjoint
 elie.rotenb...@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 
 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  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 

RE: Re: Functional Operators

2017-07-16 Thread Ron Buckton
(apologies for top posting as I’m replying from my phone)

Functional operators are not very interesting on their own, but are much more 
interesting in terms of pipelines and partial application. However, they may be 
a stretch in either scenario, so I’m not expecting them to be part of any 
official proposal for pipeline/partial application at this time.

By ergonomic, I meant that ‘{+}’ is far fewer characters than ‘Math.add’. Also, 
not every ‘+’ is arithmetic (i.e. string concatenation).

I can imagine a world where I can do:

```js
const sum = numbers |> reduce(?, {+});
const joined = strings |> reduce(?, {+});
```

As a shorthand for:

```js
const sum = numbers |> reduce(?, (a, b) => a + b);
const joined = strings |> reduce(?, (a, b) => a + b);
```

(I’m using `|>` here for pipeline and `?` as a positional argument for partial 
application here)

Ron

From: Darien Valentine
Sent: Sunday, July 16, 2017 1:18 AM
To: es-discuss@mozilla.org
Subject: Re: Re: Functional Operators

If I understand right, Ron, it means a new RHS for PrimaryExpression and would 
behave like a reference, except that it is (presumably) not a valid assignment 
target? Can you explain more about the ergonomics — maybe it’s just from lack 
of familiarity, but to me this seems pretty grawlixy, like something you’d see 
in Perl.

In other words, I’m unsure how `arr.reduce({+})` is more ergonomic than 
`arr.reduce(Math.add)`\*. Assuming it is and I’m just failing to see it, is the 
benefit significant enough to merit new syntax?

(On further consideration, maybe `Reflect.add`, since `+` is not specific to 
numeric values...)

On Sun, Jul 16, 2017 at 2:19 AM, Ron Buckton 
> wrote:
I have been looking into functional operators while working on a proposal for 
pipeline and partial application. I’ve found that a sigil like `{+}` is just as 
ergonomic as `(+)`, but has fewer lookahead issues with respect to regular 
expression parsing. While `(/)` is ambiguous as to whether it would be a 
division function or the start of a parenthesized regular expression literal, 
`{/` is far less ambiguous in most expression positions. The only ambiguity is 
at the statement level where `{/` could be interpreted as the start of a block 
with a regular expression literal. However, it is fairly unlikely this 
expression would be used in this position, and this can be mitigated using 
parentheses just as we do for object assignment patterns in destructuring 
assignments.

The other ambiguous case is how to differentiate between overloaded binary and 
unary operators. For that, I’ve considered following the approach taken by F# 
and prefixing overloaded unary operators with tilde. As such `{+}` would always 
be a binary plus function, while `{~+}` would be the unary plus function. In 
the same vein, `{-}` would be binary minus, while `{~-}` would be the unary 
minus function. For non-overloaded unary operators the prefix is unnecessary, 
so `{~}` and `{!}` would not be prefixed.

While built-ins could serve this case, they are far less ergonomic than a 
shorthand sigil for an operator. On the other hand, we could have both, with 
the operator sigils acting as shorthand for the long-form built-in methods. 
Either way, I would expect `{+} === {+}` as there is no sense in allocating a 
fresh function object each time it is encountered. Ideally, these would be 
frozen functions that are created once per realm and have the same semantics as 
an arrow function (i.e. [[Call]] but no [[Construct]], etc.).

Ron

From: es-discuss 
[mailto:es-discuss-boun...@mozilla.org] 
On Behalf Of Darien Valentine
Sent: Monday, July 10, 2017 3:08 PM
To: es-discuss@mozilla.org
Subject: Re: Re: Functional Operators

Minor point regarding the syntax given here: introducing `(/)` would likely be 
problematic because it breaks the constraint that there are no positions in the 
grammar where both a division operator and a regular expression literal could 
be valid continuations.

(Perhaps new built-ins like `Math.add` etc might represent a more consistent 
approach to the issue of operators not being function references?)

___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Bob Myers
```js
Object.defineProperty(Array.prototype, 'tap', {
  value: function(fn) { fn(this); return this;}
});
```

On Mon, Jul 17, 2017 at 12:15 AM, Logan Smyth  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  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 
>> wrote:
>>
>>> Sorry I meant:
>>>
>>> const tap = f => x => {
>>>   f(x);
>>>   return x;
>>> }
>>>
>>>
>>> Elie ROTENBERG
>>> Directeur général adjoint
>>> elie.rotenb...@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 
>>> 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  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@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>

>>>
>>
>> ___
>> es-discuss mailing list
>> es-discuss@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Logan Smyth
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  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 
> wrote:
>
>> Sorry I meant:
>>
>> const tap = f => x => {
>>   f(x);
>>   return x;
>> }
>>
>>
>> Elie ROTENBERG
>> Directeur général adjoint
>> elie.rotenb...@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 
>> 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  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@mozilla.org
 https://mail.mozilla.org/listinfo/es-discuss


>>>
>>
>
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Eli White
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  wrote:

> Sorry I meant:
>
> const tap = f => x => {
>   f(x);
>   return x;
> }
>
>
> Elie ROTENBERG
> Directeur général adjoint
> elie.rotenb...@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  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  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@mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Elie Rotenberg
Sorry I meant:

const tap = f => x => {
  f(x);
  return x;
}


Elie ROTENBERG
Directeur général adjoint
elie.rotenb...@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  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  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@mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Array.prototype.tap

2017-07-16 Thread Elie Rotenberg
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  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@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: A twist on functional operatorsr

2017-07-16 Thread Alexander Jones
I think JavaScript has reached "peak token"... I also wanted to use the #
for generic map/list literal syntax: https://esdiscuss.org/topic/map-literal

On 15 July 2017 at 04:24, Isiah Meadows  wrote:

> Few nits inline:
>
> -
>
> Isiah Meadows
> m...@isiahmeadows.com
>
> Looking for web consulting? Or a new website?
> Send me an email and we can get started.
> www.isiahmeadows.com
>
>
> On Fri, Jul 14, 2017 at 11:11 PM, Bob Myers  wrote:
> > The proposal to write `arr.reduce((+))`, with `(+)` as an alternative to
> > `(a, b) => a + b` is admirably concise, but syntactically challenging.
>
> Actually, it's not as *syntactically* challenging as you might think;
> it can be discerned just by recognizing the token sequence `(` @ `)`,
> where @ is the operator's token in question.
>
> >
> > The idea is a new form of function we'll call a "pound function",
> written as
> > `#{ }`, Within the body, parameters are available as `#0`, `#1`, etc.
>
> Potential complication: the parameter names visually conflict with the
> private member proposal.
>
> https://github.com/tc39/proposal-class-fields
>
> >
> > ```js
> > arr.reduce(#{# + #})
> > arr.sort(#{#.order - #.order})
> > ```
>
> This quite honestly looks like line noise. Also, it doesn't look clear
> at a glance whether it should be equivalent to `(a, b) => a + b` or `a
> => a + a` (using the first example).
>
> >
> > If need be, we can define `...##` inside pound functions as referring to
> the
> > argument list, so
> >
> > ```js
> > const sumParams = #{##.reduce(#{# + #})};
> > ```
>
> That does not look very elegant nor readable.
>
> >
> > Ugh. Anyway, I will leave it others to opine on whether this cryptic
> syntax
> > is worth the trouble, issues related to nested pound functions, etc. etc.
> >
>
> You might want to investigate Clojure's [1] and Swift's [2] similar
> existing syntaxes for this.
>
> [1]: https://coderwall.com/p/panlza/function-syntax-in-clojure
> [2]: https://developer.apple.com/library/content/documentation/
> Swift/Conceptual/Swift_Programming_Language/Functions.html
>
> >
> > Bob
> >
> >
> >
> > ___
> > es-discuss mailing list
> > es-discuss@mozilla.org
> > https://mail.mozilla.org/listinfo/es-discuss
> >
> ___
> es-discuss mailing list
> es-discuss@mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Re: Functional Operators

2017-07-16 Thread Darien Valentine
If I understand right, Ron, it means a new RHS for PrimaryExpression and
would behave like a reference, except that it is (presumably) not a valid
assignment target? Can you explain more about the ergonomics — maybe it’s
just from lack of familiarity, but to me this seems pretty grawlixy, like
something you’d see in Perl.

In other words, I’m unsure how `arr.reduce({+})` is more ergonomic than
`arr.reduce(Math.add)`\*. Assuming it is and I’m just failing to see it, is
the benefit significant enough to merit new syntax?

(On further consideration, maybe `Reflect.add`, since `+` is not specific
to numeric values...)

On Sun, Jul 16, 2017 at 2:19 AM, Ron Buckton 
wrote:

> I have been looking into functional operators while working on a proposal
> for pipeline and partial application. I’ve found that a sigil like `{+}` is
> just as ergonomic as `(+)`, but has fewer lookahead issues with respect to
> regular expression parsing. While `(/)` is ambiguous as to whether it would
> be a division function or the start of a parenthesized regular expression
> literal, `{/` is far less ambiguous in most expression positions. The only
> ambiguity is at the statement level where `{/` could be interpreted as the
> start of a block with a regular expression literal. However, it is fairly
> unlikely this expression would be used in this position, and this can be
> mitigated using parentheses just as we do for object assignment patterns in
> destructuring assignments.
>
>
>
> The other ambiguous case is how to differentiate between overloaded binary
> and unary operators. For that, I’ve considered following the approach taken
> by F# and prefixing overloaded unary operators with tilde. As such `{+}`
> would always be a binary plus function, while `{~+}` would be the unary
> plus function. In the same vein, `{-}` would be binary minus, while `{~-}`
> would be the unary minus function. For non-overloaded unary operators the
> prefix is unnecessary, so `{~}` and `{!}` would not be prefixed.
>
>
>
> While built-ins could serve this case, they are far less ergonomic than a
> shorthand sigil for an operator. On the other hand, we could have both,
> with the operator sigils acting as shorthand for the long-form built-in
> methods. Either way, I would expect `{+} === {+}` as there is no sense in
> allocating a fresh function object each time it is encountered. Ideally,
> these would be frozen functions that are created once per realm and have
> the same semantics as an arrow function (i.e. [[Call]] but no
> [[Construct]], etc.).
>
>
>
> Ron
>
>
>
> *From:* es-discuss [mailto:es-discuss-boun...@mozilla.org] *On Behalf Of 
> *Darien
> Valentine
> *Sent:* Monday, July 10, 2017 3:08 PM
> *To:* es-discuss@mozilla.org
> *Subject:* Re: Re: Functional Operators
>
>
>
> Minor point regarding the syntax given here: introducing `(/)` would
> likely be problematic because it breaks the constraint that there are no
> positions in the grammar where both a division operator and a regular
> expression literal could be valid continuations.
>
>
>
> (Perhaps new built-ins like `Math.add` etc might represent a more
> consistent approach to the issue of operators not being function
> references?)
>
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


RE: Re: Functional Operators

2017-07-16 Thread Ron Buckton
I have been looking into functional operators while working on a proposal for 
pipeline and partial application. I’ve found that a sigil like `{+}` is just as 
ergonomic as `(+)`, but has fewer lookahead issues with respect to regular 
expression parsing. While `(/)` is ambiguous as to whether it would be a 
division function or the start of a parenthesized regular expression literal, 
`{/` is far less ambiguous in most expression positions. The only ambiguity is 
at the statement level where `{/` could be interpreted as the start of a block 
with a regular expression literal. However, it is fairly unlikely this 
expression would be used in this position, and this can be mitigated using 
parentheses just as we do for object assignment patterns in destructuring 
assignments.

The other ambiguous case is how to differentiate between overloaded binary and 
unary operators. For that, I’ve considered following the approach taken by F# 
and prefixing overloaded unary operators with tilde. As such `{+}` would always 
be a binary plus function, while `{~+}` would be the unary plus function. In 
the same vein, `{-}` would be binary minus, while `{~-}` would be the unary 
minus function. For non-overloaded unary operators the prefix is unnecessary, 
so `{~}` and `{!}` would not be prefixed.

While built-ins could serve this case, they are far less ergonomic than a 
shorthand sigil for an operator. On the other hand, we could have both, with 
the operator sigils acting as shorthand for the long-form built-in methods. 
Either way, I would expect `{+} === {+}` as there is no sense in allocating a 
fresh function object each time it is encountered. Ideally, these would be 
frozen functions that are created once per realm and have the same semantics as 
an arrow function (i.e. [[Call]] but no [[Construct]], etc.).

Ron

From: es-discuss [mailto:es-discuss-boun...@mozilla.org] On Behalf Of Darien 
Valentine
Sent: Monday, July 10, 2017 3:08 PM
To: es-discuss@mozilla.org
Subject: Re: Re: Functional Operators

Minor point regarding the syntax given here: introducing `(/)` would likely be 
problematic because it breaks the constraint that there are no positions in the 
grammar where both a division operator and a regular expression literal could 
be valid continuations.

(Perhaps new built-ins like `Math.add` etc might represent a more consistent 
approach to the issue of operators not being function references?)
___
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss