instance_eval不能与do/end块一起使用,只能与{}块一起使用。

3

如果我有一个类:

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': 错误的参数数量 (0 for 1..3) (ArgumentError)

为什么不能在instance_eval中使用do/end块?

附注:我正在使用Ruby 2.1.0。


1
这里可以运行(ruby 2.0.0),你使用的 ruby 版本是什么? - levinalex
对我来说没问题(2.1.0)。你确定你粘贴的代码会导致错误吗? - Marek Lipka
无法在1.9.3版本中重现。如果你使用的是一些较旧或不同的Ruby实现,可能与do..end块的优先级低于{..}块有关。 - David Unric
抱歉,我本意是要与 puts 一起使用的,我的错。已编辑问题。 - Alexander Popov
5个回答

5

将提供给puts的表达式括在括号中,因为do..end块具有较低的优先级。

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

或者使用块的花括号语法
puts KlassWithSecret.new.instance_eval {
  @secret
}

4

这是因为当你使用花括号传递块时,它会被传递到instance_eval方法中。但如果你使用do-end来传递块,它会被传递到puts方法中,因此instance_eval无法获取块并抛出错误。


3
这是因为当你使用do..end块时,该块被传递给puts函数。如果您像这样编写带有do..end块的代码,则它将起作用。
puts(KlassWithSecret.new.instance_eval do
  @secret
end)

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

它说puts KlaccWithSecret do @secret end没有获得Proc(块)。


-1

Ruby(2.0.0)可以运行。 代码:

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

没问题。


1
它能够工作是因为你没有调用 puts - toro2k
我深思熟虑后发布了一个新的答案,希望能对你有所帮助。 - chuang wang
@toro2k 我认为这是一个代码高尔夫比赛... :) - Arup Rakshit

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接