Skip to content
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

Proposal: Feature Request/Suggestion: default argument using conditional assignment operator ?= #4999

Closed
sa-0001 opened this issue Mar 3, 2018 · 3 comments

Comments

@sa-0001
Copy link

sa-0001 commented Mar 3, 2018

Current Behavior

As CS2 now compiles a default function argument directly to the ES6 syntax, this is one if the major compatibility breaks with CS1, since it strictly checks for undefined but not null.

# CS1/CS2
fn = (arg = true) ->

// CS1 -> JS
var fn = function (arg) {
	if (arg == null) {
		arg = true;
	}
}

// CS2 -> JS
var fn = function (arg = true) {}

Context

Surprisingly I have found that the default argument breaking change is the one which (for me at least) will require the most effort to upgrade from CS1 to CS2. When converting, of course it's possible to rewrite every function and put the following line at the top, however that also means adding some several hundreds of lines across multiple codebases.

fn = (arg) ->
	arg ?= true

Possible Solution

May I suggest allowing use of the conditional assignment operator to allow default arguments in CS2 to work the same way they do in CS1?

# CS2
fn = (arg ?= true) ->

// CS2 -> JS
var fn = function (arg) {
	if (arg == null) {
		arg = true;
	}
}

(EDIT) I did look for issues suggesting precisely this feature and found none, although it has been suggested multiple times in comments on other issues.

@GeoffreyBooth
Copy link
Collaborator

It was discussed in #4945. I think it wasn’t implemented because if you allow it for regular arguments you should also support it for destructuring, and the destructuring case is too complicated to support in any reasonable way. In other words, (a ?= 1) -> is one thing, but ({a ?= 1}) -> is a whole separate beast.

I think where that thread concluded was that changing your =s to ?=s is a manual refactor, so if you’re already having to manually update your code it’s not that big a deal to just refactor to what the compiler would be generating:

(arg) ->
  arg ?= true

@sa-0001
Copy link
Author

sa-0001 commented Mar 9, 2018

Migrating to CS2 would require adding arg ?= true to every function in addition to the default argument arg = true, because using the default argument to denote an optional argument in a succinct way is a primary reason it exists.

It's disappointing that the very unambiguous use of ?= for default arguments could be blocked due to destructuring being ambiguous and confusing in the same scenario. I would argue that destructuring is quite often ambiguous and confusing, but this knock-on effect of blocking other features makes it a downright nuisance.

@GeoffreyBooth
Copy link
Collaborator

The 1.x code for destructuring was very, very complicated. I don’t want to resurrect it just so that we have a way to do the 1.x version of default values, whether in function arguments or destructuring. It would be a significant burden (and bug-prone) to additionally maintain this 1.x style of destructuring going forward, even if it were sectioned off behind the ?= operator.

And it would be necessary to support ?= for destructuring as well as function parameters, as default values are supported in destructuring: {a = 1} = obj is valid, so it would be inconsistent if you could do ?= for a function parameter default value but not a destructuring default value.

The ECMAScript committee made an annoying, some would argue incorrect, choice in making default values applied only when the target is undefined rather than falsy. This is discussed in great detail in #4945, but the consensus at the end was that CoffeeScript is just JavaScript, and if this is the way JavaScript went then we need to follow. We kept our current behavior for the existential operator because it has no equivalent in JavaScript (yet), but if they eventually adopt it too but use the same “undefined only” implementation, we’ll need to follow their lead.

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

No branches or pull requests

2 participants