6

To be clear - this code is running perfectly - code with proc

but if instead I change Proc.new to lambda, I'm getting an error

ArgumentError: wrong number of arguments (1 for 0)

May be this is because instance_eval wants to pass self as a param, and lambda treats as a method and do not accept unknown params?

There is two examples - first is working:

class Rule
  def get_rule
    Proc.new { puts name }
  end
end

class Person
  attr_accessor :name

  def init_rule 
    @name = "ruby"
    instance_eval(&Rule.new.get_rule)
  end
end

second is not:

class Rule
  def get_rule
    lambda { puts name }
  end
end

class Person
   attr_accessor :name

   def init_rule 
     @name = "ruby"
     instance_eval(&Rule.new.get_rule)
   end
end

Thanks

Community
  • 1
  • 1
sandric
  • 2,310
  • 3
  • 21
  • 26

1 Answers1

4

You are actually correct in your assumption. Self is being passed to the Proc and to the lambda as it is being instance_eval'ed. A major difference between Procs and lambdas is that lambdas check the arity of the block being being passed to them.

So:

 class Rule
   def get_rule
     lambda { |s| puts s.inspect; puts name; }
   end
 end


class Person
   attr_accessor :name

   def init_rule 
     @name = "ruby"
     instance_eval(&Rule.new.get_rule)
   end
end

 p = Person.new
 p.init_rule

 #<Person:0x007fd1099f53d0 @name="ruby">
 ruby 

Here I told the lambda to expect a block with arity 1 and as you see in the argument inspection, the argument is indeed the self instance of Person class.

Michael Papile
  • 6,836
  • 30
  • 30
  • Isn't it `p.get_rule` instead of `p.init_rule`? – elquimista Sep 12 '17 at 09:42
  • No it isn't. The code originally posted is calling instance_eval when calling `Person#init_rule` which is what I called and got that input, and the subject of the question. Editing my answer back to what it was. – Michael Papile May 14 '19 at 12:16