在Ruby中,如何向对象添加一个可以访问外部作用域中的变量的方法?

时间:2011-10-11 04:02:20

标签: ruby methods lambda lexical-scope

我是Ruby的新手。我正处于试图用Ruby编写东西的失败的阶段,就像我在其他语言中那样。

我正在尝试将一个方法添加到一个对象 - 一个简陋的数组,让我们说。不是所有数组,只是一个特定的数组。此方法必须能够访问外部作用域中的变量。

我的理解是我可以使用def向对象添加方法,但该方法无法访问外部作用域中的变量。为此,我需要使用lambdaProc.new,但我无法看到我如何将lambda / proc作为属性附加到数组中。

在JavaScript中,这很简单,正如这个愚蠢的例子所示:

var x = 3
var array = [1, 2, 3, 4]

array.multiply_by_x = function() {
  var i = this.length
  while (i--) {
    this[i] *= x
  }
}

在Ruby中是否有类似上述内容?

3 个答案:

答案 0 :(得分:4)

您不能在此处使用def关键字来定义方法,因为它将引入另一个范围。 如果要仅为特定对象定义方法,则必须在单例类中定义它。

x = 3
array = [1, 2, 3, 4]

array.define_singleton_method(:multiply_by_x) do
  self.map!{|e| e * x }
end

但是如果你正在使用Ruby 1.8.x,你必须这样做:

(class << array; self; end).send(:define_method, :multiply_by_x) do
  self.map!{|e| e * x }
end

注意:这与此问题无关,但如果您想查看different ways to define singleton methods.

答案 1 :(得分:1)

Monkey-patching Array会执行此操作,但它会为Array的所有实例执行此操作。

class Array
  def multiply_by(x)
     self.map! {|n|
        n * x
     }
  end
end

如果你想任意地将方法修补到现有对象上,我认为这不可能。

您可以做的一件事是使用Hashlambda

x = 3
hash = {:array => [1,2,3]}
hash[:multiply_by] = lambda {
   hash[:array].map! {|num|
      num * x
   }
}

然后你就像这样调用multiply_by lambda:

hash[:multiply_by].call

答案 2 :(得分:0)

我宁愿这样做:

ary = [1, 2, 3, 4]

def ary.multyply_by(x)
  self.map! {|e| e * x}
end

p ary.multyply_by 10

作为旁注,使用函数参数比使用高范围变量要好得多。范围是避免冲突的一种方式,而不是障碍。