Giter Club home page Giter Club logo

Comments (64)

jashkenas avatar jashkenas commented on July 23, 2024

Nice bug.

You're running into a JavaScript (mis)feature -- if you return an object from a constructor, that object will be the evaluated result of new Klass(), not the instance you were trying to make. Because, in CoffeeScript, all functions return their final value, you're getting the array back instead of a Test2. Adding a this as the final line of Test2's constructor fixes the problem.

It would be ideal if CoffeeScript could detect constructor functions, and not add the return statement to their final lines, but unfortunately because any JavaScript function can be used as a constructor, I'm not sure that this is possible. It might be better just to document that this needs to be the final line of a CoffeeScript constructor. Any ideas?

from coffeescript.

 avatar commented on July 23, 2024

Well to be honest, the sort way returning works now is sort of magic and weird to me. I'm used to do an explicit return and if none was given it returns none or nil. So it seems to me that behavior would be a better fit in combination with javascript wouldn't it?

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

I'm not willing to give up implicit returns, just to fix this special case for constructors. They're critical for the whole "everything should be an expression" idea that underlies CoffeeScript.

I guess CoffeeScript could suppress the auto-return for functions that have names starting with a capital letter, CamelCasedClassStyle, assuming that they must be a constructor function, but that would also be quite strange if you aren't expecting it.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

... a case for having a fully-fledged class model, e.g.

class Test1 {
  initializer: => this.test = "test"
  testFunction: => print("It works!")
}

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

@weepy: One of the reasons I dislike this idea is it is alot of reinvention. JS's prototype model means you can easilly roll mixins and other complicated things into the object system, whereas that sort of Class model makes it needlessly restrictive (i.e like Java)

As for the constructor thing, I don't like enforced naming styles. Can't we just add a "constructor" annotation?

blah = constructor a b c =>
    this.a = a
    this.b = b
    this.c = c

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I didn't mean that it should do anything like Base2, the code i suggested would compile like so :

var Test1 = function Test1() {
  this.initialize()
} 

Test1.prototype = function() {
  this.test = "test"
}

Test1.prototype.testFunction = function() {
  print("It works!")
}

