Instance_eval不适用于do / end块,仅适用于{} -blocks

如果我有课:

class KlassWithSecret def initialize @secret = 99 end end 

并运行:

 puts KlassWithSecret.new.instance_eval { @secret } 

它打印99,但如果我运行:

 puts KlassWithSecret.new.instance_eval do @secret end 

它返回一个错误: `instance_eval': wrong number of arguments (0 for 1..3) (ArgumentError)

为什么我不能使用带有instance_eval do / end块?

PS我使用的是Ruby 2.1.0。

这是因为当您使用花括号传递块时,它会传递给instance_eval方法。 但是如果你用do-end传递它,它会被传递给puts方法,所以instance_eval不会被阻塞并引发错误。

将括号中的表达式括在括号中,因为do..end块的优先级较低。

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

或使用块的大括号语法

 puts KlassWithSecret.new.instance_eval { @secret } 

这是因为当你使用do..end块时,块被传递给puts函数。 如果您这样编写,带有do..end块的代码将起作用

 puts(KlassWithSecret.new.instance_eval do @secret end) 
 a = Proc.new {@secret} puts KlassWithSecret.new.instance_eval(&a) # 99 

它说, puts KlaccWithSecret do @secret end不会获得Proc (阻止)。

Ruby(2.0.0)有效。 码:

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

没问题。