gkz / LiveScript

LiveScript is a language which compiles to JavaScript. It has a straightforward mapping to JavaScript and allows you to write expressive code devoid of repetitive boilerplate. While LiveScript adds many features to assist in functional style programming, it also has many improvements for object oriented and imperative programming.
http://livescript.net
MIT License
2.31k stars 156 forks source link

How to implement an Object with setters/getters? #1078

Closed ceremcem closed 5 years ago

ceremcem commented 5 years ago

I'm using implements feature mostly for splitting a huge class into smaller files, require! them and build again.

The problem is that the split sections can not contain the relevant getters/setters, which I guess because their contexts are not bound. In the following example, we need to split foo related tasks into another object:

foo = 
  foo-prop: ~
    -> @id

  foo-id: -> 
    @id 

class Hello implements foo
  (@id) ->  
  x: ~
    -> @id

y = new Hello 5
[y.x, y.foo-prop, y.foo-id!] # => [5,null,5] (expected: [5,5,5])

How can we make y.foo-prop return the @id?

rhendric commented 5 years ago

implements is basically shorthand for importing all the properties off the object, so this ‘shouldn't’ be surprising (although I definitely see how it is surprising, particularly from the perspective of some languages not from the JavaScript family)—implements gets all the properties from foo and puts them on Hello.prototype, one of which is foo.foo-prop, which evaluates to foo.id, which is undefined, so Hello.prototype.foo-prop is assigned the value undefined. This is the big difference between a getter and a getWhatever method in JavaScript: when you naively loop over the properties of an object, you get the definition of a method but the value of a getter (assuming that the getter is enumerable, which is the case when using the LiveScript getter syntax but not when using getter syntax in native JavaScript). Getters aren't intended just to be a shorter way to say getWhatever(); they have different semantics, and you should use them if you want those semantics and avoid them if you don't.

If you want to do this anyway, you'll have to do something like

Object.define-properties Hello::, Object.get-own-property-descriptors foo

instead of implements foo.