Ruby if, unless 块中定义的变量块外还可以使用?

lalameat · 2014年04月08日 · 最后由 zhouchongzxc 回复于 2014年04月30日 · 3524 次阅读

刚刚发现。

比如之前没有定义变量 obj,然后

if xxxx
     obj = .....
     .....
end

if obj.nil? # or "if obj"
   ............
end

这样正常运行。ruby 版本是 1.9.3,是应该这样么?

这个不应该这样么?

#1 楼 @arthurymp java,c++ 都是块里定义作用域只在块中。

跟 c 不一样的是 if/end 不创建新作用域吧。

嗯,作用域没变

#3 楼 @realwol 这个倒是 ruby 比较独到的地方,我依稀记得 Perl 应该也是块中定义变量作用域就在块里。

#5 楼 @lalameat ruby 也是,你换成 block 就访问不了。只不过 ruby 里 if 不这样而已,相对的,C 等语言里的变量的生命周期会受 if 限制。或许 ruby 将 if 做成更纯粹的比较和条件符号了。

我也遇到过这种情况,貌似是因为对象还没有被回收,又或者说即使遇到了 if,context 也并没有变化,这是我的猜测...

但是这种写法可不能保证每次运行都正常。

ruby 中遇到 class module def 这三个关键字才会切换作用域。作用域切换后,原先的绑定就会被替代为一组新的绑定。

#7 楼 @hz_qiuyuanxin 可以保证每次都正确,因为变量的定义检查在词法解析阶段,也就是说只要在之前有提到,无论是否执行,Ruby 解释器均认为已经定义此变量。

#8 楼 @rockliu block 不是也会么。

我记不清在哪里看到过说这种if的作用域问题以后 Ruby 版本升级可能会有变化,个人觉得最好能避免这种写法。

@realwol block 在 ruby 里面是闭包,就像你说的,在里面定义一个变量,外部是不能访问的。 不过 block 会绑定上下文,当碰到闭包的时候作用域不会重新绑定

var_out_of_block = 1

a_block = Proc.new do 
 puts var_var_out_of_block
end

a_block.call

但是碰到,class, module, def 这三个关键字,变量的作用域会发生重新绑定

var_out_of_class = 1

class AClass
 puts var_out_of_class
end

 #undefined local variable or method `var_out_of_class' for Aclass:Class

#12 楼 @rockliu 可以理解为 block 是单向通道的作用域;而 class module def 是双向关闭的新建作用域吧。

有本书叫 programming ruby 中文,看 第 7 章 第 7 节

还有本书叫 programming ruby 1.9 & 2.0 看 第 9 章 第 7 节

书都不看的吗?那 ruby 的 C 语言源码就更没有人看了吧!(这是为什么呢?)

需要 登录 后方可回复, 如果你还没有账号请 注册新账号