tc39 / proposal-partial-application

Proposal to add partial application to ECMAScript
https://tc39.es/proposal-partial-application/
BSD 3-Clause "New" or "Revised" License
1.02k stars 25 forks source link

Using ? outside function parantheses #20

Closed trustedtomato closed 5 years ago

trustedtomato commented 6 years ago

Is something like const startsWith = ?.startsWith(?) possible? If not, could this proposal be extended with it? It would be very useful.

obedm503 commented 6 years ago

can you expand on your proposal? what does the first ? mean? some more examples would be nice

trustedtomato commented 6 years ago

OK, so my original idea was:

const startsWith = ?.startsWith(?); // same as: const startsWith = (str, start) => str.startsWith(start);
elements.filter(?.includes('potato')); // same as: elements.filter(str => str.includes('potato'));

But this way it's ambiguous.

const test = elements.map(?.startsWith(?)); // is it const test = (x,y) => elements.map(x.startsWith(y)); or is it const test = elements.map((x,y) => x.startsWith(y));

To avoid ambiguity, the syntactic marker would be used, discussed in #13. After the syntactic marker, you could use those question marks until the end of that expression.

const test1 = ^elements.map(?.startsWith(?)); // oh it's definitely const test1 = (x,y) => elements.map(x.startsWith(y));
const test2 = elements.map(^?.startsWith(?)); // and this is the same as const test2 = elements.map((x,y) => x.startsWith(y));
obedm503 commented 6 years ago

interesting, but I would say two ? are extremely ambiguous. i would expect ?.startsWith(?) to be the same as str => str.startsWith(str)

trustedtomato commented 6 years ago

The two ? is already in the proposal.

Quoting semantics' fifth bullet-point: Given g = f(?, ?) the partially applied function result g will have a parameter for each placeholder token that is supplied in that token's position in the argument list:

const f = (x, y, z) => [x, y, z];
const g = f(?, 4, ?);
g(1, 2); // [1, 4, 2]
trustedtomato commented 6 years ago

This extension would also enable writing non-functions as functions. For example, you could write an anti-filter like:

const antiFilter = ^?.filter(? |> ^!?) // same as: const antiFilter = (arr, predicate) => arr.filter(predicate |> (itsTrue => !itsTrue)); 

Or an addition function like:

const add = ^?+?; // same as: const add = (x, y) => x + y;

An id function like:

const id = ^?;

I think this would be a huge step towards functional programming. I've always missed using operators as functions from Haskell.

trustedtomato commented 6 years ago

The involved expression lasts until the first closing bracket )}] which's start is not in that expression or a semicolon ; or a comma ,. The comma only closes the expression if there is no unclosed bracket.

Examples:

const add = ^?+?; // same as const add = (x,y) => x+y;
const notAdd = (^?)+?; // syntax error, the second ? is not involved in ^'s expression
nums.reduce(^?+?, 0); // same as nums.reduce((x,y) => x + y, 0);

Edge cases:

const x = ^10, 20; // syntax error, same as const x = () => 10, 20;
const y = ^(10, 20) // same as const y = () => (10, 20); which is the same as const y = () => 20;
const z = (^10, 20) // same as  const x = (() => 10, 20); which is the same as const x = 20;

EDIT: this whole thing basically means the precedence of the ^ operator would be 4.5

trustedtomato commented 6 years ago

But the ^ operator already exists, so we would have to change to # for example.

trustedtomato commented 6 years ago

Oh, and another idea. With this addition, the need for accessing arguments from higher ^ (#)s becomes more prominent. So the new addition: ?? means an argument from one higher, ??? means an argument from two higher, etc. Example:

const waitEvent = ^new Promise(^??.addEventListener(??, ?));
//              = ^new Promise(resolve => ?.addEventListener(?, resolve));
// with #...    = #new Primise(#??.addEventListener(??, ?));
//              = (el, event) => new Promise(resolve => el.addEventListener(event, resolve));
trustedtomato commented 6 years ago

As this would expand the proposal way too much, I've made another proposal.

achung89 commented 6 years ago

Just an observation, wouldn't the semantics of using a separate syntax for the partial expression and the partial application overlap, since a partial application is also an expression? I would think that the same syntax should be used for both, since a partial expression syntax can be used in place of a partial application syntax.

trustedtomato commented 6 years ago

I agree with you, but the interest is currently too small in that proposal to take it into account. I hope that we can do a merge sometime.

rbuckton commented 5 years ago

Closing in favor of discussion in #23 and #13.