Skip to content

Proposal: Optional (pre-last) function arguments #5318

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
celalo opened this issue May 10, 2020 · 4 comments
Open

Proposal: Optional (pre-last) function arguments #5318

celalo opened this issue May 10, 2020 · 4 comments

Comments

@celalo
Copy link

celalo commented May 10, 2020

It has been submitted before #1091, #4148 but it has been a while since last discussed so I'd like bring it forward again. I've been an avid coffeescript user since the early days and I missing this feature all the time.

instead of:

fn = (optional_arg1, optional_arg2, cb) ->
  unless cb?
    unless optional_arg2?
      cb = optional_arg1
    else
      cb = optional_arg2

wouldn't it make it sense to have it as:

fn = (optional_arg1?, optional_arg2?, cb) ->

or better yet, decorating optional arguments with default values:

fn = (optional_arg1 ?= true, optional_arg2 ?= false, cb) ->

for example:

retriveRecords = (perPage ?= 20, page ?= 1, cb) ->

above function can be used neatly as:

retriveRecords page, cb for page in [1...20]

or as:

retriveRecords -> #callback result with arguments page=20 & page=1

my workaround at the moment is like this:

retriveRecords = ({perPage, page}, cb) ->
  perPage ?= 20
  page ?= 1

retriveRecords perPage: 50, ->
retriveRecords page: 5, ->
retriveRecords perPage: 50, page: 5, ->
retriveRecords {}, ->
@celalo celalo changed the title Proposal: Optional function arguments Proposal: Optional (pre-last) function arguments May 10, 2020
@GeoffreyBooth
Copy link
Collaborator

Can you please include what the expected output JavaScript would be for your examples?

Also are there any ECMAScript proposals at any stage of the TC39 approval pipeline that overlap with this?

@celalo
Copy link
Author

celalo commented May 10, 2020

Can you please include what the expected output JavaScript would be for your examples?

fn = (opt?, cb) -> do cb

could compile into

fn = function(opt, cb) {
  if (typeof cb === "undefined") {
    return [opt, cb] = [undefined, opt];
  }
  return cb();
};

fn = (opt ?= 42, cb) -> do cb

could compile into

fn = function(opt, cb) {
  if (typeof cb === "undefined") {
    return [opt, cb] = [42, opt];
  }
  return cb();
};

retriveRecords = (perPage ?= 20, page ?= 1, cb) ->

could compile into

retriveRecords = function(perPage, page, cb) {
  if (typeof cb === "undefined" && typeof page === "undefined") {
    return [perPage, page, cb] = [20, 1, perPage];
  } else (typeof cb === "undefined") {
    return [perPage, page, cb] = [perPage, 1, page];
  }
};

Also are there any ECMAScript proposals at any stage of the TC39 approval pipeline that overlap with this?

I could not find anything related.

@GeoffreyBooth
Copy link
Collaborator

GeoffreyBooth commented May 11, 2020

So I think you would need to compile into == null rather than === undefined to match the output of ? in other contexts (i.e. null or undefined, not just undefined). Though there's the complication that since CoffeeScript 2 default parameters are only applied for undefined, to match ES6, so arguably ? in the function parameter context should follow this undefined-only rule.

This also looks challenging to implement. Keep in mind it would need to apply also for => functions and class/object methods. Are you up for taking this on?

One more consideration is simply, how useful is this? Node uses the style in its callbacks of putting err first specifically to save people the hassle of having to parse parameters like this. The object style, e.g. fn(options), has also become increasingly popular especially with destructuring (fn = ({ foo, bar }) ->). It seems less common nowadays to see functions with lots of arguments, especially optional ones in the non-final position.

@Inve1951
Copy link
Contributor

Here's a tidy general-purpose implementation: #try

retriveRecords = (perPage, page, cb) ->
  defaults = [20, 1]
  [perPage, page, cb] = [
    defaults[0 ... retriveRecords.length - arguments.length]...
    arguments...
  ]

The signature length would probably need to be hardcoded at compile-time, and for fat arrow functions the parameter list would need an arguments replacement like soaking args.... defaults could also be inlined to not clutter the scope.

CoffeeScript (and JS for that matter) typically has callback arguments as the last function parameter to allow inline function definitions at the call site. It's true that this creates the hassle of having to rearrange the arguments if some of them are optional.

I too found this to be a common pattern/burden in my projects and am all for getting this language feature.

I'm uncertain of the proposed ?= syntax however.
I'd expect ?= to give default arguments back their CoffeeScript v1 meaning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants