📖

[Feature #20818] Hash#store にブロックを渡せるようにする提案

2024/10/21に公開

[Feature #20818] Allow passing a block to Hash#store (to update current value)

  • Hash#store にブロックを渡せるようにする提案
  • Hash#storeHash#[]= と同等で特定のキーに値を割り当てるメソッドです
hash = {}
hash.store(:name, "homu")
pp hash
# => {:name=>"homu"}
  • Hash#store にブロックを渡した場合は以下のような値をブロックの引数で受け取り、ブロックの戻り値がそのキーに割り当てられます
    • ブロックの引数に現在の値が渡される
    • 現在の値がなければ Hash#default の値が渡される
hash = { name: "homu" }

# :name のキーに対して値を割り当てる
# ブロックの引数は現在の値を受け取る
# ブロックの戻り値が新しい値として割り当てられる
hash.store(:name) { |v|
  v # => "homu"
  "mami"
}
hash[:name]   # => "mami"

# キーがなければ Hash#default の値がブロックで渡される
# 意図的に設定されていなければ `nil` を受け取る
hash.store(:age) { |v|
  v # => nil
  14
}
hash[:age]   # => 14

# #default の値に依存して設定もできる
hash.default = 100
hash.store(:id) { |v|
  v # => 100
  v + 1
}
hash[:id] # => 101
  • モチベーションとしては例えばキーがない場合に次のように Hash#[]=Hash#[] を呼び出すことがあると思うんですが
hash[:name] = hash[:name] || "default name"
  • 今回の Hash#store を使うと以下のようにかけるのでパフォーマンスがよい、みたいなところがモチベーションとしてあるみたいです
# こっちだとメソッド呼び出しが1つだけになる
hash.store(:name) { _1 || "default name" }
  • PR もすでにあり実際にどれぐらいパフォーマンスが向上するのかと安全なのかどうか(ブロック内で他のキーの値を書き換えた場合にどうなるのか)みたいなところがコメントされています
  • 個人的には hash[:name] ||= "default name" の書き味が好きなんですがどれぐらいパフォーマンスを気にする必要がありそうなんですかねー
GitHubで編集を提案

Discussion