我正在从PERL转换到Ruby。我喜欢PERL的一点是,通过使用我的命令,可以在子程序中拥有局部作用域。也就是说,这段代码不起作用,因为$only_in_the_if超出了作用域。
...
if (cond) {
my ($only_in_the_if) = bar($foo );
}
bar1($only_in_the_if) ; #can't work, $only_in_the_if scope is finished
...
在Ruby中,only_in_the_if将出现在方法作用域中。什么好主意吗?
简单作用域显然不属于条件作用域。
irb(main):001:0> if my_cond
irb(main):002:1> my_var = 'blah'
irb(main):003:1> puts my_var
irb(main):004:1> end
blah
=> nil
irb(main):005:0> puts my_var
blah
=> nil
,但你可以使用一个块来强制作用域…尽管这有点奇怪。
irb(main):006:0> 1.times { new_var = 'blah'; puts new_var } if my_cond
blah
=> 1
irb(main):007:0> new_var
NameError: undefined local variable or method `new_var' for main:Object
from (irb):7
from :0
如果你愿意,你可以把它元程序到一个叫做"my"的方法中;)
Ruby的代码块与Perl的代码块不同,而且毫无疑问,没有简单的方法可以声明性地将变量范围限定为仅在诸如if这样的复合语句中使用词法。
你可以像Taryn建议的那样使用代码块。我不确定收益是否会超过成本(在执行速度和与其他Ruby开发人员工作方式的差异方面)。
另一个简单的解决方案是保持复合语句的轻量级,并依靠较短的方法来实现严格的变量作用域。在Perl中,您可能会编写一个30行方法,在if和for中包含4或5行的小子块,而在Ruby中,相同的流程和作用域可以通过一个控制方法完成,该方法具有主流程和几个私有方法,其中变量具有作用域。这些方法之间共享的数据可以是对象状态(在@ variables中)或控制方法中的作用域变量,这些变量作为参数传递给私有方法。
def main_method foo
if (cond)
bar foo
end
end
private
def bar param
only_in_bar = Math.whatever(param)
# Do some stuff with only_in_bar
end