if var¶
如果一個變數是 if
的條件,在 then
分支內,該變數會被視為不具有 Nil
類型
a = some_condition ? nil : 3
# a is Int32 or Nil
if a
# Since the only way to get here is if a is truthy,
# a can't be nil. So here a is Int32.
a.abs
end
當變數在 if
的條件中被賦值時,此規則也適用
if a = some_expression
# here a is not nil
end
如果條件中有 and (&&
),此邏輯也適用
if a && b
# here both a and b are guaranteed not to be Nil
end
在這裡,&&
表達式的右側也保證 a
不為 Nil
。
當然,在 then
分支內重新賦值一個變數,會使該變數具有基於賦值表達式的新類型。
限制¶
以上邏輯僅適用於區域變數。它不適用於實例變數、類別變數或閉包中綁定的變數。這些種類的變數值可能會在條件檢查後,被另一個纖程影響,使其變成 nil
。它也不適用於常數。
if @a
# here `@a` can be nil
end
if @@a
# here `@@a` can be nil
end
a = nil
closure = ->{ a = "foo" }
if a
# here `a` can be nil
end
可以通過將值賦給一個新的區域變數來規避這個問題
if a = @a
# here `a` can't be nil
end
另一個選項是使用標準函式庫中的 Object#try
,它只在值不為 nil
時執行區塊
@a.try do |a|
# here `a` can't be nil
end
方法調用¶
此邏輯也不適用於 proc 和方法調用,包括 getter 和屬性,因為可為 nil 的(或更廣泛地說,聯合類型的)proc 和方法不保證在連續兩次調用時回傳相同的更特定類型。
if method # first call to a method that can return Int32 or Nil
# here we know that the first call did not return Nil
method # second call can still return Int32 or Nil
end
上面描述的針對實例變數的技巧也適用於 proc 和方法調用。