Skip to content
This repository has been archived by the owner on Feb 19, 2018. It is now read-only.

CS2 Discussion: Features: const assignment operator #31

Closed
GeoffreyBooth opened this issue Sep 7, 2016 · 30 comments
Closed

CS2 Discussion: Features: const assignment operator #31

GeoffreyBooth opened this issue Sep 7, 2016 · 30 comments

Comments

@GeoffreyBooth
Copy link
Collaborator

GeoffreyBooth commented Sep 7, 2016

Branching off from #1 and #30, I thought it would be good to have a thread dedicated to discussing the proposed new operator for explicitly declaring and assigning a variable as a const. This thread is not for debating automatic let assignment, or whether we should change other things related to variable assignment. Just const. For other topics, please comment on other issue threads.

The consensus from #1 seems to be to add an := operator that works like =, but declares and assigns a variable as a const. So:

foo := 42

becomes:

const foo = 42;

This has the advantage that it’s not a breaking change; currently := fails to compile. There is no need to support ?:=, since by definition constants can’t be reassigned.

Nothing else would be changed by adding this new operator. Normal assignment is handled as it is today, with var. Even though using := would cause const to be in the generated output, this feature is “opt in” like modules and the same warning would apply about transpiling CoffeeScript’s output.

If people like the idea but disagree with the syntax, I invite you to propose an alternate syntax that isn’t a breaking change. Simply following ES2015, with a syntax like const foo = 42, is an option since const is already a reserved word in CoffeeScript.

So I think the debate is: should we add this at all? And if so, this syntax or some other backwards-compatible syntax?

@zeekay
Copy link

zeekay commented Sep 7, 2016

I prefer matching JavaScript here. It's less confusing to newcomers, matches compiled output exactly, etc. Seems preferable for a minor ES6 feature of limited utility.

As const is a reserved word passing through const foo = 42 would not be a backwards-incompatible change as it does not currently compile.

I would much rather see := used for let declaration which would make it easy to avoid shadowing outer variables explicitly (and remove one of the greatest gripes with the language).

@GeoffreyBooth
Copy link
Collaborator Author

I take it back, I didn’t notice that const was reserved. I’ll update my leading post.

@lydell
Copy link

lydell commented Sep 7, 2016

I tend to use const for every single variable (except when I more or less have to reassign a variable) when I write ES2015+ code. So I wouldn't the short := operator. But typing const in JS doesn't bother my that much either.

@zeekay
Copy link

zeekay commented Sep 7, 2016

I can see the value of := as a shorthand if it's your default declaration (I would prefer to optimize for let). I tend to use const pretty sparingly in ES2015+ code and other languages (like Go). Top level bindings are about all I ever use const for. Having managed a team of Go developers the last couple years I've not seen it used for much else (but that might be my bad influence on them).

I would still prefer := used elsewhere, I'll submit a proposal for my suggested usage which can be weighed against it's use for const declaration here.

@DomVinyard
Copy link

DomVinyard commented Sep 7, 2016

I'll drop my opinion on this here by way of completeness (#30). I strongly believe that the concept of an exposed const does not belong in CoffeeScript. Frankly, that it doesn't even belong in a discussion about CoffeeScript.

@rattrayalex
Copy link
Contributor

I tend to use const pretty sparingly in ES2015+ code

that's not true for many people; see the discussion in #1 .

Having managed a team of Go developers the last couple years

that's not true for many coffeescript developers either 😉

@rattrayalex
Copy link
Contributor

How parseable would const x = ... be?

@GeoffreyBooth
Copy link
Collaborator Author

If we could somehow automatically choose var or const (or let) as appropriate, that would seem to be the ideal solution, as then people could continue their blissful state of never having to worry about var, or now const, but still get the (perhaps theoretical, at least for now) gains of code output with consts everywhere. Automatically choosing var or const as appropriate would mean we would need to introduce a flag, since there wouldn’t be new syntax with which people could “opt-in,” like import for modules; but an --esnext flag or similar is probably inevitable at some point anyway.

What’s lost by automatic const assignment is the intentionality that typing const provides in ES2015. It’s telling the runtime, “throw an error if I mistakenly reassign this variable!” I think a lot of people find value in that; though that doesn’t mean it needs to become part of CoffeeScript. We’re not becoming TypeScript anytime soon. Is the lack of this something that people would miss?

I think we could, potentially, automatically assign variables with const. Having just spent way too much time thinking about modules, one of the nice things about variables that are imported is that they’re read-only—consts, essentially. That means that the compiler would never need to look beyond the current file’s scope to determine if a variable in that file should be declared with const or with var/let: if it’s reassigned in this file, it must become a var or let; if it’s not, it can become a const because any other file that imports this one would get it as a const (no matter how it’s declared in this file). Am I correct about this? Is there a scenario I’m not thinking of where the compiler might not be able to tell if a variable ever gets reassigned (something returned from a function, perhaps)?

@rattrayalex
Copy link
Contributor

I don't quite see the point in an inferred const? (As discussed elsewhere). If people want pretty output they can use decaffeinate.

@lydell
Copy link

lydell commented Sep 8, 2016

Personally, I don't care about any theoretical performance benefit or something like that by using const. For me, it's all about stopping myself from re-assigning variables, because I find my code easier to understand then.

@GeoffreyBooth
Copy link
Collaborator Author

