Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Ruby 1.9.2-rc1: instance_eval can't handle a lambda (needs a proc)
class InstanceEval
def initialize(code)
@code = code
@context = Object.new
end
def run
code = @code
result = @context.instance_eval(&code)
"* run --> #{result.inspect}"
end
end
p = proc { :p }
l = lambda { :l }
puts InstanceEval.new(p).run
puts InstanceEval.new(l).run
# The output in 1.8.7-p72 and in 1.9.1-p378:
#
# * run --> :p
# * run --> :l
#
# The output in 1.9.2-rc1:
#
# * run --> :p
# code.rb:15:... wrong number of arguments (1 for 0) (ArgumentError)
# from code.rb:10:in `instance_eval'
@sunaku

This comment has been minimized.

Copy link

@sunaku sunaku commented Jul 17, 2010

The ArgumentError highlights the primary difference between proc and lambda: lambdas are like real methods, they do not accept arguments other than those specified in their parameter list. In contrast, procs are lenient and will accept less/more arguments than specified in their parameter list.

$ irb
## ruby 1.8.7 (2010-06-23 patchlevel 299) [i686-linux]
>> Object.new.instance_eval {|*args| p args }
[#<Object:0xb72f517c>]
=> nil

$ irb
## ruby 1.9.1p378 (2010-01-10 revision 26273) [i686-linux]
>> Object.new.instance_eval {|*args| p args }
[]
=> []

So it seems the Ruby 1.9 instance_eval() no longer passes the self object as a block argument.

@gsinclair

This comment has been minimized.

Copy link
Owner Author

@gsinclair gsinclair commented Jul 18, 2010

I've updated the gist to show the specific versions in which the code worked. It works in 1.9.1-p378 but not 1.9.2-rc1 so it's probably a regression.

Lambdas and procs are confusing things (unfortunately) but I don't think their deliberate differences are the cause of this ArgumentError.

@gsinclair

This comment has been minimized.

Copy link
Owner Author

@gsinclair gsinclair commented Jul 18, 2010

Update from nobu on ruby-core:

No, it not the point. Now instance_eval yields the self.

I was unaware of instance_eval ever yielding self, so I missed some of your meaning above, sunaku.

Now I'm wondering: when did instance_eval start yielding self, and why? Has it been going on for ages without my knowledge? ;)

@sunaku

This comment has been minimized.

Copy link

@sunaku sunaku commented Jul 18, 2010

That makes more sense. So Ruby 1.9.1 had a bug where instance_eval() did not yield self, and that bug was corrected in Ruby 1.9.2. According to my 1st comment, Ruby 1.8.7 also yields self just like Ruby 1.9.2, so yes it was just an unnoticed (because block parameters are not enforced in procs & blocks) feature of instance_eval().

@marick

This comment has been minimized.

Copy link

@marick marick commented Jan 8, 2012

Why does instance_eval pass self as the first argument to its argument (given that self is already implicitly available)?

@sunaku

This comment has been minimized.

Copy link

@sunaku sunaku commented Jan 9, 2012

@marick, the reason is not known. Ruby 1.8.7 just does it (see example output above).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment