class @Point construc...">

CoffeeScript: How to return an array from a class?

What is wrong with this class in CoffeeScript?

@module "Euclidean2D", -> class @Point constructor: (x,y) -> return if Float32Array? then Float32Array([ x, y ]) else Array(x,y) 

I want him to behave like this:

 p = new Point(1.0,2.0); p[0] == 1.0 p[1] == 2.0 

But testing with Jasmine, I get "Expected undefined equal to 1".

 describe "Point", -> beforeEach -> @point = new Euclidean2D.Point(1.0,2.0) it "extracts values", -> (expect @point[0]).toEqual 1.0 (expect @point[1]).toEqual 2.0 

Is there a bug in CoffeeScript or in Jasmine?

And all this in a module like:

 @module = (names, fn) -> names = names.split '.' if typeof names is 'string' space = @[names.shift()] ||= {} space.module ||= @module if names.length space.module names, fn else fn.call space 

In the Chrome console, I get:

 a = new Euclidean2D.Point(1.0,2.0) -> Point a[0] undefined b = new Float32Array([1.0,2.0]) -> Float32Array b[0] 1 

EDIT: again .. sorry

Decided to use a combination of @brandizzi and @ arnaud576875 answers. @module, proposed on the official Wikipedia CoffeeScript, does not work. Result:

 class @Point constructor: (x, y) -> return if Float32Array? then Float32Array([ x, y ]) else Array(x,y) 
+4
source share
2 answers

You must use new to create the object:

 p = new Euclidean2D.Point(1.0,2.0) 

If you want to return Array from the constructor, do this explicitly:

 constructor: (x,y) -> return if Float32Array? then Float32Array([x,y]) else Array(x,y) 

(By default, Coffeescript does not return values ​​from the constructor, so you need to do this explicitly.)


You could do this too:

 class @Point constructor: (x,y) -> @[0] = x @[1] = y 
+1
source

You define a constructor, but expect it to behave as a function. However, the constructor simply sets the values ​​in the returned object. Since your constructor does not set any attributes in the initialization object, this is really not useful.

You have several alternatives:

  • Initialize the class as @amaud sugested.

  • It returns the value from the constructor as @amaud sugested (which does not make much sense to me. This is not a constructor function as I feel it. In this case, solution # 3 looks better).

  • define a function instead of a class. IMHO, is the simplest and most functional solution

     @Point = (x, y) -> if Float32Array? then Float32Array([x,y]) else Array(x,y) 
  • If you want Point be either a Float32Array or Array specialization, use option # 1, but make Point inherits from the class you need:

     superclass = if Float32Array? then Float32Array else Array class @Point extends superclass constructor: (x,y) -> @[0] = x @[1] = y 

EDIT : @ amaud676875 posted an interesting question as a comment. Since a reasonable answer will include some code, I am posting the answer as an edit.

@amaud, to test your point, I wrote the following CoffeeScript module:

 class Float32Array extends Array first: -> # Just for testing @[0] superclass = if Float32Array? then Float32Array else Array class @Point extends superclass constructor: (x,y) -> @[0] = x @[1] = y 

Then I imported the module into the console:

 coffee> point = require './point' { Point: { [Function: Point] __super__: [ constructor: [Object], first: [Function] ] }, Float32Array: { [Function: Float32Array] __super__: [] } } 

and created Point :

  coffee> p = new point.Point 3, 2 [ 3, 2 ] 

This Point has a first() method from Float32Array :

  coffee> p.first() 3 

and instanceof say this is also an instance of Float32Array :

 coffee> p instanceof point.Float32Array true 

So, I put that new Point x, y returns an instance of Float32Array . Of course, this is an instance of Point , and that is not a problem, because Point is-a Float32Array to use the classic OOP expression.

+1
source

All Articles