Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CoffeeScript dynamic methods

I'm trying to create methods dynamically in coffee script, but as my code shows, the iterator I use to create the methods doesn't reset its variables between iterations and so I en up with shared variables that conflicts:

class MyClass
  constructor: (@name) ->

  for k, v of ['get', 'set']
    console.log('creating method: ' + v)
    MyClass::[v] = (args...) ->
      method = v
      console.log('executing method: ' + method)

o = new MyClass('dummy')
o.get()
o.set()

Outputs:

> creating method: get
> creating method: set
> executing method: set
> executing method: set

one knows what I'm doing wrong?

like image 252
loopole Avatar asked Jun 28 '11 15:06

loopole


2 Answers

mu has correctly diagnosed the problem. The most direct solution is to use the CoffeeScript language's do keyword, which creates and runs an inner function that captures the values of the variables you pass in:

for k, v of ['get', 'set']
  do (k, v) ->
    console.log('creating method: ' + v)
    MyClass::[v] = (args...) ->
      method = v
      console.log('executing method: ' + method)

I talk about this feature in my PragPub article, A CoffeeScript Intervention.

like image 66
Trevor Burnham Avatar answered Oct 25 '22 07:10

Trevor Burnham


Your inner function:

(args...) ->
  method = v
  console.log('executing method: ' + method)

is actually a closure on v so when it is executed, v will evaluate to its last value in the loop (i.e. set). Looks like you just need a bit of closure busting:

build_method = (v) ->
  (args...) ->
    method = v
    console.log('executing method: ' + method)

And then:

for k, v of ['get', 'set']
  console.log('creating method: ' + v)
  MyClass::[v] = build_method(v)

Keep in mind that CoffeeScript is just JavaScript with different makeup so it suffers from a lot of the same problems (as does any language with closures) and those problems have the same solutions.

like image 36
mu is too short Avatar answered Oct 25 '22 07:10

mu is too short