问题
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.
回答1:
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.
回答2:
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
}
回答3:
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)
回答4:
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).
回答5:
Ruby(2.0.0) works. Code:
KlassWithSecret.new.instance_eval do
p @secret
end
# 99
no problem.
来源:https://stackoverflow.com/questions/21042867/instance-eval-does-not-work-with-do-end-block-only-with-blocks