So @rattrayalex and @lydell want the explicit “I want the compiler to fail if I reassign this variable” while @DomVinyard and @greghuc in #30 want to preserve “I don’t need to think about how my variables are assigned.”

We get the former with := (or a const keyword), and the latter with automatic const. I guess the language could have both, though everyone would need to learn both.

@JimPanic
Copy link
Contributor

JimPanic commented Sep 8, 2016

👍 for explicit

Implicit const is not worth implementing. There is absolutely no benefit to it.

@mrmowgli
Copy link

+1 for explicit. For both const and let.
I can see some value in having a shorthand, however for const I find that the keyword is actually very descriptive and readable.

Unfortunately it seems that const refers only to the reference of the variable not changing, rather than variable immutability. Perhaps const could pass through, and := could mean the variable cannot be altered. Or since CS could actually clarify this, just use const but add immuteablity.

@GeoffreyBooth
Copy link
Collaborator Author

@JimPanic there is actually a benefit to implicit const, but it’s the same benefit from let: block scope. You can run this code in Chrome DevTools console today:

if (true) {
  var a = 1;
  let b = 2;
  const c = 3;
}
console.log(a); // 1
console.log(b); // Uncaught ReferenceError: b is not defined
console.log(c); // Uncaught ReferenceError: c is not defined

Also theoretically runtimes should be more performant with const than var, though I don’t know if such improvements have happened yet. But they should come eventually.

@GeoffreyBooth
Copy link
Collaborator Author

I’m starting to think it doesn’t make sense to implement only const. Doing so would mean that one could declare a block-scoped variable—but only via const. (See the variable c in my previous comment.) I think if we’re going to allow block-scoped variables, we need to allow both let and const. I’ve opened #35 for that approach.

@GeoffreyBooth
Copy link
Collaborator Author

I’m going to close this in favor of #35, unless anyone objects.

@rattrayalex
Copy link
Contributor

I object 😉

const is a separate feature, primarily focused on preventing reassignment, and secondarily about block scoping.

Regardless of whether const is worth implementing, it's worth considering on its own in my opinion.

@GeoffreyBooth
Copy link
Collaborator Author

How would you deal with the side effect that outputting const means that variables declared with := would be block-scoped, while variables declared with = would be function-scoped?

@rattrayalex
Copy link
Contributor

A line of documentation 😉

@rattrayalex
Copy link
Contributor

The ability to declare some variables as block, and some as lexical, is a "feature" of JavaScript, bless-its-heart.

@rattrayalex
Copy link
Contributor

And the number of times when you really don't want coffeescript's current scoping, and really want block scoping instead, and can't use const, is probably extremely low.

@GeoffreyBooth
Copy link
Collaborator Author

I think if we introduce into CoffeeScript the ability to declare a block-scoped variable, we can’t force it to be unreassignable. If we give people const, we need to also give them let.

Maybe the times when someone would want let instead of var would be low, but I think it’s way too confusing for variable assignment to not offer them that option.

@rattrayalex
Copy link
Contributor

If we give people const, we need to also give them let.

In theory, that's true.

In practice, we can give the one without the other, and very few people will run into difficulties.

@rattrayalex
Copy link
Contributor

However, if you'd like to propose completely replacing var with let in CS2, that might be reasonable in the other thread.

... in any case, I personally think this thread should be kept alive for discussion, regardless of whether you think it will ultimately make sense to merge.

@GeoffreyBooth GeoffreyBooth reopened this Sep 16, 2016
@GeoffreyBooth
Copy link
Collaborator Author

I disagree that the amount of times people would want let would be low. Many of CoffeeScript’s users have some experience with ES2015, and are used to using let and const exclusively for all their variable declarations. If we give them a way to generate const, they’ll also look for a way to generate let, and if they don’t find it they’ll be confused.

I’m not convinced we should mess with variable assignment. Perhaps one = is better than three.

@mrmowgli
Copy link

We definitely don't want to take away the ability to use var when they expect it. Especially when dealing with closures.

@jcollum
Copy link

jcollum commented Sep 16, 2016

Keep in mind I'm not any good at writing transpilers: why not just let people use let/const and default to var if they don't?

let a = 1 # output let
const a = 1 # output const
a = 1 # output defaults to var

@GeoffreyBooth
Copy link
Collaborator Author

@jcollum there’s no reason the transpiler couldn’t. It was a core design decision of CoffeeScript, though, that developers wouldn’t have to think about variable declaration. That’s why CoffeeScript groups together all variables used in a scope to a var declaration line at the top of each scope. Adding the ability to specify let or const, whether with a keyword or with an operator, violates this design principle.

Not everyone agrees with this design decision, clearly. And they may have more ammo to their argument since ES2015 introduced let and const. But it’s hard to know if this is something we should change, since the agitators are always louder on GitHub than the people who prefer the status quo, even though there may be more people out there who prefer things as they are.

@jcollum
Copy link

jcollum commented Sep 16, 2016

I like the design principle of "Use a default but allow people to override it". I'd prefer not to use backticks to override it. 2¢

@GeoffreyBooth
Copy link
Collaborator Author

See this comment. I really don’t think allowing const without let is feasible, for all the other differences that const has from var aside from unreassignability. I still think we should close this issue and leave #35 as the only viable option for supporting let/const.

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

No branches or pull requests

8 participants