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

隐身守侯 提交于 2019-12-01 07:12:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!