「items.map(&:name)」が動く仕組み――&: 記法の裏にある巧妙なハック
Ruby で配列を処理していると、何度もお世話になる短縮記法があります。それが「&: トリック」、通称「アンパサンド・コロン(pretzel colon)」と呼ばれる書き方です。
words = ["would", "you", "like", "to", "play", "a", "game?"]
# この書き方が...
words.map &:length
# ...実質的にはこれと同じ意味になります:
words.map { |w| w.length }
筆者は長い間、この &: 構文を「演算子の一種」だと思い込んでいました。ところが実際にはそうではありません。これはもともと ActiveSupport で生まれた賢いハックであり、その後 Ruby 1.8.7 で正式な言語機能として採用されたものです。
& 演算子のもうひとつの役割
論理 AND 演算でおなじみの「&」ですが、Ruby ではもうひとつ重要な役割を担っています。メソッド呼び出しの引数の先頭に & を付けると、そのオペランドに対して to_proc が呼び出され、返り値の Proc オブジェクトがブロックとして渡されます。言葉だけだと分かりにくいので、具体例を見てみましょう。
def my_method(&block)
block.call
end
class Greeter
def self.to_proc
Proc.new { "hello" }
end
end
my_method(&Greeter) # => "hello"
Symbol#to_proc の正体
to_proc メソッドは任意のオブジェクトに定義でき、もちろん Symbol クラスにも定義できます。&: ショートカットが成立するのは、まさにこの仕組みのおかげです。イメージとしては、次のような実装になっています。
class Symbol
def to_proc
Proc.new do |item|
item.send self
end
end
end
ポイントは item.send(self) の部分です。ここでの self は、レシーバとなっているシンボル自身を指しています。
全体を組み合わせると
each や map といった Enumerable 系のメソッドはブロックを受け取ります。各要素に対してブロックが呼び出され、そこへ要素への参照が渡されます。このとき渡されているブロックの中身こそが、シンボルに対して to_proc を呼び出した結果の Proc なのです。
# &:name は Proc に変換され、item.send(:name) を実行する
items.map(&:name)
面白いのは、map 側はこうした内部の動きを一切意識していないという点です。実際に仕事の大半を担っているのは :name というシンボルの方です。確かに賢い仕組みですが、筆者の好みとしては少し「賢すぎる」感もあります。とはいえ、長年にわたり Ruby の標準ライブラリの一部として使われてきた歴史があり、あまりに便利なので、当分の間は使い続けることになりそうです :)
補足として、Ruby 1.9 以降では Symbol#to_proc はインタプリタの C レベルで最適化されており、明示的に書いたブロックと同等以上のパフォーマンスを発揮します。簡潔さと速度の両面で、今や積極的に使ってよいイディオムといえるでしょう。
-
Rubyのmapメソッド完全ガイド!配列・ハッシュのデータ変換を実例で解説
Rubyのmapメソッドは、配列(Array)・ハッシュ(Hash)・範囲(Range)といったコレクションに対して使用できる強力なメソッドです。 mapの主な用途は、データの変換です。 例えば、文字列の配列があった場合、すべての文字列を順番に処理して、各文字を大文字に変換することができます。 また、Userオブジェクトのリストがある場合も同様です。 それらを変換して、対応するメールアドレスや電話番号など、Userクラスに定義された任意の属性のリストを作成できます。 それでは、具体的な使い方を見ていきましょう! Ruby mapメソッドの基本構文 mapの構文は次のようになっています。 a
-
冷蔵庫がハッカーの武器に?史上最も衝撃的な「ゾンビ冷蔵庫」サイバー攻撃事件
スマートホームが狙われる時代へテクノロジーの進化によって、私たちの住まいはますます「スマート」になっています。しかし、その裏で、悪意あるハッカーたちが家に侵入するための新たな「入り口」が生まれていることをご存じでしょうか。パソコンや金庫だけの時代は終わり、サイバー犯罪はすでに身近な存在となりつつあります。今やスマート冷蔵庫やテレビ、洗濯機までもが攻撃の標的になり得るのです。IoT(モノのインターネット)は、日常的に使うあらゆる機器を一元的に管理できる便利な仕組みである一方、サイバー犯罪者にとっては格好の攻撃手段となり得るという二面性を抱えています。今回は、デジタル時代の歴史の中でも特に興味深い