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

Can '?' be used to declare function currying? #40

Closed mwc closed 3 years ago

mwc commented 4 years ago

Can '?' be used to declare function currying? Just like the generator function:

function ? add(a, b, c) {
  return a + b + c
}

and then the function 'add' has been curried.

usage:

add(1)(3)(5)
add()(1, 3)(5)
add(1, 3)(5)
zenflow commented 4 years ago

This is a really really really awesome idea and I hope it happens! I've wanted JS to have currying built-in (no user-land package necessary) for a long time.

This is a great idea for a syntax to support it.

My only concern is that this syntax for generator function doesn't apply to arrow functions, so would the curried function syntax apply to arrow functions? For example: Could we do const add = ? (a, b, c) => a + b + c? Honestly, it would be a little nicer, but probably not worth making the syntax incongruent with generator syntax. Anyways, I would happily type the full function ? to create a curried function.

munizart commented 3 years ago

IMHO, using a word token to mark a function as curried would place a strong parallel with async functions

function curried add(a, b, c) {
  return a + b + c
}

const add = curried (a, b, c) => a + b + c
zenflow commented 3 years ago

@munizart Yes! That's a great idea!

But if possible, I think the curried keyword should come before the function keyword, the same as with the async keyword..

async function add(a, b, c) {
  return a + b + c
}
curried function add(a, b, c) {
  return a + b + c
}
async curried function add(a, b, c) {
  return a + b + c
}
munizart commented 3 years ago

@munizart Yes! That's a great idea!

But if possible, I think the curried keyword should come before the function keyword, the same as with the async keyword..

async function add(a, b, c) {
  return a + b + c
}
curried function add(a, b, c) {
  return a + b + c
}
async curried function add(a, b, c) {
  return a + b + c
}

Yeah, i meant that hahah

ducaale commented 3 years ago

It might be possible to achieve function currying without the need for a special syntax once function decorators is added to the decorators proposal.

import {curried} from 'utils.js';

@curried function add(a, b) {
  return a + b;
} 

add(1)(2); // 3
add(1,2);  // 3
add(1);    // (b) => 1 + b

See https://github.com/tc39/proposal-pipeline-operator/issues/167#issuecomment-756643663

shadowtime2000 commented 3 years ago

It might be possible to achieve function currying without the need for a special syntax once function decorators is added to the decorators proposal.

import {curried} from 'utils.js';

@curried function add(a, b) {
  return a + b;
} 

add(1)(2); // 3
add(1,2);  // 3
add(1);    // (b) => 1 + b

See tc39/proposal-pipeline-operator#167 (comment)

@ducaale I mean like - one of the reasons for a curried keyword is so that you don't have to rely on packages, and using function decorators that still kind of happens - you need to find a package that has the decorator

kosich commented 3 years ago

Kyle Simpson made an interesting proposition with more explicit curried syntax https://gist.github.com/getify/c8f017cc45246c723af7fd1b0b6af496

function fn(x)(y)(z) {
  return x * y / z;
}

I think its worth adding to this discussion

munizart commented 3 years ago

We should think about a new proposal for those syntax propositions or do they this fit this one?

theScottyJam commented 3 years ago

I've always liked the arrow function syntax we already have to make curried functions:

const addThreeNumbs = a => b => c => a + b + c

It's true this only supports arrow functions, but usually, when following the functional paradigm in a strict way, you're not creating classes, and so don't have to worry as much about this-bindings.

Is this curried shorthand being suggested because people don't like the arrow function shorthand, or because people have needed to declare curried functions that didn't bind "this"?


Also, @munizart is probably right, I don't really see a strong connection between currying and this proposal. it would probably need to be a separate proposal.

zenflow commented 3 years ago

Is this curried shorthand being suggested because people don't like the arrow function shorthand, or because people have needed to declare curried functions that didn't bind "this"?

@theScottyJam The only limitation that I see with the higher-order arrow function style of currying is this: You need to decide to use it up-front. You may not think you need it when you write the function, and so don't bother with the extra effort of both writing it and using it that way. Or you may think that it's enough to separate the arguments into two groups. If later you decide you do want to use currying (or more currying) with that function, you will need to refactor in all the places that use it (going from add(1, 2, 3) to add(1)(2)(3)). Compare this to the ideas explored above, where we can add curried or @curried to the function declaration, keeping backward compatibility (e.g. we can still do add(1, 2, 3)) while allowing the use of currying in a more flexible way than we ever could with just higher-order arrow functions (e.g. we can do add(1)(2)(3) and add(1, 2)(3))

theScottyJam commented 3 years ago

Ah, got it. I can see the value in that.

rbuckton commented 3 years ago

What you are suggesting would be a wholly different proposal than this one, and isn't a direction I intend to take this proposal.