In Ruby, how does one add to an object a method with access to variables in outer scope?
I'm new to Ruby. I'm at the stage where I'm unsuccessfully attempting to write things in Ruby as I would in some other language.
I'm trying to add a method to an object – a humble array, let's say. Not to all arrays, just to one specific one. This method must have access to a variable in outer scope.
My understanding is that I can use def
to add a method to an object, but that methods do not have access to variables in outer scope. For开发者_开发技巧 that I'd need to use lambda
or Proc.new
, but I can't see how I'd "attach" the lambda/proc to the array as a property.
In JavaScript this is straightforward, as this silly example demonstrates:
var x = 3
var array = [1, 2, 3, 4]
array.multiply_by_x = function() {
var i = this.length
while (i--) {
this[i] *= x
}
}
Is something similar to the above possible in Ruby?
You can't use def keyword to define the method here because it will introduce another scope. If you would like to define a method to only a specific object, then you have to define it in singleton class.
x = 3
array = [1, 2, 3, 4]
array.define_singleton_method(:multiply_by_x) do
self.map!{|e| e * x }
end
But if you are are using Ruby 1.8.x, you have to do this:
(class << array; self; end).send(:define_method, :multiply_by_x) do
self.map!{|e| e * x }
end
Note: It's not related to this question, but if you would like to see different ways to define singleton methods.
Monkey-patching Array
would do this, but it would do it for all instances of Array
.
class Array
def multiply_by(x)
self.map! {|n|
n * x
}
end
end
If you want to arbitrarily monkey-patch a method onto an existing object, I don't think this is really possible.
One thing that you could do is use a Hash
with a lambda
:
x = 3
hash = {:array => [1,2,3]}
hash[:multiply_by] = lambda {
hash[:array].map! {|num|
num * x
}
}
You'd then call the multiply_by
lambda like so:
hash[:multiply_by].call
I would rather do like that:
ary = [1, 2, 3, 4]
def ary.multyply_by(x)
self.map! {|e| e * x}
end
p ary.multyply_by 10
As a side note, it is much better to use function parameters than highly-scoped variables. Scopes are a way to avoid clashes, not obstacles.
精彩评论