You could take or leave the initialize idea (it's only an idea to make inheritance of the constructor more straight forward).

Another alternative would be to alias the prototype keyword (e.g like jQuery to fn)

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

Right, I am not suggesting changing semantics, but to fully convey the existing semantic richness of the prototype object system, you will need to come up with tons of new syntax, which I think is completely unneeded.

You're trying to cram Java like semantics into prototypal OO, and I don't like it.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I don't think I am. Really I'm just trying to figure out a different keyword to "prototype" which is both intimidating and confusing (particularly, to newcomers). It's also a pain to type :D

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

If we're going to address this issue, our answer needs to be capable of expressing the full semantic richness of JS's prototype system, as kamatsu says. The problem with exposing all of that plumbing directly is that it's very easy to break or mangle your prototype chain by accident.

I don't think that there's a place for Ruby or Java-esque classes in CoffeeScript. But we should have a convenient syntax for accomplishing the same patterns with prototypes, without the risk of messing up the chain.

extends and super are the start of it, but maybe a more holistic approach is needed, because of this constructor issue, and because it's pretty verbose to have to keep typing Klass.prototype.method:, over and over, as you're defining a superclass (parent object).

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

First off, CoffeeScript is lovely. Thanks for spending your time on it.

"You're running into a JavaScript (mis)feature..."
Agreed, but a nice aspect of CoffeeScript is that it is nearly semantically identical to JavaScript. In this case, if a constructor is going to return a value, I also find JavaScript's behavior to be more intuitive than CoffeeScript.

Seems there are at least 3 solutions here:

  1. Break semantic CS/JS semantic equivalence by having the constructor return a value. This is the current behavior. (I find this confusing.)
  2. Kamatsu's suggestion is great, but it also breaks semantic equivalence by having the constructor never return a value. (Better...)
  3. (2++) Adopt Kamatsu's suggestion, but allow functions to use the 'return' statements. 'return' would be implicit in all functions except for 'constructor', so the behavior would be standard CoffeeScript. However, a 'constructor' could 'return' which be equivalent to JavaScript. (Best?)

See http://gist.github.com/267191 (a mod of http://gist.github.com/266191)

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

I implemented 3 at
http://github.com/alsonkemp/coffee-script/commit/d9e07c31e8c9a53584f548ed0f771bf2aaa7c6e3

Sample CoffeeScript @
http://github.com/alsonkemp/coffee-script/blob/master/examples/constructors.coffee

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Hey Alson. Thanks for the patch. I have a couple of concerns:

  • Any function can be used as a constructor by writing new func(). So, having to manually tag constructors yourself isn't very foolproof.
  • Even if it was, it's not any easier to tag a function with constructor than it is to just put a this at the bottom of the function, and the latter doesn't have to introduce a new keyword.

So I'm thinking more along the lines of a complete complete class-definition syntax, if we pursue this. You'd have to have a clean way of saying: here is a class, this is its name, these are its methods, these are its properties, this is the constructor.

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

A lot of the current verbosity in creating a class lies in repeatedly writing Klass.prototype.method: ... when defining methods. What do y'all think of having a real prototype assignment operator? This:

Bird.fly:: wind => airspeed * wind * effort

Could compile into:

Bird.prototype.fly = function fly(wind) {
  return airspeed * wind * effort;
};

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I'd don't like how it looks like it's a method on Bird itself, prefer sthing like

Bird::fly wind => airspeed * wind * effort

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Yeah, you're right, and it doesn't even save that much. Nevermind.

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Taking the example from the current documentation, what do y'all think of something like this:

class Animal
  constructor: name =>
    this.name: name

  move: meters =>
    alert(this.name + " moved " + meters + "m.")


class Snake extends Animal
  speed: 5

  move: =>
    alert("Slithering...")
    super(this.speed)


class Horse extends Animal
  speed: 45

  move: =>
    alert("Galloping...")
    super(this.speed)

All methods and properties would be defined on the prototype, and the constructor would return "this", naturally.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

How would you go about adding further methods to the prototype. Perhaps Bird::fly isn't so bad after all.

Also, in this example, how would the base constructor get called from the subclasses?

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

If you wanted to add methods to the prototype from outside, you can just add them:

Horse.prototype.canter: => ...

You should be able to call your ancestor's constructor using super(), like any other method.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

Sorry - just to be clear, in this instance class Snake extends Animal, the Animal constructor would not be called?

I.e. as with normal JS, the constructor is not subclassed (something that's unfortunately confusing for newcomers).

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Hmm, in the case above, subclasses like Snake should call Animal's constructor unless they choose to override it, no? It might be tricky to implement.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

That's what it should do, but as you say implementation might be tricky. Coffee could keep track of implemented classes, but seems out of the question.

I suggested an implementation where each constructor automatically called an 'initialize' function with the inbound params which would then be subclassed automatically. The only problem I can see with this is that it means that every class would have an initialize function.

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

Jeremy,

w.r.t. creating a real Class mechanism: one of the aspects of CoffeeScript I really like is that it's basically just pretty JavaScript. Creating a Class mechanism would add to CoffeeScript something that is not within JavaScript, so I'd be less excited about that.

If you delete the word "Class" from your sample code, wouldn't you have clean CoffeeScript that is concise and doesn't imply anything special?

Animal:
  constructor: name =>
    this.name: name

  move: meters =>
    alert(this.name + " moved " + meters + "m.")

Snake extends Animal:
  speed: 5

  move: =>
    alert("Slithering...")
    super(this.speed)

subclasses like Snake should call Animal's constructor unless 
they choose to override it, no?

From my perspective, Javascript doesn't do that, so I wouldn't expect CoffeeScript to do so.

Alson

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Yeah, I agree completely, which is why there's been so much discussion on this page, and why we haven't moved forward with any of the proposals yet -- I don't think that my most recent posted one is very satisfactory.

Ideally, we can come up with something that keeps JavaScript's prototype flavor (avoiding class), encapsulates the common patterns for setting prototype properties and prototype chains, and provides a greatly shortened syntax. I don't think we've seen that yet -- the field is still wide open.

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

One last note: object prototypes already have a constructor member, so 'constructor' is probably a bad term to use (lest people be confused about whether they're modifying widget.prototype.constructor or not). Maybe '_'.

Animal:
  _ : name =>
    this.name: name
  move: meters =>
    alert(this.name + " moved " + meters + "m.")

Snake extends Animal:
  _ : name => super(name)
  speed: 5
  move: =>
    alert("Slithering...")
    super(this.speed)

This syntax is pretty nice and is just sugar. 'Snake extends Animal' is a little complicated because the constructor needs to be pushed up to run before the object is extended...

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

The way I tend to write objects in JS is perhaps appropriate here:

var animal = function() {
    //mixins added here
    mixin_stuff(this)
    var private_function = function (a,b) {
    }
    var private_variable;

    //constructor goes here

    this.public_function = function () {
        //Note how private stuff is inherited via closure
    }
    this.public_variable = 5;
}

I believe inheritance is a broken model (I am a haskell programmer by trade) so I tend to use mixins exclusively.

Anyway, the only problem faced by my object model in coffee is that I have to add "this" at the end. The model you are proposing is different, and unfortunately doesn't allow me to make private data via closure. That's why I'd rather a smaller change that just prevented the unsightly "this" from appearing at the end.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I was just playing with the example at the start - it's quite odd, since it works if the return value is a string, but not an array or and object. Quite odd?!

from coffeescript.

weepy avatar weepy commented on July 23, 2024

We could do somethign like:
Use :: or similar for an alias to this., unless it's preceded by a variable name, in which case, it's an alias to prototype.. So without the Class stuff, an example would be :

Animal: name --> 
  ::name = name
  ::move = meters -->
    alert(::name + " moved " + meters + "m.")

Animal::hello = --> alert("hello")

(I was just also experimenting with using = and --> in above)

from coffeescript.

weepy avatar weepy commented on July 23, 2024

or use @ in place of ::, for something more rubyesque.

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

I'm getting a bit confused in this thread... It started off simple (constructor behavior is unexpected) and got pretty complicated (I think there are now a number of separate features within this thread). Maybe we could move this discussion off onto a wiki page and do the following:

  • Add some real world, fairly large sample code gists. The gists we're looking at here are so short that the benefits are both minimal and different for each gist.
  • Enumerate the features:
    1. Align constructor behavior with JS's (maybe)
    2. Provide a bit of sugar for long .prototype. sections
    3. Provide a bit of sugar for long this.* sections
    4. Provide a bit of sugar for Classes (?)
    5. ???

Assuming that y'all are okay with that, I've added a wiki page to my repo and made you all collaborators. Feel free to edit to taste, to add example code, etc. See here:
http://wiki.github.com/alsonkemp/coffee-script/cs-issue-17

And shouts out to any Haskellers who're reading...

from coffeescript.

weepy avatar weepy commented on July 23, 2024

sorry alson - here's another idea to add to the melting pot: supress the return value if the function starts with a capital (it would still be possible to explicitly return from there functions).

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

Weepy,

Added. You're welcome to update the wiki page, too.

Alson

from coffeescript.

jnicklas avatar jnicklas commented on July 23, 2024

Sorry to be continuing the discussion here, but wikis really don't lend themselves for discussion, imho.

One problem that always crops up in JavaScript is that if the binding of a function changes (as is common for click events for example), it really screws up any attempt at using the 'this' keyword in a constructor. A common workaround is to assign 'this' to some other variable, such as 'self'.

I really like wimpy's suggested syntax, maybe CoffeeScript could do some analysis, like it does for scoping of variables and automatically resolve the "instance" variables correctly:

Animal: name =>
  @name: name
  @move: meters =>
    click(event => alert(@name))

would compile to:

var Animal = function(name) {
  var _this_12345 = this; // added because we are defining stuff with @

  _this_12345.name = name;
  _this_12345.meters = function() {
    click(function(event) {
      alert(_this_12345.name);
    });
  };
};

I have no idea how hard this is to implement, but it would remove a lot of the pain associated with working with constructors.

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

While I would like capitalized names, I sort of hesitate to use it as it reduces the ability to make partial ports of existing JS applications to coffee.

@alsonkemp: Haskell hi-5!

from coffeescript.

weepy avatar weepy commented on July 23, 2024

Yes - I feel the same about the capitalized. I think we just need a 'class' operator or similar that suppresses the return (note that you don't have to return this, you just have to avoid returning an array or an object) and handles any 'extends'.

from coffeescript.

jnicklas avatar jnicklas commented on July 23, 2024

Wasn't really thinking about that part of it. I agree, capitalization to determine if a function is a constructor is bad, especially since we can do stuff like:

Animal: x => this.x: x.
animal: Animal

Now animal is a constructor, even though it is lowercase?

from coffeescript.

weepy avatar weepy commented on July 23, 2024

jnicklas, your self idea is interesting. Perhaps @ on it's own could signify _this_12345 if it was required?

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024
  1. Cool, looks like we agree on capitalization: no assumptions about caps (or lack thereof).
  2. If we need to, there's no problem with having the compiler generate unique local variable names -- Scope#free_variable handles this.
  3. I agree that it's nice to have a discussion in a conversational format like this, but that longer code samples would also be valuable. Please feel free to link to Gists of longer samples, which can be forked and edited by others.
  4. There are a lot of proposals for different features/syntax in this thread, but that's not a bad thing -- we need a comprehensive proposal that addresses all the pieces of defining a class/parent-object: here is a class, this is its name, this is the superclass, these are its methods and properties, this is the constructor.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

Here's my stab :

http://gist.github.com/267997

I didn't address the 'self' idea as I felt there need to be some more discussion on the area. If we introduce that implicitly with @ - would it introduce any problems?

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

I disapprove of the use of the word "class" as JS has no such concept.

from coffeescript.

jnicklas avatar jnicklas commented on July 23, 2024

I agree. Why not just call it constructor, that's what it is, after all? (http://gist.github.com/268063)

from coffeescript.

weepy avatar weepy commented on July 23, 2024

yes i agree,construct could also work (avoiding the collision with JS keyword?)

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

It's not a problem to collide with JS keywords -- I'm using "extends" and "super", after all. They won't be present in the final JS.

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

Right, constructor isn't too bad.

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

A question for Jeremy: is CoffeeScript a sugaring of Javascript (better syntax; same semantics)? Or is CoffeeScript a fixing/normalization of Javascript (better syntax; some different semantics)?

If it's sugar, then I tend to agree with Kamatsu that 'class' doesn't seem like an appropriate addition.

If it's a clean-up/normalization, then adding 'class' is lovely.

I tend to use a number of existing JS libraries and would love to use them with CoffeeScript. The semi-guarantee of semantic alignment between JS and CS means that I can do so. If that semi-guarantee is at risk, then CoffeeScript is much less useful to me.

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

There should be no risk of semantic mis-matching between CoffeeScript and JavaScript. We're not adding anything to the runtime -- no extensions of core objects, no assumptions of special predefined helper functions, as convenient as it might be to have them.

On the other hand, CoffeeScript is only going to provide syntax for "the good parts" of JavaScript. Ideally, you wouldn't be able to write CoffeeScript that ever creates a warning in JSLint, without it being a syntax error in CoffeeScript first. We're not there yet, but it's a nice abstract goal.

We're definitely wandering away from "same semantics" with some of the syntax that compiles into larger chunks of JS: The existence operator ?, extends, array and object comprehensions, and slice and splice literals all come to mind.

Still, anything that you can write in JavaScript, you should be able to write in CoffeeScript -- including integration with JS libraries. If you can't, please file a bug.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

constructor leaves me with a bit of a empty feeling in my stomach. What exactly are we constructing? Whilst kamatsu is right that we're not creating a classical OO class system, I think it needs some kind of name. Maybe class isn't so bad after all (as long as we educate that it's not a classical OO class).

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

Except class isn't at all what it is. It has nothing but wrong connotations. The C++/Java choice of the "class" keyword is even a misappropriation from type theory that unfortunately permeated the lexicon. Constructor is a good keyword because you are defining a constructor for an object. You are in no way specifying a class.

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

Weepy,

What exactly are we constructing?

We're constructing whatever Javascript is constructing with its 'new' operator... 'constructor' is a notion from Javascript so would be good to mirror in CoffeeScript. In Javascript

new Klass();

behaves differently from

Klass();

CoffeeScript does not mirror this behavior so constructing an object in CS is error-prone if you expect CS to have JS's behavior.

Another possible solution to the issue with 'new' behavior is to adopt Javascript's behavior and wrap the function with a 'return this'. Wouldn't be pretty since every function would have to set something like 'coffee_script_last_this = this', then 'k = new Klass()' would compile to:

new Klass();
k = coffee_script_last_this;

Hackety way to ignore Klass's return value... Probably not thread safe...

from coffeescript.

weepy avatar weepy commented on July 23, 2024

fair enough guys - you're probably right. constructor it is ?

from coffeescript.

weepy avatar weepy commented on July 23, 2024

OK. I've updated the gist to use constructor. Can I get feedback please. http://gist.github.com/gists/267997

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

LGTM!

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

Just making sure that we have all of the bases covered (I liked Kamatsu's example code). In functions, we have notations to declare:

  • local variables
  • this variables
  • prototype variables

If we're going to adopt Ruby-ish syntax, then weepy's proposal looks good.

constructor cons : s => 
  priv_storage : s     # var priv_storage = s;
  @pub_storage : s   # this.pub_storage = s;
  @@pro_storage : s  # this.prototype.pro_storage = s;

These notations, suitably modified, should also work when applied to an object:

priv_storage : s      #var priv_storage = s;
obj@pub_storage : s     # obj.pub_storage = s;
obj@@pro_storage : s  # obj.prototype.pro_storage = s;

One issue is that this notation could cause confusion for Ruby programmers since '@' deals more with privacy than with storage location (both priv_storage and @pub_storage are stored locally, but priv_storage is only available while inside the object).

[ARGH... Github's sometimes-Markdown, sometimes-Textile markup is killing me.]

from coffeescript.

weepy avatar weepy commented on July 23, 2024

Alson, I think you've confused the prototypes with constructor's here. I think it's more like:

constructor Obj : s => 
  storage : s     # var storage = s;
  @storage : s   # this.storage = s;
  @@storage : s  # this.constructor.storage = s; // or Obj.storage = s 
storage : s      #var local_storage = s;
Obj@storage : s     # Obj.prototype.storage = s; // mostly useful for instance variables and functions
Obj@@storage : s  # Obj.storage = s; // this is a bit pointless? 

Essentially @ is used for instance variables. I'm not sure whether the @@ syntax is useful enough to include?

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

Doh. Never type before having coffee...

I guess I'm a little confused by the syntax, so was hoping to straighten it out a bit. From your sample it appears that @ sometimes refers to this and sometimes to prototype. An alternative might be to use '.' for instance and '@' for prototype. This would be simple sugar and would match up well with JS:

constructor f : =>
  a : 1 # var a =1;
  .b : 2 # this.b = 2;
  that.c : 3 # that.c = 3;
  that@d : 4 # that.prototype.d = 4;
  that..d : 4 # alternative syntax for that.prototype.d = 4;

a : new f()
.d : 5 # error: no 'this' available
a.d : 5 # a.d = 5;
a@d : 6 # a.prototype.d = 5;
a..d : 6 # alternative syntax

would be lovely to get Jeremy's thoughts here..

[hard to do this via the phone browser!]

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Sure, Alson. Sorry to have been so quiet. This is all a little too nebulous to try and get into CoffeeScript 0.2, so I've been trying to get that ready to release before turning back to this issue. It's a pretty epic thread though -- clearly doing JavaScript inheritance correctly is something that everyone has an interest in seeing happen. I'm happy to let folks come to consensus on a reasonable syntax before trying to build the thing.

But still, some opinions:

  • I'm not a big fan of @, especially when nothing is really private in JavaScript (except local variables). Writing out this.property isn't so bad, and is conceptually consistent with everything else in JS.
  • If we need a shorthand to read and set properties on the prototype, I kind of like weepy's proposal: Bird::fly compiles to Bird.prototype.fly. It would also provide quick access to the core prototypes: Object::hasOwnProperty.apply(...)
  • I'm torn about tagging constructors with constructor, if it's not doing any more than suppressing the return value, but I don't see a better alternative. It looks especially alien with constructor SubObj extends ParentObj: => .... Maybe extends should always be on a line of its own.

Gotta run...

from coffeescript.

jnicklas avatar jnicklas commented on July 23, 2024

To me the reason to use @property and not just this.property is the scoping problems inherit in this that I mentioned before. The fact that this can change with the function binding can be extremely annoying. Using jquery, for example:

$('.something').each() => item
  @submit: href => $.post(href)

  item.find('a').click() =>
    href: $(this).attr('href')
    @submit(href)
    this.remove()

Here, there is clearly a semantic difference between @submit and this.remove. @submit works as though it was a locally declared variable, and becomes part of the closure, this is how it should work, imho.

Regarding the issue with nothing being "private", why carry over this notion from Ruby? I see the @ sign as signifying "public" here, as in, "this property is publically accessible for all objects created by this constructor".

from coffeescript.

alsonkemp avatar alsonkemp commented on July 23, 2024

re: @Property: this implies the addition of the uniqueified 'this', right? (this.this_12345 = this)

Jeremy: thanks for stopping by! ;)

'constructor' notation: this seems error prone. If you forget to include 'constructor' then funky and very hard to detect errors occur. (yes, I have totally flip flopped.) I'm a fan of actually implementing 'new' in CS so that it operates the same as in JS. Might be ugly, but it seems like the best thing to do...

'this' and 'prototype' : since CS is just sugar, I'd prefer to let people elide bits that can reasonably be inferred and 'this' and 'prototype' can be inferred in the following:

.prop # this.prop
inst..prop # inst.prototype.prop

Simple to implement and tightens up the code. It includes a slight risk of turning typos into valid statements.

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

@jashkenas: whoa whoa whoa, did you just say nothing is really private in javascript? Where did you get that notion? behold!

function objectWithPrivateData() {
    var private_data = 5;
    this.method = function() {
          private_data++;
          return private_data*2;
    }
}

var a = new objectWithPrivateData()
print(a.method()) // = 12
print(a.method()) // = 14

from coffeescript.

 avatar commented on July 23, 2024

Yeah, yeah, local variables are only accessible from within the closure, sure. Maybe it's just because it doesn't feel like a real private variable (but I'm probably just being old fashioned). Note that when you add methods like this, within the constructor, you have to re-create them every time you instantiate a new object (not-so-efficient), and they're not shared with other instances of the class. And yes, there are ways around this, but they're fairly awkward, which is an opportunity for us to address.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I never meant @ to mean anything about public and private, or to point to _this_12345 idea ( a separate discussion).

It's just an alternative syntax to my :: suggestion, i.e sugar for this. and prototype.

@prop compiles to this.prop
Bird@fly compiles to Bird.prototype.fly

I like it because:

  1. it's sugar and so exposes the 'real' machinery,
  2. it's fairly compact (this. and prototype are typed alot in JS)
  3. has a consistency (@ implies the notion of property of instance).

Lastly I'd like to make the case of @ over . and :: -- It stands out more and doesn't get confused with assignment (:)

from coffeescript.

liamoc avatar liamoc commented on July 23, 2024

@documentcloud: If the constructor adds methods, the efficiency cost is about as low as a hashtable lookup on each method creation. This is not C and we're already talking about awful performance generally for most JS VMs, a variable assignment is the least of your worries.

As for privacy, closures and objects are actually proven equivalent, so your idea of a closed variable being not a "real" private variable is hogwash, you can mathematically reason about either identically.

Also, they are shared with other instances of the prototype (not class), provided that prototype's constructor calls the previous constructor. This provides a convenient mechanism for implementing mixins and a very expressive object system. A true prototype object system such as Potion's would eliminate the out-of-constructor prototype manipulation, which is just a hack that JS adds.

from coffeescript.

weepy avatar weepy commented on July 23, 2024

I'm splitting this ticket out into several ... it's getting too confused.

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

Thanks for splitting it weepy, retiring this thread from the open issues...

from coffeescript.

jashkenas avatar jashkenas commented on July 23, 2024

As of Issue #210, CoffeeScript has classes, which fixes the constructor / return value trouble.

from coffeescript.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.