跳到內容

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 和方法調用。