Ruby中带赋值与后置条件的return行为差异及求值顺序解析
Ruby方法f、g、h的求值顺序与结果差异解析
三个方法的定义与执行结果
方法f
def f(a) return a = 2 if !a.nil? return 'oh' end f(42) # 2 f(nil) # 'oh'
方法g
def g(b) return a = b if !a.nil? return 'oh' end g(42) # 'oh' g(nil) # 'oh'
方法h
def h(b) a = b return a if !a.nil? return 'oh' end h(42) # 42 h(nil) # 'oh'
为什么g(42)返回'oh'?
Ruby有个规则:局部变量在首次赋值前,出现在条件判断表达式中会被视为nil。方法g里的条件!a.nil?中,a是未定义的局部变量,此时Ruby会把它当作nil处理,!nil.nil?等价于!true,结果为false。条件不成立,就不会执行return a = b分支,直接执行后续的return 'oh',所以无论传入42还是nil,g方法都会返回'oh'。
f与g、g与h的求值顺序差异
f与g的差异
- 方法f的条件判断
!a.nil?里的a是方法参数,属于已定义变量,判断的是传入参数是否非nil。调用f(42)时,a的值是42,!a.nil?为true,因此执行return a = 2,将a赋值为2后返回。 - 方法g的条件判断
!a.nil?里的a是未定义的局部变量,Ruby在条件判断时将其视为nil,导致条件为false,直接跳过赋值分支返回'oh'。这里的a = b只有在条件为真时才会执行,但因为条件不成立,a从未被定义和赋值。
g与h的差异
- 方法g中,
a = b的赋值操作放在条件分支的return语句里,条件判断时a还未被定义,判断逻辑失效,赋值语句根本不会执行。 - 方法h中,先执行
a = b提前完成了a的定义与赋值,之后的!a.nil?判断的是已经有值的a,因此能正确根据传入参数返回结果:传入42时a非nil,返回42;传入nil时返回'oh'。
内容的提问来源于stack exchange,提问作者ybakos
相关产品推荐
相关产品推荐

