Help us understand the problem. What is going on with this article?

AdventCalendar Day11 [超Ruby入門]

More than 1 year has passed since last update.

はじめに

本記事は、超Ruby入門11日目の記事です。

コメント頂ける方は、ガイドラインを読んで頂けると幸いです。

本題

%w[Ruby, Python, PHP].map {|x| x.length }

上記のコードがどのように動くかはもう知っているね。

では、下記コードを実行してみよう。

%w[Ruby, Python, PHP].map(&:length)

何と二つのコードは同じ結果をもたらす。

秘密を知るために、シンボルとProcを学んでいこう。

シンボル

シンボルとは、ある文字列に対して一つだけ割り当てられる整数だ。

下記コードを実行してシンボルが一意なオブジェクトIDを持つことを確かめてみよう。

symbol = "symbol"
copy_symbol = "symbol"

# 各変数のオブジェクトid
symbol.object_id
copy_symbol.object_id

# シンボル化
symbol.intern
copy_symbol.intern

symbol.intern.object_id
copy_symbol.intern.object_id
%w[Ruby, Python, PHP].map(&:length)

上記のコードでは:lengthがシンボルだ。

疑い深い人は確かめてみよう

Symbol.all_symbols
Symbol.all_symbols.grep(/\Alength\z/)

Proc

Procとは、ブロックを関連データと共に持ち運べるようにするクラスだ。Procは常にブロックと共にある。

Proc_squeeze = { | x | x.squeeze } # エラー
Proc_squeeze = Proc.new { | x | x.squeeze }
Proc_squeeze.class
Proc_squeeze.call("PPPHHHPPP")

Procオブジェクトを使うことで、ブロックを変数として定義できる。

Proc.callメソッドを呼び出すことで、Procオブジェクトを実行できるのだ。

本題

さて、ブロックの説明でイテレータには複数の文法があることを覚えているだろうか?

method(arg1, arg2, ..., `&' proc_object)

例えば、下記のような使い方ができる。

%w[Ruby, Python, PHP].map(& Proc.new { | x | x.length } )

もう少しで、map(&:length)の謎が解けそうだ。

"&"でオブジェクトを渡すと暗黙的にto_procメソッドを呼び出す。to_procメソッドはProcオブジェクトを返すメソッドだ。

to_proc メソッドを持つオブジェクトならば、`&' 修飾した引数として渡すことができます。デフォルトで Proc、Method オブジェ クトは共に to_proc メソッドを持ちます。to_proc はメソッド呼び出し時に実 行され、Proc オブジェクトを返すことが期待されます。

シンボルには、to_procメソッドを持つ。

もうわかっただろう。

① %w[Ruby, Python, PHP].map(&:length)
② %w[Ruby, Python, PHP].map(& Proc.new { | x | x.length } )

①では、&:lengthからto_procメソッドが呼び出され、Procオブジェクトを返すことで②のような形で実行されるのだ。

利用例

さて、Procオブジェクトを紹介したが実際にはいつ利用するのだろうか?

require "rspec"

class Person
end

describe Person do
    it "should be a instance" do
      expect{ Person.new }.to be_a(Person)
    end

    it "should be a instance" do
      expect( Person.new ).to be_a(Person)
    end
end

MUGENUP技術ブログさん

Procは、Railsのテストなどで利用される。

上記のテストでは、{ }がProcクラスであるため最初のテストをパスすることができない。

*Procの使い所をコメントしてくださるとありがたいです

参照

徳丸浩の日記

imaharu
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away