-
Notifications
You must be signed in to change notification settings - Fork 2k
It's back: executable class bodies and local methods #640
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
Comments
I can't think of a good way to deal with Besides properties, another possible use for this is function decorators. So one might do, for example:
I'm actually thinking about doing some basic RPC over WebSockets. Decorating and/or adding properties to functions could be useful for that. Perhaps to help compressors, rather than call the scope function in the prototype context, simply pass the prototype as a parameter? Would require a bit more effort when parsing Finally, Ruby has this odd feature that allows you to reopen a class definition. It seems within grasp, but I'm not sure if it's something you want to support. |
In Kaffeine, I decided to make the class declaration as the function constructor , as that makes it closer to the raw Javascript (and hence executable class bodies). E.g.: class User(name) @name = name fn = -> doSetup() ::fullName = -> @first + " " + @second ::active = -> !!@lastActivityAt |
A Ruby ActiveRecord-like example that may fit within this proposal:
Stan made a gist with a possible compiled version of this. |
Ok ... I've played around with a draft of this, on a branch, here: http://github.com/jashkenas/coffee-script/tree/executable_bodies If you're interested in it, I encourage you to check out the branch, and play around. Note that the compiler is only partially converted -- only I'm not planning on merging it to master unless there are some really compelling demonstrations / examples, but as a proof of concept, it's there -- thanks to Stan's neat prototype-as-the-target-of-the-class-body trick. |
I have been trying to come up with examples that can be unique on their own, but unfortunately pretty much everything I have tried can be accomplished in Coffee already. Here is an example with the new syntax:
and here is the alternative that is already compiling:
I'd much rather have typed
On a side note, I am still in favour of using
|
Is there still no known way to allow private methods to access the instance through |
I don't understand why you dont make the class body simply the constructor like normal javascript. Doesn't this cover all the use cases ? |
@michaelficarra: Unfortunately, there's no easy way. JavaScript determines what @StanAngeloff: The way I see it, it gives us neat syntax for accessing the prototype and doing all sorts of things with it, rather than just assign attributes. So that's the direction I would look in for possible uses. The A simpler example might be a mixin. Currently, you would do something like Another idea I mentioned was RPC. Basic part of that is serialization, which could happen as follows:
|
A simpler, more native approach
into For the cons, we could use a little magic that appends |
Hmm. I do see the benefit of executable class bodies, but I'm not sure about the syntax for declaring private and public methods that you propose here. What about class methods that were previously declared using the @ symbol. See my ticket on private methods (#651) for my proposal which would use a similar syntax to what Ruby uses for declaring private methods. Also, I like the colon syntax that classes have now rather than the = sign that you propose here. |
Also, my proposal (ticket #651) addresses the issue of accessing |
I feel like things have been watered-down a bit so back to my main concern: I am still in favour of using
How are we going to address the issue with resolving |
Agreed that this is quite confusing. I'd expect
...and thus not in favor of this (see my mockup above). |
As a combination of StanAngeloff and Satyr's suggestions, I present my own proposal:
Unfortunately, it suffers the same problem that they all do, with private methods unable to access the instance unless explicitly called with the instance as its context. I agree with StanAngeloff that the @ represents an instance everywhere else and should be consistent inside class definitions. |
All these syntax proposals have gotten awfully cluttered. Supplying fields for whether values are public or private seems both unnecessary and confusing. Frankly, if a class body is going to be executable (which I think it should be), it needs to appear similar to an ordinary function. While the current implementation is a 'good enough' approach that appears as a classical OO programmer would expect, because of the way Javascript works they may occasionally be caught out. It's also important to note that it's practically impossible to implement classic OO classes in Javascript in a manner that doesn't hog memory. An implementation would need to account for the three different types of properties an object can have in Javascript: local to the constructor, public with local access, and public by attachment to the prototype. Each has their place in Javascript, and each should be easy to use, and clear in their use. As a result, I agree almost wholeheartedly with weepy's suggestion, which makes it very clear where function are being assigned to (due to their prefix) and what they have access to (due to their indentation). As stated above, though, if a class body is going to be runnable then it should appear so. How about this as a suggestion, then: |
@Tesco: those are some nice examples, but I still have some doubts.
The many syntaxes show the struggle to understand and somehow hide the underlying JavaScript object system. |
Remember, folks, that we didn't have classes for a long time, and the current class system is just simple sugar for generating a class from an object literal full of prototype properties... Tesco: Your example can be written like this with the current CoffeeScript:
The only difference being a regular function def instead of |
@stephank: I considered those points before writing the examples. I originally had the @jashkenas: Right. The real point of my proposal is simply brevity while overcoming the automatic return problem we had until the current sugar was created. I believe the current class syntax too closely mirrors classic OO style without fully implementing the concepts. |
@jashkenas: Don't forget you'd have to return |
Tesco: got a minute to pop into |
If we are going to do private methods, we need to do a real implementation not just some half baked solution. That means that those methods must have access to Maybe we should just stick to executable class bodies for now until someone comes up with a feasible syntax and implementation of private and public methods. |
I have to pretty much completely disagree with devongovett here. Private methods in javascript just don't have access to this, whether natively or through some framework or higher level abstraction. This fact should be understood by all JS developers and accounted for by them manually writing private method calls in the form |
@michaelficarra it depends on what you want. If you want classes to act like a JS closure in that they can contain internal properties and values that are not available externally, this solution is just fine. However, if you want true private methods that act like they are a part of the class you are defining (which would only be intuitive), calls to private methods need to be compiled into The currently proposed implementation (for private methods, not executable class bodies) can be accomplished with the current CoffeeScript by doing the following:
The above example is intuitive because the private function is not inside the class definition itself. Thus, it shouldn't have access to the If we are going to do the work to add a nicer syntax to the language to accomplish something that can already be done with the current CoffeeScript, why not go the extra mile and make the implementation work as users will expect it to work? |
Let's put private/local methods to rest for a moment (or split them in a separate ticket). Jeremy, any thoughts on the EDIT: |
Food for thought:
Locals would be class locals, not instance locals. |
Here's a way to solve “this” problem using my old proposal: stop treating By That is, code like:
is compiled into something like:
That way you can have your private functions with access to |
@andreyvit: unfortunately, that would restrict access to the real context value in
I would expect this code to return |
@michaelficarra: right, in this case |
The current implementation of classes takes away things from the developer that are possible in plain Javascript, and this proposition gives those things back. It's also syntactically sound and converges use cases to work on the same principles (ie. |
Wanted to express my position again -- I am happy to take a stab at the grammar/core to allow for the case I've initially proposed -- |
Then I'll happily put this one to rest.
The object has a number property, and a function that returns the value of
... should work in an analogous fashion, and indeed does in the current coffeescript. Local functions also don't belong in class definitions -- if you'd like to create a local function, you can certainly do so above the class, items in the class definition itself should either be attached to the class itself, or to its prototype. Closing the ticket -- thanks for the nudge, Stan. |
FYI, I've now got a draft of executable class bodies up over here: https://github.com/jashkenas/coffee-script/issues#issue/841 |
I have been thinking about extending the classes in CoffeeScript. Two of the most requested features so far have been executable class bodies and local methods. I have to agree, both provide extensibility and great control. So, without further due, here is what I have in mind:
while
blocks=
and prefixed with a@
. The current notionfn: ->
makes sense if we think of theclass
as an object bag, but it's not going to be just that any more@
Here is the stuff outlined so far in action:
Nothing too major and no big breaking changes. To build on top of that, let's add some executing code:
The above adds a property to the prototype of
Hello
and defines two methods on it to act as getters/setters.But enough about the goodies we get, let's think about side effects and bad design choices we can work over so we can move this baby forward:
this
is not available in local methods - let's not fuss about this too much. It's JavaScript and we can document it@@
or any other combination of symbols to be defined - it's an inconvenience more than an issue, but I am sure we can think of a better way to deal with this. As for referencing local methods inside a static function, I reckon this is not necessaryfn = ->
to define functions. Also@
references an instance everywhere else except within classes where it references the definition, not the reference. The proposed changes address thisMy two requests: Do you find executable class bodies useful? If so, what potential issues do you see and how do we fix 'em?
The text was updated successfully, but these errors were encountered: