Instance_eval does not work with do/end block, only with {}-blocks

558 Views Asked by At

If I have a class:

class KlassWithSecret
  def initialize
    @secret = 99
  end
end

and run:

puts KlassWithSecret.new.instance_eval { @secret }

it prints 99, but if I run:

puts KlassWithSecret.new.instance_eval do
  @secret
end

It returns an error: `instance_eval': wrong number of arguments (0 for 1..3) (ArgumentError)

Why can't I use do/end blocks with instance_eval?

P.S. I am using Ruby 2.1.0.

5

There are 5 best solutions below

0
Marek Lipka On BEST ANSWER

It's because when you pass block with curly braces, it is passed to instance_eval method. But if you pass it with do-end, it's passed to puts method, so instance_eval doesn't get block and raises an error.

0
David Unric On

Enclose expression supplied to puts in parenthesis because lower precedence of do..end block.

puts( KlassWithSecret.new.instance_eval do
  @secret
end )

or use brace syntax of block

puts KlassWithSecret.new.instance_eval {
  @secret
}
0
vidang On

This is because when you use do..end block, the block is passed to the puts function. The code with do..end block will work if you write it like this

puts(KlassWithSecret.new.instance_eval do
  @secret
end)
3
chuang wang On

Ruby(2.0.0) works. Code:

KlassWithSecret.new.instance_eval do
  p @secret
end
# 99

no problem.

0
chuang wang On
a = Proc.new {@secret}
puts KlassWithSecret.new.instance_eval(&a)
# 99

It say that puts KlaccWithSecret do @secret end does not gain the Proc(block).