基礎

Rubyの||=演算子入門|nilガードと条件付き代入の使い方

||=(ダブルパイプイコール)は、変数がnilまたはfalseの場合にのみ値を代入する演算子です。「nilガード」とも呼ばれ、デフォルト値の設定やメモ化(キャッシュ)パターンでよく使われます。Rubyのイディオムとして非常に頻出するため、必ず覚えておきたい演算子です。

基本的な使い方

a ||= ba = a || bとほぼ同じ意味で、aが偽(nilまたはfalse)の場合のみbを代入します。

Ruby
# 変数がnilの場合
name = nil
name ||= '名無し'
puts name  # nilだったのでデフォルト値が代入される

# 変数に値がある場合
name = '太郎'
name ||= '名無し'
puts name  # すでに値があるので変更されない
実行結果
名無し
太郎

namenilのときは'名無し'が代入され、すでに'太郎'が入っているときはそのまま変更されません。これが「nilガード」と呼ばれる理由です。

if文で書いた場合との比較

Ruby
config = nil

# if文で書く場合(冗長)
if config.nil?
  config = 'default'
end
puts config

# ||= で書く場合(簡潔)
setting = nil
setting ||= 'default'
puts setting
実行結果
default
default

メモ化(キャッシュ)パターン

||=の最も一般的な使い方は、計算結果のキャッシュ(メモ化)です。

Ruby
class UserProfile
  def initialize(user_id)
    @user_id = user_id
    @data = nil
  end

  def data
    @data ||= fetch_from_database  # 初回のみDBアクセス
  end

  private

  def fetch_from_database
    puts "[DB] ユーザー#{@user_id}のデータを取得中..."
    {name: '太郎', age: 25, email: 'taro@example.com'}
  end
end

profile = UserProfile.new(1)
puts profile.data  # 初回: DBにアクセス
puts profile.data  # 2回目: キャッシュを使用
puts profile.data  # 3回目: キャッシュを使用
実行結果
[DB] ユーザー1のデータを取得中...
{name: "太郎", age: 25, email: "taro@example.com"}
{name: "太郎", age: 25, email: "taro@example.com"}
{name: "太郎", age: 25, email: "taro@example.com"}

@data ||= fetch_from_databaseにより、初回アクセス時にのみfetch_from_databaseが呼ばれます。2回目以降は@dataにすでに値があるため、DBアクセスはスキップされます。

ハッシュでのデフォルト値設定

Ruby
# オプションにデフォルト値を設定
def configure(options = {})
  options[:host] ||= 'localhost'
  options[:port] ||= 3000
  options[:debug] ||= false

  puts "Host: #{options[:host]}"
  puts "Port: #{options[:port]}"
  puts "Debug: #{options[:debug]}"
end

puts '--- デフォルト設定 ---'
configure({})

puts '--- カスタム設定 ---'
configure({host: '192.168.1.1', port: 8080})
実行結果
--- デフォルト設定 ---
Host: localhost
Port: 3000
Debug: false
--- カスタム設定 ---
Host: 192.168.1.1
Port: 8080
Debug: false

実践的な使い方

Ruby
# カウンターの初期化に使う
def count_words(text)
  counter = {}

  text.split.each do |word|
    word = word.downcase
    counter[word] ||= 0  # 初回はnilなので0を代入
    counter[word] += 1
  end

  counter.sort_by { |_, v| -v }.each do |word, count|
    puts "#{word}: #{count}回"
  end
end

count_words('Ruby is fun Ruby is great Ruby')
実行結果
ruby: 3回
is: 2回
fun: 1回
great: 1回
||= の動作原理

a ||= bは正確には「aが偽(nilまたはfalse)のときbを代入する」です。a0や空文字列''の場合は偽ではないため、代入は行われません。aが未定義の場合はnil扱いとなり代入されます。

falseの値には注意

||=falseも偽として扱うため、変数にfalseを意図的に設定したい場合は正しく動作しません。例えばflag ||= trueとすると、flagfalseのときもtrueに上書きされてしまいます。この場合はflag = true if flag.nil?を使いましょう。

まとめ

  • ||=は変数がnil/falseの場合にのみ値を代入する
  • デフォルト値の設定やnilガードとして頻繁に使われる
  • メモ化パターンで計算結果のキャッシュに最適
  • falseを意図的に扱う場合はnil?チェックを使う
  • Rubyの重要なイディオムとして必ず覚えておくべき演算子