Closed coffeescriptbot closed 6 years ago
From @kirly-af on 2016-08-07 13:36
This is discussed in jashkenas/coffeescript#4233 (and probably many others I'm not aware of).
Also, I just discovered this Redux PR thanks to @GeoffreyBooth which looks REALLY promising.
From @GeoffreyBooth on 2016-08-10 07:04
So it appears that someone has actually already implemented CoffeeScript class
to ES2015 class
—in decaffeinate. Check it out!
From @DomVinyard on 2016-08-15 15:16
I think there's probably a larger conversation to be had about decaffeinate specifically, how and where it intersects with this project, what can be borrowed, what can be adapted, etc.
From @alangpierce on 2016-08-21 02:06
Hi, I'm a decaffeinate contributor. While decaffeinate does have basic support for classes, full support is one of the main missing features right now. I'm hoping to improve it over the next few weeks, but it's definitely a challenge, since my understanding is CoffeeScript allows arbitrary code in class bodies, while ES2015 classes only allow methods. Decaffeinate also compiles CoffeeScript class fields to the public class fields proposed feature (currently stage 2), but even that has pretty significant semantic differences that have caused bugs for me (CS class fields are on the prototype, JS class fields are assigned to the instance once the constructor finishes). Anything other than methods or fields causes decaffeinate to crash.
From @GeoffreyBooth on 2016-08-21 02:28
Thanks @alangpierce. Yeah, after looking at it more I think the better solution is to redefine the class
syntax in CoffeeScript to be something that translates directly into ES2015 classes, dropping support for ES2015-unsupported features like code in class bodies. This would be a breaking change in CoffeeScript, probably one that’s opt-in via a flag, but necessary if CoffeeScript is going to keep up with new features introduced by ECMAScript.
While the immediate focus is on adding support to CoffeeScript for missing vital ES2015 features (modules, classes), the longer-term goal especially of coffeescript6 is to update CoffeeScript’s output to use more of the latest standards. This essentially means we would be doing the work that decaffeinate is doing, but within the main CoffeeScript compiler. I skimmed through the decaffeinate repo, hoping to find some commits that highlight what differences it had from the main CoffeeScript compiler, but I couldn’t make sense of it. Do you mind giving whatever overview you can of how decaffeinate works, and where I should look for code that might be useful to repurpose in the main CoffeeScript compiler? For example, where is the code that generates an ES2015 class?
From @mrmowgli on 2016-08-21 06:38
I would love to see some way of extending the current class functionality to generate the ES2015 code, and then decorate with everything else. I guess I don't really understand what actually breaks and where yet though. I am assuming that ES classes have extra restrictions, ie that they aren't just objects with prototypes set in a specific pattern?
From the Babel overview:
ES2015 classes are a simple sugar over the prototype-based OO pattern. Having a single convenient declarative form makes class patterns easier to use, and encourages interoperability. Classes support prototype-based inheritance, super calls, instance and static methods and constructors.
So I would think we could construct functions only, then decorate with everything else?
From @alangpierce on 2016-08-21 07:00
@GeoffreyBooth Yep, dropping support for code in class bodies makes a lot of sense for your case.
Sure, I can give a quick overview of how decaffeinate works:
Unfortunately, I think the short answer is that decaffeinate's approach is pretty different from the CoffeeScript compiler, so you may not be able to use much code/logic. From my reading of the CoffeeScript compiler, it parses the input to an AST, then calls the recursive compileNode
method (and related methods) to generate a big JavaScript string that becomes the output file. Decaffeinate works by parsing the input into an AST (and a token sequence), then using that AST to inform targeted transformations on the code (inserts, removes, and replacements) using the magic-string library. For example, to compile a b
, it uses the AST to see that it's a function call, looks at the tokens to see that there's no open-paren or close-paren, and replaces the space with a (
and inserts a )
after the b
(code here). This approach makes sense given decaffeinate's goal: it doesn't want to rewrite all of your code, it wants to tweak it (sometimes significantly) to be valid JavaScript, maintain formatting and comments as much as possible. But really, this approach ends up being a big pain sometimes, and transforming the code to a JavaScript AST would probably be more robust in a lot of ways (but would lose formatting).
A little more information on how decaffeinate is structured: it consists of five "stages" (one CoffeeScript -> CoffeeScript, one CoffeeScript -> JavaScript, and three JavaScript -> JavaScript), the most important of which is the CoffeeScript -> JavaScript stage, which is called MainStage. For that stage, every type of AST node corresponds to a Patcher class. Each Patcher is a class that knows what kind of modifications to make to transform that type of CoffeeScript node to JavaScript.
Here's a repl link that has some examples of what happens in different stages. You can change the "run to stage" selection to see the intermediate result after each stage (or intermediate lexer/parser results).
I actually haven't worked with the class generation code, but was able to mostly figure out how things work. If you look at the decaffeinate-parser output for your example, you can see that the main AST hierarchy is Class
> Block
> ClassProtoAssignOp
> Function
. From the node name to patcher class mapping, (or by just looking at the names), you can see that they map to the classes ClassPatcher
, BlockPatcher
, ClassAssignOpPatcher
, and FunctionPatcher
. The methods patchAsStatement
and patchAsExpression
are generally the most important ones. As one example, ClassAssignOpPatcher
extends ObjectBodyMemberPatcher
, which calls this.expression.patch
with the method
flag set appropriately. On the FunctionPatcher
side, it knows that it should skip the function
keyword if the function is being patched as a method.
Also, here's a writeup with some more details: https://github.com/decaffeinate/decaffeinate/blob/master/docs/contribution-guide.md
Hope that helps!
From @GeoffreyBooth on 2016-09-05 21:02
I don’t think we can simply redefine the class
keyword, even behind a flag. That would be too drastic a breaking change for current projects to handle, including the CoffeeScript compiler codebase itself (which uses class
extensively). I think we need to provide a clear and easy upgrade path, especially if we’re adding ESNext class
support to the original compiler.
How about this approach: we create a new CoffeeScript keyword, esclass
, that has different syntax than the current class
. It only allows things that can be output into an ESNext class
, and it compiles into ES output (so class
is in the generated JavaScript, not function
).
With esclass
, a CoffeeScript project could contain both new compile-to-ESNext-class
classes and legacy old compile-to-function
classes. People could convert a project gradually, or pick and choose which type of classes they want to use (for example, esclass
could be used when extending a class imported from another library, with class
used for all classes particular to your project). Having two types of classes would also let us keep the CoffeeScript compiler codebase intact without major changes.
Introducing a new keyword that wasn’t previously reserved is a breaking change, so we would need to introduce a flag. I think since esclass
is so obscure a string, it’s unlikely that there are many (if any) projects out there using it already as a symbol; so maybe we could get away with shipping it reserved by default, so that the vast majority of projects need not do anything to take advantage. For the 0.001% of projects using esclass
already as a variable or function name (and who don’t want to refactor), they would need to set the flag to force legacy support. The flag could work something like this:
class
keyword would retain its current syntax, and esclass
would become a new reserved word that introduces a new syntax that compiles into ESNext classes.--legacy-classes
: The current behavior. class
is unchanged, and esclass
is not a reserved word.We could even add support for making class
an alias for esclass
and csclass
an alias for the current class
, if we want to let people use the class
keyword for the new syntax; but I’m concerned that it’s probably a bad idea to not be able to look at code and know how it will get compiled, if you don’t know what flag will be set in the compiler.
Conversely, it might be a good idea to introduce csclass
as a new reserved word that always aliases to the current class
syntax, so that people could use esclass
and csclass
exclusively, leaving no ambiguity about what their intentions are.
What do you all think? @lydell, @rattrayalex, @JimPanic, others . . .
From @JimPanic on 2016-09-06 05:54
I like the idea of csclass
& esclass
although we might want to find better names. I also am not sure yet what the differences in semantics are. It seems there is a bit more to it than just syntactic sugar as the ES201x class
does not allow data properties, has different grammatical rules than object literals and cannot be called without new
(if I read that correctly).
Apart from that, I think the only solution to introduce this to users is a) with conversion tools and b) through a process of deprecation warnings, deprecation and removal over several releases. This is something we have to plan, no matter what keywords we use in the end.
The only thing that could be dangerous is to keep the class
keyword to stay semantically different from the one in ES201x. Its meaning has to change eventually.
From @lydell on 2016-09-06 05:55
Here's my vote:
Add esclass
for ES2015+ classes. Make no other changes whatsoever.
Release it by bumping the middle version number, keeping CoffeeScript's current versioning scheme of bumping the middle number when there are new features an slightly-but-not-very breaking changes. (As @GeoffreyBooth it is very unlikely that this will cause any trouble for anyone.)
No csclass
. Do we want csin
, csof
, csfor
etc. too?
CoffeeScript 2.0.0: Remove old class
, rename esclass
into class
(and do similar things for other ES2015+ features) and switch to semver.
From @GeoffreyBooth on 2016-09-06 05:58
I guess we probably don’t need a flag if we’re simply adding esclass
(or whatever people decide to name it) and leaving class
alone. It would be a breaking change to anyone who was already using esclass
as a symbol, but maybe rather than giving them a flag to opt out we should just recommend they simply don’t upgrade (or that they refactor). It’s a very minor refactor to find and replace all instances of esclass
with something else, we wouldn’t need to provide migration tools for that.
My god, did we just come up with a way to implement classes without a flag? 😛
From @JimPanic on 2016-09-06 06:23
I think we did, yes. 🤔 I'm also very much in favour of implementing semver.
From @greghuc on 2016-09-06 08:20
I like the idea of a separate esclass
as a 'least breakage' way forward. However, I'm less comfortable with how the eventual replacement of Coffeescript's class
with esclass
could pan out.
At present class
let's me do some nice things: instance functions, static functions, private static functions and 'constants'. I've written a short example class below. If esclass
doesn't eventually support these class
capabilities, then this is a step backwards for Coffeescript. Though you could argue that if ES2015+ classes can't handle this, then that's a step backwards too!
Example:
class ClassExample
CONSTANT_EXAMPLE = 'I am a constant example'
constructor: -> console.log 'I am a constructor'
instanceFunction: ->
console.log '[start] I am an instance function'
console.log CONSTANT_EXAMPLE
privateStaticFunction()
@constructor.staticFunction()
console.log '[end] I am an instance function'
@staticFunction: ->
console.log '[start] I am a static function'
console.log CONSTANT_EXAMPLE
privateStaticFunction()
console.log '[end] I am a static function'
privateStaticFunction = -> console.log 'I am a private static function'
# Example calls
#ClassExample.staticFunction()
(new ClassExample).instanceFunction()
From @lydell on 2016-09-06 11:21
@greghuc I don’t really see the step backwards?
# ClassExample.coffee
CONSTANT_EXAMPLE = 'I am a constant example'
privateStaticFunction = -> console.log 'I am a private static function'
export class ClassExample
constructor: -> console.log 'I am a constructor'
instanceFunction: ->
console.log '[start] I am an instance function'
console.log CONSTANT_EXAMPLE
privateStaticFunction()
@constructor.staticFunction()
console.log '[end] I am an instance function'
@staticFunction: ->
console.log '[start] I am a static function'
console.log CONSTANT_EXAMPLE
privateStaticFunction()
console.log '[end] I am a static function'
# whatever.coffee
import {ClassExample} from 'ClassExample.coffee'
ClassExample.staticFunction()
(new ClassExample).instanceFunction()
From @greghuc on 2016-09-06 11:48
@lydell I'm still getting up to speed with ES6 features, so please take my comments with a pinch of salt..
Your example code isn't that bad. It is essentially forcing a coffeescript user to have a closure wrapping both the class declaration and the private 'constant' and static function, to ensure private means private. But from my quick scan of ES6 modules, I suppose there's an implicit closure when importing a module from a file.
I could live with this, although I don't think your example code is as clean or explanatory as the current coffeescript code. In the current code, the class acts as an encapsulating namespace for all private and public functions.
For the esclass
to class
transition, there'll be a need to document how 'private' variables and functions are implemented in the new world.
From @DomVinyard on 2016-09-06 15:02
How about, instead of esclass
we go for Class
, uppercase C?
From @lydell on 2016-09-06 15:08
@DomVinyard In my opinion that would be very confusing. I also think that that will break more people's code – even CoffeeScript's source code has class Class
in it!
From @DomVinyard on 2016-09-06 15:24
@lydell I concede that point and do accept it would break more projects than esclass
would (although still not a great deal in the grand scheme of things). It's just that Coffeescript seems too institutionally elegant and natural for keyword prefixes. Your illustration earlier of "why not esfor
or esin
?" describes the danger better than I could.
From @GeoffreyBooth on 2016-09-08 03:46
@DomVinyard I have to agree with @lydell on this one. I’m not thrilled by the name esclass
, but I think Class
could be way too confusing. It’s easy to rename later if someone proposes a better name.
So I think the next step is to define what the syntax of esclass
would be. I don’t really follow the example above. The relevant pages on MDN are here and here and here. Some interesting things:
super
keyword appears alone and must be used before the this
keyword can be used. This keyword can also be used to call functions on a parent object.Here’s an extensive example.
It seems clear from the examples that we will need to implement get
and set
as part of this, and some way to trigger output of the static
keyword. super
will also behave differently when inside an esclass
—it would be called like super.parentClassMethodName
rather than just super
, except in the constructor.
I think like with modules, our goal should be to simply create a way to output ES classes with all their features as they are, rather than trying to improve upon them the way that the original class
improved upon “function classes.” At least at first; we could add sugar later.
Is anyone else interested in helping research/define this, and/or code it?
From @rattrayalex on 2016-09-08 04:27
Exciting stuff.
Perhaps once esclass
is implemented we'll even find that it can replace class
. Either way, makes sense to me to take that tack.
I am curious though – what advantages do CS classes have over ES classes? Why would a developer prefer CS to ES output? (Honestly don't know).
From @JimPanic on 2016-09-08 08:29
@rattrayalex ES201x classes cannot have executable code in their bodies. You cannot declare properties at runtime. You can do that with CS classes but I personally think it's bad practice to do so as it's not very explicit and mixes different styles of defining "types".
From @JimPanic on 2016-09-08 08:39
Ok let me rephrase that a bit: of course you can declare properties at runtime, but not in the class declaration body like in CS. :)
From @greghuc on 2016-09-08 08:54
Re-reading through this 'classes' thread, I think it's worth noting that are at least three distinctive positions to take on Coffeescript and ES6 classes. Two positions are at odds with one another. The positions:
esclass
.My personal position is a combination of 1 and 3: change the Coffeescript compiler to take advantage of ES6 class functionality, and fix any technical incompatibilities. But don't change (or remove!) existing CS class semantics.
I see position 2 as a risky one (Coffeescript classes are semantically wrong, now that ES6 classes have come along). This path leads to the ES6 tail wagging the Coffeescript dog. From now on, Coffeescript is no longer an opinionated "little language that compiles into JavaScript". Instead, we'll be continually playing catchup, discussing the best way to implement the newest EcmaScript feature in Coffeescript syntax. In essence, it will be Ecmascript committees driving the core direction of Coffeescript, not the Coffeescript committers themselves. Already, because ES6 classes don't currently support data properties, we might have to remove Coffeescript class data properties. What happens when Ecmascript adds them back in?
From @lydell on 2016-09-08 09:19
@greghuc The biggest problems, in my opinion, are that you currently cannot extend an ES2015+ class (jashkenas/coffeescript#4233) and that CoffeeScript’s super
is both very complicated and very different from super
in ES2015+ (jashkenas/coffeescript#3796 might be informative).
From @greghuc on 2016-09-08 12:19
Also, to put a slight dampener on 'ES6 classes are the new awesome', here's a link to a curated list of resources on why ES6 (aka ES2015) classes are NOT awesome.
I'm not aiming to start an argument over the pros and cons of ES6 classes. However, it's worth keeping in mind that ES6 classes are a new and unproven technology, and it's unclear how things will play out with them. This is independent to how well ES6 classes are supported by browsers and nodejs.
This raises the possibility of Coffeescript nextgen locking itself to a feature that doesn't stand the test of time.
It doesn't preclude Coffeescript being able to interoperate with ES6 classes.
From @GeoffreyBooth on 2016-09-11 18:08
@greghuc I think your preferred approach (1 and 3) is what the esclass
proposal does. We leave the current class
alone, in all its awesomeness, and introduce a new esclass
that matches ECMAScript’s class
definition. If ECMAScript adds data properties, we add data properties to esclass
. Yes, this means we are following the ECMA standards body. But . . . CoffeeScript is a language that compiles to JavaScript. By definition the ECMA committee tail will wag the CoffeeScript dog.
What your “data properties” example illustrates, however, is that we should think long and hard before we add any sugar over esclass
. Since ECMAScript’s class
is subject to change, we very well could get ourselves into trouble if we add custom features on top of it. In general now that JavaScript is no longer static, we should refrain from implementing any new custom features that might someday get implemented natively in ECMAScript (especially if they might get implemented in an incompatible way, like class
or ...
). Presumably ECMAScript won’t break backward compatibility with the current spec for class
, so we can at least implement that; but no more than that, until ECMA finalizes those new additions.
I don’t think it’s so bad to follow ECMA. They’re moving way faster than we ever could. It’s not a bad thing to keep up with the JavaScript world.
From @GeoffreyBooth on 2016-09-14 03:14
I’ve been thinking about how Decaf manages to parse most CoffeeScript classes into ES2015 class
es. If we’re going to introduce ESNext output via a flag or 2.0.0 breaking-change version bump, then we could take Decaf’s approach and output ES2015 class
whenever the CoffeeScript class
isn’t doing anything incompatible (like code in class
bodies) and the current function
otherwise. What would people think of this approach?
Out of curiosity I ran Decaf on nodes.coffee
. It throw an error on any statement like [..., last] = body.expressions
, but if I commented them out, the only class it couldn’t parse was Op
, because of the lines starting with CONVERSIONS =
and INVERSIONS =
that technically are code in a class
body. But I feel like those could probably be refactored as @CONVERSIONS =
and just placed inside the constructor. Ditto for the children:
lines that Decaf simply loses in its conversion.
It’s another question whether these ES2015 class
es are truly functionally equivalent to the CS-generated function
versions. To figure that out, we’d have to either refactor all the [..., last]
lines throughout the code or fix Decaf to handle such lines; and refactor any other classes with class bodies; and update the test runner to use a version of CoffeeScript that was run through Decaf and then Babel. No small task, but perhaps worth it if we learn that most uses of class
could be output as ES2015 as is. Here is Decaf’s output for my modified nodes.coffee
(that comments out the troublesome lines); aside from the missing children:
properties, is there anything here in its conversion of classes that stands out to anyone as being problematic?
Assuming we wouldn’t use Decaf but would reimplement similar logic ourselves, is this an approach we want to take?
From @kirly-af on 2016-09-14 14:14
To be honest, I'm not so sure what are the exact points where CS classes and ESnext classes clash.
All I'm aware of are: super
behavior is different and CS classes have CS classes have an executable body.
Another issue is this.
However, this suggestion looks good to me.
From @jashkenas on 2016-09-14 14:19
To chime in:
find_by_name
in ActiveRecord, without the method_missing
hit. A (nicer, better, IMO) semantic for super
is the other.2.0
release (or 2.0-pre
, if we need to get it out early).esclass
and class
at-the-same-time compromise. That's hideous, hard to explain to learners, and unnecessary. If you're intentionally upgrading to CS2 to take advantage of new features, then take advantage of them.From @kirly-af on 2016-09-14 14:31
Glad to see @jashkenas join this discussion.
I couldn't agree more that adopting something like esclass
would be terrible.
I can live with those two breaking changes. Aligning super
semantic makes complete sense, though I wondered if @connec suggestion would be suitable to keep executable bodies.
From @jashkenas on 2016-09-14 14:37
I don't think we can hack in executable bodies, and that's a loss, but it's okay. ES class bodies are inherently static.
From @connec on 2016-09-14 15:00
I would lament losing executable class bodies when a compilation such as...
class Whatever {
...
}
(function () {
// executable class body statements
}).call(Whatever)
...is possible. I made a bigger comment on this here.
The only danger I can see with this would be ordering-based: if a CS class has executable sections mixed in with property definitions, the ordering would be lost. The only situation I think that would matter in would be calling a previously defined @method
, but since the executable happens after the class is defined, and if executable ordering is maintained, then that wouldn't be an issue.
From @jashkenas on 2016-09-14 15:05
That's a lovely try, but it wouldn't work in the slightest. For example, local variables in executable class bodies are available in the prototypal functions, like normal, through the closure. In this compilation they aren't. Boom. Broken backwards compatibility.
From @connec on 2016-09-14 15:07
In the other comment I addressed that issue with a wrapper, similar to the compilation classes have now:
let A = (() => {
let counter
class A {
constructor () {
this.id = ++counter
}
}
// Non-function prototype property
A.prototype.b = 'nice'
;(function () {
counter = 0
// other executable class body statements
}).call(A)
return A
})()
E.g., we hoist variables from the executable class body in to the IIFE wrapper.
From @jashkenas on 2016-09-14 15:10
We'd lose the ordering, as you mention. We'd lose the compilation into straightforward JS. And we still wouldn't be backwards compatible. It's not worth it.
From @connec on 2016-09-14 15:12
Slightly ignorant question, but in this case what precisely do you mean by "backwards compatible"? This would be compatible with the previous implementation of executable class bodies, as far as I can tell.
From @jashkenas on 2016-09-14 15:21
I don't really have time to get deep into it — but the best example, as always, is going to be working code that passes the current test suite. If we can get ES class + executable bodies working in a clean way, fantastic! But I'd put my money on "can't do it".
From @rattrayalex on 2016-09-14 16:21
@jashkenas thanks very much for the clear direction here. Personally I'm 100% on board. @GeoffreyBooth sound good to you?
In terms of adding the executable class body feature, @connec , when it comes time for a PR for the feature, it sounds like you'd be more than welcome to try to come up with a solution!
From @connec on 2016-09-14 16:25
Yes! I've just had a look at the current tests for classes and there are a few in there for executable class bodies. I'll look at adding some to exercise the ordering, and I'll keep my eye open for PR time :)
From @GeoffreyBooth on 2016-09-14 19:20
Something else to keep in mind is that we probably want to be wary about adding future “sugar” CoffeeScript features now that ECMAScript is changing so fast. A sugar feature is one like =>
that (when it was created) had no corollary in ECMAScript. If class executable bodies didn't already exist in our spec, I would oppose adding them as sugar because I would be wary of ECMAScript adding its own support for them in some way that’s incompatible with ours, like what they did with the splat operator.
In this case it’s probably better to try to support executable class bodies as a way to avoid breaking changes, since they’re already in our spec and out in the wild. But we should probably think long and hard before considering any future such “enhancements” that could get lapped by ECMAScript.
From @connec on 2016-09-15 16:51
Another relevant feature is class fields, which exist in CS but are only Stage 2 in tc39. So depending on the timeframe we may need to polyfill (as in my above comment), or alternatively decide to compile to non-standard JS (or remove them).
From @GeoffreyBooth on 2016-09-19 21:07
@connec or @rattrayalex or @kirly-af or @greghuc or @JimPanic or @DomVinyard or @mrmowgli or anyone else, would you like to take the lead on implementing this feature?
I’m happy to give you commit access to https://github.com/GeoffreyBooth/coffeescript, where you could create a branch to eventually submit as a PR. A shared branch means we could all contribute to the classes work as it develops.
From @mrmowgli on 2016-09-23 05:37
I would be willing to help work on this, although I still need some help understanding the current CS codebase. I added some wiki pages to this repo, consolidating comments across various threads on the way the various CS compilers work.
Would @JimPanic, @GeoffreyBooth, or @lydell be willing to add to the wikis and hopefully outline what it takes to add a new feature to the compiler?
From @GeoffreyBooth on 2016-09-23 06:03
@mrmowgli of course, though I’ve only implemented one feature and don’t understand the compiler all that well. See what I wrote and linked to here.
I’ve invited you to https://github.com/GeoffreyBooth/coffeescript. Would you like to create a classes
branch there? And I’m happy to invite anyone else who wants to collaborate on this. I’ll probably have some time to help on this, but not enough to lead it.
Fortunately with classes we’re only changing the output of the compiler, not adding new grammar; though unfortunately classes are one of the most complicated constructions in the compiler, so it’s a lot to sift through. But at least we’re simplifying it. Also, Node 6 has full support for native classes, so our tests can be straightforward like the bulk of CoffeeScript’s tests, unlike the string-comparison modules tests.
From @JimPanic on 2016-09-23 06:24
I've been reading through the compiler, trying to understand it more in-depth. But I'm nowhere near being able to explain it more than what's already present in @GeoffreyBooth's repo . Maybe this helps to get you started, though?
From @jashkenas on 2016-09-23 13:37
Fortunately with classes we’re only changing the output of the compiler, not adding new grammar; though unfortunately classes are one of the most complicated constructions in the compiler, so it’s a lot to sift through. But at least we’re simplifying it.
That's actually key. A Coffee -> ESNext implementation of classes should be able to delete a whole bunch of messy code — particularly in the Nodes file.
From @rattrayalex on 2016-09-23 17:19
I found this talk by jashkenas helpful as a high-level starting point, though you're probably already past that @mrmowgli . Might be a fun watch in any case, he's a good speaker.
From @GeoffreyBooth on 2016-09-24 17:06
I moved the parsing overview into the main CoffeeScript wiki: https://github.com/jashkenas/coffeescript/wiki/%5BHowTo%5D-How-parsing-works
@mrmowgli Most of the work will probably be in the Class
class in nodes.coffee
. Much of what it’s doing is finding class properties and bound functions and handling those appropriately; all of that can be removed. We won’t be supporting class properties anymore, and every function in an ES class is already bound to that class, so the distinction between ->
and =>
for methods is meaningless. You’ll need to find a way to output these methods using the new shorthand function syntax (foo() { }
) as the function
keyword isn’t allowed for defining class methods. We will also need to add get
and set
as keywords and output them appropriately.
To take MDN’s example:
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() {
return this.calcArea();
}
calcArea() {
return this.height * this.width;
}
}
I would think the way to generate this in CoffeeScript would be:
class Polygon
constructor: (@height, @width) ->
get area: ->
@calcArea()
calcArea: ->
@height * @width
From @kirly-af on 2016-09-25 21:48
Hi @GeoffreyBooth, first let me thank you for your endeavor concerning import/export.
Now, regarding Classes there are 2 points I'd like to discuss:
EDIT: also, I'm willing to contribute, but I don't have a lot of time to learn more about the compiler. For now, I'm afraid I won't be of any help so soon.
From @GeoffreyBooth on 2016-09-25 22:40
@kirly-af:
We would love to have your help! Hopefully as the 2.0 effort goes on, the compiler will start to get simpler to comprehend 😄
From @rattrayalex on 2016-08-06 21:33
This is a core feature that we should rally around submitting to jashhkenas/coffeescript in the near term.
Does anyone know of current leading efforts to accomplish this in the community? Perhaps we can lend a hand there.