nilガードについて

こんにちは!odaです!

Rubyを使っていると、よく次のようなコードを見かけます。

foo ||= 10

これは「nilガード」と呼ばれるイディオムで、私自身は「foonilが入って欲しくないときは、こう書くと初期値が設定できるんだなー」ぐらいの認識で使っていました。

||演算子について調べているときに、この書き方がすごく腹落ちしたので、今日はそれをテーマにします。

||演算子

||演算子は論理和を表す演算子です。

私は次のように条件式の中に使うことが多いです。

foo = false
bar = true

if foo || bar
  # fooかbarがtrueの時の処理
else
  # fooもbarもfalseの時の処理
end

上記の例だと、foo || bartrueと判定されます。

直感的に理解はできますが、||演算子の返り値を意識することでなぜこのように判定されるのかがよくわかります。

||演算子は、まず左辺(今回はfoo)を評価し、真であればその値を返します。

左辺の評価結果が偽であれば、右辺(今回はbar)を評価し、その値を返します。

そのため、foo || barbarの評価結果であるtrueが返り値となります。

nilガード

||=+=などと同じ自己代入の演算子です。

以下の2つの式は、同じ内容を表しています。

foo ||= 10
foo = foo || 10

先ほどの||演算子の返り値を意識して2つ目の式をみると、fooが偽であれば、foo10が代入されるということがよくわかります。

Rubyにおいて偽とはfalsenilのため、foonilが入ることを防ぐことができます。(=nilガード)

以下のコードで、上記の内容を確認してみます。

a, b, c = 1, nil, false

a ||= 10 # => 1
b ||= 10 # => 10
c ||= 10 # => 10

nilだけでなく、偽と判定されるfalseもしっかりガードされています。

falseをガードしたい場面があるかはさておき、「nilガード」という言葉からnilだけを防いでいると思っていたので、新たな発見となりました。

さいごに

今回のように、調べていた内容が元々持っていた知識に繋がると理解の深まりを感じることができました。

何より、この繋がる瞬間の感覚は、とても気持ちいい!