📌

Hash#to_proc について

2024/10/18に公開

#to_proc メソッドは & でブロック引数を渡したときに Ruby の内部で呼び出されるメソッドです。

class X
  def to_proc
    -> (value) { "hello, #{value}" }
  end
end

x = X.new

# x.to_proc の結果をブロック引数として渡す(受け取る)
pp "homu".then(&x)

#to_proc で一番有名なのは Symbol#to_proc になりますかね。
.map(&:upcase) も内部で :upcase.to_proc がブロック引数として渡されるようになっています。

# Symbol#to_proc は引数をレシーバとして symbol の名前のメソッドを呼びだす
# 下記だと "mami".upcase が内部で呼び出される
pp :upcase.to_proc.call "mami"
# => "MAMI"

# :upcase.to_proc がブロック引数として渡される
pp "homu".then(&:upcase)
# => "HOMU"

普段何気なく使っている & も内部ではこんな動きをしています。

Hash#to_proc

Symbol#to_proc は有名なんですが他に #to_proc が定義されているクラスで Hash#to_proc があります。
これは Hash#[] と同じような挙動の Proc オブジェクトを返します。

homu = { id: 1, name: "homu", age: 14 }

# Hash#[] はキーを引数に受け取り、その値を返す
pp homu[:name]   # => "homu"
# 対応するキーがなければ nil を返す
pp homu[:hoge]   # => nil

# Hash#to_proc では Hash#[] と同じ挙動をする Proc を返す
pp homu.to_proc.call(:name)   # => "homu"
pp homu.to_proc.call(:hoge)   # => nil

わたしは未だに利用したことはないんですがどういうときに便利なんですかね〜。

homu = { id: 1, name: "homu", age: 14 }

# 配列の要素から Hash の値を抽出する
pp [:id, :name, :age].map(&homu)
# => [1, "homu", 14]

ちなみに Proc#callProc#[] でも呼び出せるので以下のように書くこともできます。

homu = { id: 1, name: "homu", age: 14 }

# より Hash っぽく添字アクセスでーの値を参照できる
pp homu.to_proc[:name]   # => "homu"
pp homu.to_proc[:hoge]   # => nil
GitHubで編集を提案

Discussion