Search code examples
rubymethodslambdalexical-scope

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?


Solution

  • 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.