Closed coffeescriptbot closed 6 years ago
From @carlsmith on July 12, 2016 0:24
Whether we have let
and var
or not is a different question than whether we have const
. The first two are related to scope, and const
is about reassignment.
We should keep this discussion about let
and var
, and move const
to a new issue.
Should we even keep CoffeeScript's nonlocal assignment rule? If were making breaking changes, we should consider changing that as it was quite controversial - all assignments are currently nonlocal. The name lookup starts locally, and works outwards until it finds the name and reassigns it. If it doesn't find the name, the assignment is local.
In Python, all assignments are just local, which is what you normally want to happen. Lexical scope exists to keep variables locally defined. You never have to worry about clobbering something in the global scope with a local variable like you do in JS and CoffeeScript.
The problem with Python is that it uses nonlocal
statements when you want to reassign names in outer scopes, the way CoffeeScript does by default, and we really want to avoid var
and let
and any other assignment keywords. They're especially awkward in a language where everything is an expression.
I think all assignments should be local, and we should have a variable available inside each function, just like arguments
, called outer
, that's a reference to the function's outer scope.
You would use outer
the same way we use window
in the browser to do global assignments:
outer.x = 1
If you had functions nested inside of each other, each lexical scope would have its own outer
, so it would naturally be recursive. You could do outer.outer.outer...
all the way to the global scope.
Assignments should have always been local, and it's natural to extend the idea behind window
to all scopes. Then you don't need assignment keywords, can access any scope, and it works naturally as an expression.
From @rattrayalex on July 12, 2016 4:55
const
is now often the default in ES6 code. Making it convenient to use would be a plus. But not necessarily a priority.
My hunch is the outer
proposal, while interesting, would be too far a departure to take on right away.
From @rattrayalex on July 12, 2016 4:58
I don't think there's much reason to use let
since coffeescript's var
's have (most of) the same benefits; they are block-scoped.
If adding a const
keyword isn't too hard, it might be worthwhile.
An alternative would be to have all variables by const
by default, and allow explicit var
or let
declarations. I assume this would be more work, as the scoping code coffeescript undertakes would be mostly-removed.
From @DomVinyard on July 12, 2016 8:24
You could do outer.outer.outer... all the way to the global scope.
That sounds like an absolute nightmare. Hard-coding your depth in the scope.
It will be very easy to reimagine all of coffeescript's features under the mandate of 'allowing breaking changes' - but I think there is a good case for picking a few bits of low hanging fruit and then addressing the rest once we're up and running. let/var/const would be a good candidate for leaving alone, i think.
From @carlsmith on July 15, 2016 16:11
I don't see a problem with absolute scope references, when scope is already lexical. Still, we have more worthwhile stuff to discuss, so yeah, forget it.
From @JimPanic on July 19, 2016 9:17
I really want to see const
in this new endeavour in one way or another. Maybe not in the first iteration, but definitely when targeting ES6. This is a key feature for me (and I guess a lot of other people as well) in ES6.
Regarding scoping, I'm in favour of leaving lexical scope as-is as well. In the future it might be a good idea to make let
the default, const
easy to use and var
the least common thing syntactically.
From @carlsmith on July 19, 2016 13:20
Hi @JimPanic, welcome.
Regarding scoping, I'm in favour of leaving lexical scope as-is as well.
You misunderstood the problem I was trying to address. CoffeeScript will always have lexical scope as-is. No one wants to change that. It's the way CoffeeScript mandates that all assignments are nonlocal that's the issue. It's always been a pretty controversial feature, and one of the most popular criticisms of CoffeeScript. For an example of the feature, here's two seemingly similar blocks of code, the first is CoffeeScript, the second is Python. They do different things though:
x = false
do ->
x = true
console.log x # true
console.log x # true
In CoffeeScript, the outer x
is clobbered by the inner assignment. Whereas, without an explicit nonlocal x
statement, Python will never clobber names outside the local namespace.
x = False
def f():
x = True
print x # True
f()
print x # False
We can avoid clobbering x
in CoffeeScript too, if we introduce the name into the local namespace as a parameter, but you still have to know that that name exists in some outer scope to preempt the clobbering.
x = false
do (x) ->
x = true
console.log x # true
console.log x # false
Lacking any real evidence, I can just say from experience with Python that nonlocal assignment is pretty rare. You almost always want assignments to be local. I assume @jashkenas only went with nonlocal assignment to avoid having to have declarators. There's no other sane reason to do it.
If we're going to change the language design to introduce declarators, then we should definitely make assignment local by default and have a declarator for nonlocal assignment. We don't need Python's global
declarator as we have window.x
already.
If let
makes a variable block-scoped and const
makes the name un-reassignable and block-scoped, neither does what we need.
Even if we keep assignments nonlocal, if we introduce declarators, we would really need declarators for local
, const
and local const
.
The benefit of having block-scope in CoffeeScript is slim. We can always create a new scope with do ->
, and any variables in the function will be effectively block-scoped (again, assuming we don't clobber anything). Having let
would allow us to do this:
if foo
let x = true
let y = false
But, we can already do this anyway:
if foo then do ->
x = true
y = false
JavaScript became considerably more complicated by introducing let
, and it was only introduced to fix different problems to the ones CoffeeScript has. We don't have much use for it.
I personally think outer.x
is better than nonlocal x
because it's explicit about which scope it references, and follows logically from window.x
. Still, I'm happy to hear other ideas.
Taking declarators from JavaScript requires changing them to fit CoffeeScript's nonlocal assignment feature, which may in turn require any declarators to be renamed for their new semantics, so we'd basically need to define our own declarators from scratch. And we really should try and do everything we can to avoid introducing declarators, given that they have been rejected from CoffeeScript for seven years, and they make everything look like Java.
jQuery ->
local const square = (x) -> x * x
From @JimPanic on July 19, 2016 13:58
@carlsmith You are right, I did misunderstand.
I always thought CS was favouring the innermost scope in assignments. Lucky me it didn't bite me so far.
From @carlsmith on July 19, 2016 14:3
@JimPanic :) It's not obvious what CoffeeScript is doing, especially when it seems to be doing what you'd expect, coming from other languages. It doesn't bite that often, but when it does, it can be totally baffling.
From @rattrayalex on July 20, 2016 20:25
Thanks very much @carlsmith for the terrific explanation there. Didn't understand that bit myself so well till now 😄
I do agree that it would likely be too ambitious to change how scoping works, unless we can simplify the coffeescript compiler by staying closer to JS's behavior.
From @rattrayalex on July 20, 2016 20:27
[const] is a key feature for me
@JimPanic can you elaborate? I intuitively feel the same way – I enforce const
-by-default in my eslint – but curious to hear if there are additional reasons why const
is useful.
From @rattrayalex on July 20, 2016 20:39
Any thoughts on const
being used like so:
x := 7 # const x = 7
And all other =
being treated as they are today, either using var
or let
?
From @rattrayalex on July 20, 2016 20:43
Personally, I believe these should be untouched. I can see that there is a case for implementing const in almost any language remit. But not coffeescript.
@DomVinyard re-reading this, I'm not sure I understand what you originally meant. Can you clarify?
From @carlsmith on July 20, 2016 21:29
Adding a constant operator is easier than adding declarators. It changes the language less. The operator is ok, but will get a bit messy when its x :=? 7
. If it was a short word, but still a normal operator, it wouldn't look as cryptic: x be 7
and x be? 7
looks more like regular CoffeeScript. I don't think it should be called be
though. Just, if there was a good, short word, that would be better than having a :=?
operator :)
From @JimPanic on July 22, 2016 8:38
@rattrayalex It helps avoiding so many bugs and enables a more declarative way of coding, which in turn helps keep code readable and (more) testable. How do you enforce const
by default? Does your linter settings just yell at you when you do not declare something as const? :D
From @JimPanic on July 22, 2016 8:39
@carlsmith I was thinking the same; a different assignment operator would go well with the CS syntax as it is now, since there are no declarator keywords. Why the question mark in :=?
?
From @carlsmith on July 22, 2016 12:55
@JimPanic - My bad: I got it back-to-front (I rarely use the feature this way), but you have an existential assignment operator in CoffeeScript that looks like ?=
, so if we have a constant assignment operator like :=
, we'd need an existential constant assignment operator, which would end up looking like ?:=
.
From @carlsmith on July 22, 2016 13:26
We could figure out from static analysis whether a name is assigned more than once, and make names that are never reassigned constants automatically, but expect JavaScript engines already do this, so any efficiency gains would likely be negligible. More importantly, people want explicit constant assignment/declarations to communicate that constraint to other programmers. Given that it's a popular CoffeeScript feature request, and already part of ES6, explicit constants should really be supported somehow.
There's an argument for getting rid of the is
and isnt
operators from CoffeeScript. CoffeeScript used to have an aint
operator that compiled to !==
, but it got dropped in favour of just having the current isnt
alias, but that's confusing. People often shorten a is not b
to a isnt b
, expecting them to mean the same thing, like they do in English, but a is not b
compiles to a == !b
, while a isnt b
compiles to a !== b
.
If we just kept the current ==
and !=
CoffeeScript operators (which compile to ===
and !==
), and got rid of isnt
altogether, then is
would be a good constant assignment operator.
i = 0
pi is 3.141
Then a ?is b
would work as an existential assignment operator.
If we do a backwards incompatible CoffeeScript, we should definitely fix anything that is accepted as broken and easy to fix. Removing is
and isnt
would be trivial. We already have conventional, unproblematic ==
and !=
operators. And is
would be a really nice constant assignment operator.
It's also worth mentioning that Python has an is
operator. It's used to test whether two expressions evaluate to the exact same object in memory.
a = b = []
a is b # True
a, b = [], []
a is b # False
Using is
for assigning constants would be a bit different, but still similar to Python - they both kind of mean is actually
rather than equals
.
From @DomVinyard on July 22, 2016 14:25
@rattrayalex
Coffeescript succeeded, at least partially, because it traded out efficiency optimisations for simplicity in a bunch of contentious but elegant ways. Not distinguishing between let and const fits that core simplicity brief.
Perhaps this means that a few edge-projects will have to use vanillaJS for certain classes of application because the overhead of trading out lets for consts would trip the project from acceptable into unacceptable but I think that is a reasonable cost to keep things simple.
Avoiding having to add a new operator is worth fighting hard for in every case.. if CS is to retain its CSiness.
From @DomVinyard on July 22, 2016 14:40
@carlsmith Firm -1 from me for redefining is.
From @rattrayalex on July 22, 2016 16:24
How do you enforce const by default? Does your linter settings just yell at you when you do not declare something as const?
Yes – it's an ESLint setting to always use const unless you redefine the variable later.
we'd need an existential constant assignment operator, which would end up looking like ?:=.
I don't think an existential constant assignment operator makes sense 😉. ?=
is used for reassignment, which isn't possible with const
.
From @rattrayalex on July 22, 2016 16:55
explicit constants should really be supported somehow.
I'm increasingly convinced of this as well personally. Should probably add to https://github.com/coffeescript6/discuss/issues/8.
Avoiding having to add a new operator is worth fighting hard for in every case.. if CS is to retain its CSiness.
I disagree with this sentiment, actually. While maintaining a decent degree of backwards-compatibility would be nice, I don't think we should shy away from adding new features, especially those that are part of ES6. The number one purpose of this org is to ensure that CoffeeScript isn't behind ES6 at all – that anything* you can do conveniently in JavaScript, you can do at least as conveniently in CoffeeScript.
Furthermore, language innovation is a core aspect of the "CSiness" of CoffeeScript IMO. Jeremy combined the most convenient language features he could find from other languages, made it easy to write good javascript, and added some new ideas into the mix as well.
We should certainly think really hard about whether any new features are worth doing – and focus on compatibility with ES6 first – but I also don't think it's something we should shy away from.
* Anything that you should be doing, anyway. Making "the bad parts" and generally poor programming practices less convenient, or even impossible, is a good thing.
From @rattrayalex on July 22, 2016 16:59
Firm -1 from me for redefining is.
I personally agree. However, to keep a healthy environment where people feel comfortable voicing new ideas they might not be 100% comfortable with yet, let's try to back up -1's with a few calm reasons.
In this case, my reason is primarily difficult of porting – redefining a language keyword to something completely different could make updating quite difficult, as you'd have to both translate all existing =
s to is
, and only once that is 100%-for-sure-done across your whole project, change most of your =
s to is
.
I also happen to think it'd be a bit less readable than something with symbols, given the ubiquity of the =
for assignment across programming languages.
From @rattrayalex on July 22, 2016 17:1
My understanding is the primary objection to :=
is the conditional assignment scenario, which as I outlined above probably doesn't apply. Are there others?
I think the leading alternative at this point would probably be to just pass const
through, or come up with a similar (ideally shorter) word.
Thoughts?
From @carlsmith on July 22, 2016 22:0
I don't think an existential constant assignment operator makes sense 😉. ?= is used for reassignment, which isn't possible with const.
I didn't think about that. Sorry about the noise then. I mentioned not using that feature much when I misspelled the operator :|
I'm with @rattrayalex on adding new features, but feel pretty strongly that we should stick to things that are just sugar for well established idioms or that have already been standardised by ECMA. CoffeeScript should make one big breaking change, then treat TC39 as our standards process. Now that CoffeeScript has inspired JavaScript to evolve, we can co-evolve with JavaScript in a way Jeremy couldn't in 2009.
So, yeah - sorry to ramble - assuming there will be no need to have an existential constant assignment operator, then I would personally be ok with :=
, but still wish it was prettier.
square := (x) -> x * x
I still feel strongly that we should avoid declarators if at all possible. It changes the language, and we use assignment expressions in lots of places where they need to be concise, not just in standalone statements..
Also, do we need a story for constant function parameters, or can you just not define a parameter as a constant?
From @rattrayalex on July 23, 2016 2:11
but still wish it was prettier.
Agreed.
remember that we use assignment expressions in lots of places where they need to be concise.
Would you be willing to provide a few quick examples for illustrative purposes?
or can you just not define a parameter as a constant?
Well, you can't in es6, so we'd really be going above and beyond if we implemented it in cs6. It's not an unappealing feature imo but probably not something to worry about yet.
CoffeeScript should make one big breaking change
Amen.
then treat TC39 as our standards process
I really need to learn more about TC39 😃
From @carlsmith on July 23, 2016 2:57
Would you be willing to provide a few quick examples for illustrative purposes?
I meant using assignment expressions like this:
if (stuff = getStuffOrReturnNull) then use stuff
employees = [
ali = new Employee "Ali"
bob = new Employee "Bob"
]
Because assignments are expressions, you can write one anywhere you can write an expression. It can be helpful when you want to make assignments conditionally, and lets us use some shorthand expressions for initialising variables.
From @carlsmith on July 23, 2016 3:10
On the TC39 comment: I really just meant that we should follow the ECMAScript standards when introducing features that go beyond sugar for common JS idioms.
We have the luxury these days of a standards process that moves quickly, releases often and develop editions in parallel. It has some of the best minds in our community, and all the vendors are on board. You can get involved through ESDiscuss, and influence the spec, but for the most part, we don't need to. It works.
If Jeremy had followed the spec, we wouldn't have the problem we now have with incompatible classes. Obviously, in 2009, following the spec would have made CoffeeScript suck.
From @rattrayalex on July 23, 2016 3:13
Wow, I've never seen the employees
code before. Looks awesome though.
https://github.com/michaelficarra/CoffeeScriptRedux/wiki/Intentional-Deviations-From-jashkenas-coffee-script#intentional-deviations might be relevant here once we get into the weeds, especially if we decide to build on CSR.
Thanks for sharing the examples! Helpful.
From @rattrayalex on July 23, 2016 3:14
Re; TC39, thanks for elaborating - helpful. To clarify, do you propose:
(I'm mostly 👍 to both)
From @rattrayalex on July 23, 2016 3:55
Some thoughts on an alternative route to :=
.
There are three things that we typically do with =
:
const myVar
, let myVar
, var myVar
)let myVar = 3
)let myVar = 3; myVar = 'foo'
)Reassignment occurs the least often, and is arguably an anti-pattern (though often a practical necessity). const
prevents reassignment, let
and var
do not. const
requires assignment with declaration, let
and var
can be declared without assignment.
There are a couple routes we could go down:
const
by default, and infer when let
/var
should be used instead.
Leverage coffeescript's existing Scope parser to check if a variable is ever reassigned; if not, it's const
. If it's reassigned, it's var
or let
(we can decide later).
Pros: This would be backwards-compatible (modulo some probable bugs) and would result in frequent use of const
.
Cons: Since there is nothing visible to the coffeescript programmer, the benefits of using const are essentially eliminated. The work of discouraging reassignment would probably have to fall to a linter. Use const
by default, and enforce declarators for let
/var
.
This would make using let
/var
less convenient; the example above would probably look like this:
let employees, ali, bob
employees = [
ali = new Employee "Ali"
bob = new Employee "Bob"
]
# later, reassign to different values:
ali = 5
bob = 'foo'
employees = 'other nonsense'
(the let
would be unneeded if the variables were never reassigned)
Pros: This would discourage use of reassignable variables, while still allowing it without too much hassle. It should be reasonably tractable to write an automated cs->cs6 transpiler to add the let
's, but probably a pain. It also allows use of both let
and var
without taking a stance.
Cons: Declarations are still ugly. Might be too prescriptive.
Use const
by default, and enforce special syntax for reassignment (eg; ^=
, the update-operator).
This is pretty outlandish – I don't know of any other language that has a different syntax for assignment vs reassignment – but I think it's pretty interesting. Imagine reading a program and immediately knowing whether foo = 'bar'
is writing a variable or overwriting a variable.
It could look like this:
foo = 1
foo ^= 2
Or, perhaps:
foo := 1 # becomes `let foo = 1`
foo ^= 2 # becomes `foo = 2`
bar = 3 # becomes `const bar = 3`
Or this could be done in tandem with option 2:
let foo = 1 # becomes `let foo = 1`
foo ^= 2 # becomes `foo = 2`
bar = 3 # becomes `const bar = 3`
Pros: Would strongly discourage, but allow, reassignment. Would be extremely explicit about what is assignment, what is reassignable-assignment, and what is reassignment. Possibly a genuine language innovation. Can get rid of CoffeeScript understanding of scope entirely. Cons: Inconvenient, ugly, foreign.
var
and allow const
declarations through :=
.
Pros: Much more backwards-compatible, still allows const
for those who really want it.
Cons: Discourages the thing you should really be doing; the right thing and the good thing aren't the same.const
, and allow var
or let
declarations (but only one of the two) through :=
.
Pros: Relatively simple, avoids declarators, could possibly get rid of CoffeeScript understanding of scope, makes the right thing the easy thing.
Cons: Still a little ugly, not backwards-compatible, have to make a choice between let
and var
. Thoughts? Any other ideas?
From @ozjd on July 24, 2016 17:39
To keep things very CoffeeScript like, I would use the following: (in this order)
const
: When a variable is named UPPERCASE eg VAR = ...
(It's very important to note that this seems to be the common suggestion for coffeescript, and is how most people already write an implied constant)
var
: When an object is redefined (eg, contains a .
as in window.var = ...
or []
as in window['var'] = ...
let
: All other times.
Examples:
@foo = 'bar'
would become let this.foo = 'bar'
@FOO = 'bar'
would become const this.foo = 'bar'
obj::foo = 'bar'
would become let obj.prototype.foo = 'bar'
obj::FOO = 'bar'
would become const obj.prototype.foo = 'bar'
obj.prototype.foo = 'bar'
would become var obj.prototype.foo = bar
obj.prototype.FOO = 'bar'
would become const obj.prototype.FOO = 'bar'
I'm sure there are other cases that I haven't thought of, but I'd imagine that this would also probably break very few existing scripts. Thoughts?
Note: I think the most important part is automatically mapping UPPERCASE variable names to a const
.
From @carlsmith on July 24, 2016 18:35
I didn't quite understand the code above, but just to be clear: Deleting ali
and bob
in this code would not change what the array named employees
evaluated to:
employees = [
ali = new Employee "Ali"
bob = new Employee "Bob"
]
The code creates three names:
employees: [<Employee0>, <Employee1>]
ali: <Employee0>
bob: <Employee1>
Deleting ali
would decrement the reference count on <Employee0>
, but it would not be garbage yet, as it's still referenced by employees[0]
.
From @carlsmith on July 24, 2016 18:37
I already commented about this on the main CoffeeScript repo, but beings as it's being addressed here as well...
-1
on forcing constants to be uppercase. Most functions will be constants, and we don't want every function to have a LOUD_NAME
. We also wouldn't be able to distinguish between class names and the names of regular functions if they all have to be uppercase. We also use camelCase a lot in CoffeeScript, and would be forced to use underscores if we only have uppercase constant names.
A constant assignment operator has been discussed elsewhere, so you'd do something like:
i = 0
pi := 3.141
A better looking operator would be nice, but it's a much less radical change at least.
From @ozjd on July 24, 2016 19:52
Note that I wasn't suggesting that you MUST use uppercase for constants, just that UPPERCASE variables would be considered constants.
From @rattrayalex on July 24, 2016 17:31
@ozjd I might recommend you familiarize yourself with ES6 a bit.
Variable declaration isn't done as a part of property assignment; let obj.prop
results in Uncaught SyntaxError: Unexpected token .
.
const
is commonly used outside of traditional "constants". For example, AirBnB's style guide (the de facto community standard) recommends using const
for as many variable declarations as possible.
From @rattrayalex on July 24, 2016 17:40
@carlsmith sorry for my confusing code sample, I didn't mean to delete the variables, just reassign them. I've edited my comment for (arguable) clarity. Does that help at all?
From @rattrayalex on July 24, 2016 17:56
Ah, one idea I meant to add to this thread that could make the parser simpler and the language more explicit:
Outlaw implicit window
.
Now that ES6 has modules, the value of the convenience of the implicit window has gone way down. It's almost exclusively an antipattern. In some files where I need to use a global, I put this at the top:
const { app } = window; // fake import
... and otherwise just use window.someVariable
.
CoffeeScript already does not allow implicit writes to the global object, but does allow implicit reads:
thing() ->
f() // would essentially call `window.f()`
Should we do this if it makes life easier?
From @GeoffreyBooth on July 24, 2016 21:05
I guess an early question to answer is whether we want to give the developer the power to specify when let
or const
is output. In other words, what's the goal here:
let
, when to use const
, and when to use var
? And current syntax is unchanged.const
for a particular variable? And the compiler would automatically use let
or var
for all others.let
for a particular variable? And the compiler would automatically use const
or var
for all others.const
or a let
for a particular variable? And the compiler would automatically choose the best option for all others.I assume we at least want to do the first goal, and that should get its own issue to figure out the methods for how the compiler will decide what to do. If we want to do one of the others, perhaps a new thread can be created where we can hash out the desired functionality and new syntax.
From @rattrayalex on July 25, 2016 20:28
Terrific summary @GeoffreyBooth . Personally I'm interested in 1, 2, or 3. I'd prefer 3 but for backwards-compatibility would accept 2.
const
exists, and is used, for a reason. That reason goes away if the compiler infers which one you mean, hence my unease with option 1. What's the point of const
at that point?
From @carlsmith on July 25, 2016 20:31
The point in that case would be that the JS engine gets to do all the optimisation, without us having to tell it what to do manually. We get all the benefits, with none of the labour.
From @rattrayalex on July 26, 2016 22:05
What benefits?
From @carlsmith on July 26, 2016 5:12
Perf.
From @rattrayalex on July 26, 2016 10:48
Sorry, I should have been more clear. I don't think performance is the reason people use const
in JavaScript.
As of Oct 2015:
Using
const
is consistently slower in all tests but it is marginal and too close to call.
And was much slower when it was first released. It might be faster in the long term, of course, but for now it's not – especially if you use Babel, and the const
is turned into a var
anyway. As such, it probably wouldn't make sense to enable const
at all if performance is the argument, until there is indeed a dramatic performance boost from using it. At which time, yes, implicit const
would probably be fine.
From @rattrayalex on July 26, 2016 10:48
My impression is that const
is used for preventing the class of bugs related to reassigning variables. Eg; from the AirBnB style guide note on the topic:
This ensures that you can't reassign your references, which can lead to bugs and difficult to comprehend code.
From the ESLint docs:
If a variable is never reassigned, using the
const
declaration is better.
const
declaration tells readers, “this variable is never reassigned,” reducing cognitive load and improving maintainability.
These benefits don't apply if const
declaration is invisible and goes away the moment you reassign a variable.
From @carlsmith on July 26, 2016 11:03
Yeah, that's the controversial bit. Jeremy could have added constants to CoffeeScript at any point - the compiler knows which vars are reassigned - but didn't. The perf thing is a definite benefit if it works, but as you pointed out, it doesn't seem to. The benefit of explicit constants has to be weighed against complicating the language.
Personally, I think you're right: It's a feature people want, and it's now standardised, while it wasn't when Jeremy decided against it, and the complication is pretty minor, especially for the kind of people CoffeeScript appeals to, so I'd vote to accept a PR if asked.
If we work on the basis that concensus means that nobody strongly objects (as it's impossible to get everyone to agree), then the question is really simple...
Does anyone feel strongly that we should not add explicit constants?
From @GeoffreyBooth on July 26, 2016 11:39
Personally I think we should do both: the compiler should automatically choose the best of var
/let
/const
for each variable assignment, and we provide developers a way to force a const
for a particular assignment. I don’t see a need to provide a way to force var
or let
.
I like the idea of echoing the @foo
as our way of designating a constant, by using some symbol other than @
to designate a constant. My instinct would be to use !
but that already means “not.” So . . . ^foo
? %foo
? Is there something standard from other languages?
From @carlmathisen on July 26, 2016 11:47
Agree with @GeoffreyBooth that we don't need to worry about var
or let
when writing CS code. I mean, CS takes care of that scope for you under the hood anyway.
Regarding const
assignment: In normal JS and other languages, you just reference a constant like a normal variable, don't see why CS needs to do this differently. IMHO, it just adds unnecessary complexity to syntax.
Why not just const foo = 'bar'
?
From @JimPanic on July 26, 2016 11:52
I feel strongly in favour of adding some form of const
syntax. It does not have to be a declarator keyword. To keep the concise nature of CS, the aforementioned :=
for const
is what I would like to see.
Regarding let
and var
: since const
will then not be the default, let
should be the default behaviour. var
could be explicitely declared using the var
keyword.
@carlmathisen: I think the main thing with this is, there are no declaration keywords in CS and it would change the language quite a bit.
From @carlsmith on July 26, 2016 15:25
If we're compiling to ES6, we'll definitely end up using let
in compiled JS (whether we redo CoffeeScript's nonlocal assignment or make assignments local or whatever happens). CoffeeScript currently wraps stuff in self-invoking lambdas to create the same effect withvar
, so we'd definitely use let
instead these days.
Everyone who's contributed so far seems to agree we should have explicit constants, that compile to const
and so have ES6 semantics (the name can't be reassigned, but the value can still be mutable). We keep going back to declarators though. I'm pretty strongly against them. They are too bulky:
const factory = (mutator) -> (args...) ->
mutator (const self = Object.create null), args...
return self
Employee = factory (self, name, salary) ->
self.salary = salary
const self.name = name
const self.raise = (amount) -> self.salary += amount
const ali = Employee "Ali", 50000
ali.raise 10000
CoffeeScript hasn't got declarators, so adding them is a big change. From that example (which I only went with because I use it all the time), const
is used five times. It makes much more sense to use an operator. Adding an operator doesn't change things as radically, though it does change things substantially still.
factory =: (mutator) -> (args...) ->
mutator (self =: Object.create null), args...
return self
Employee = factory (self, name, salary) ->
self.name =: name
self.salary = salary
self.raise =: (amount) -> self.salary += amount
ali =: Employee "Ali", 50000
ali.raise 10000
I put the equals first because GitHub kept trying to insert people's names when it's written the other way around.
There's the option of appending something to the beginning or end of a constant, but that seems pretty bulky in practice too.
@factory = (mutator) -> (args...) ->
mutator (@self = Object.create null), args...
return self
@Employee = factory (self, name, salary) ->
self.@name = name
self.salary = salary
self.@raise = (amount) -> self.salary += amount
@ali = Employee "Ali", 50000
ali.raise 10000
If it looks like a different programming language, it's gone too far, so only an operator seems acceptable. If we could get it down to one character, then it would be better still, but looking at the keyboard, there's nothing left, so something like =:
seems like the best compromise, but it is a bit ugly still.
We could use unicode, but even in a language for the Web, that's still a big change. Looks good though.
i = 0
pi ▹ 3.141
It would be nice to support unicode for people who want to use it, in a subproject (APL Mode). Using stuff like ≠
, ≤
, and ≥
would make code less cryptic and prettier, and isn't hard to enter once you start using Alt and Alt+Shift for a little while.
Given that so many CoffeeScript users like to do language design, we should give plenty of thought to letting people do stuff like configure the compiler, expand macros and walk the AST mutating nodes. Obviously, we can't do everything, but letting people have the dialect they want would be cool.
Sorry for such a long post.
From @DomVinyard on July 11, 2016 12:13
Personally, I believe these should be untouched. I can see that there is a case for implementing const in almost any language remit. But not coffeescript.
Copied from original issue: coffeescript6/discuss#1