🐡

Ruby の Hash#default について

2024/04/11に公開

Ruby の Hash ではキーの要素が存在しなかった場合には nil を返すようになっています。

hash = {}

pp hash[:key]   # => nil

このデフォルト値は Hash#default の値に依存しており、この値を意図的に書き換える事もできます。

hash = {}

# デフォルトでは nil に割り当てられている
pp hash.default  # => nil
pp hash[:key]    # => nil

# Hash#default= でデフォルト値を書き換えることもできる
# デフォルト値を 0 にする場合
hash.default = 0
pp hash[:key]    # => 0

注意点

Hash#default なんですがこれは『要素がみつからなかったときには同じオブジェクト』を返します。

hash = {}

default = "homu"
hash.default = default

# 全部同じオブジェクトを参照する
pp default.__id__   # => 60
pp hash[0].__id__   # => 60
pp hash[1].__id__   # => 60

なので、どれか1つでも破壊的な変更を行うと全ての結果に影響を与えます。

hash = {}

default = "homu"
hash.default = default

hash[0].upcase!

# 全ての値が変わる
pp default   # => "HOMU"
pp hash[0]   # => "HOMU"
pp hash[1]   # => "HOMU"

もし、上記のような副作用を防ぎたい場合は Hash.new にブロック引数を渡して都度初期化する必要があります。

# キーの要素がみつからなかったときにブロックが呼び出される
hash = Hash.new { |hash, key| hash[key] = "homu" }

# 別のオブジェクトを参照する
pp hash[0].__id__   # => 60
pp hash[1].__id__   # => 80

# 他の要素に影響を与えない
hash[0].upcase!
pp hash[0]   # => "HOMU"
pp hash[1]   # => "homu"
GitHubで編集を提案

Discussion