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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With