此代码:
private def not_ok
collection.each do |x|
puts x
end
end
导致语法错误:
syntax error, unexpected keyword_do_block, expecting keyword_end
更新:这是使用MRI Ruby 2.1.0 。显然,此行为是特定于版本的,并已在更高版本中修复,包括2.1.1(!)。 (感谢@Amadan和@JörgWMittag指出这一点。)
为什么会引发语法错误,如何在不将do
块更改为{}
块的情况下不提出语法错误?
为了进行比较,这些变体不会导致语法错误:
def ok
collection.each do |x|
puts x
end
end
private def ok
collection.each { |x|
puts x
}
end
private def ok
each do |x|
puts x
end
end
由于我知道def
表达式会返回一个可以传递给其他方法的符号,因此我开始使用private
单独注释我的更多方法,而不是单独使用public
和{ {1}}类中的部分(我发现它不易维护),并且多次遇到此问题 - 只要该方法包含private
块。
答案 0 :(得分:3)
似乎在旧版本的Ruby上,do
/ end
块存在优先问题。
您可以通过将def
表达式的返回值赋给变量,然后将该变量传递给Module#private
的调用来解决这个问题:
var = def not_ok
collection.each do |x|
puts x
end
end
private var
但请注意,在旧版本的Ruby中,方法定义表达式的返回值是实现定义的,因此您不知道上面的代码将执行什么操作。 MRI,YARV,MacRuby,MagLev,JRuby和IronRuby将返回nil
作为def
表达式的结果,raise
表示TypeError
Module#private
,Symbol
只需要String
或CompiledMethod
s。 Rubinius将返回一个raise
对象,表示该方法的已编译代码,但同样,TypeError
来自Module#private
的{{1}}。
只有在最新版本的Ruby上,def
表达式才会计算为Symbol
,但是,在这些最新版本的Ruby上,优先级问题也已修复,因此您的代码将只是工作
它适用于YARV 2.2.0和JRuby-9.0.0.0-dev,但不适用于JRuby 1.7.18和Rubinius 2.2.0(最后一个可能是一个bug,因为它声称兼容Ruby 2.1.0)。