プログラミング備忘録

プログラミングの学習状況をメモしています

52日目

今日の学習

Ruby

Ruby本の第10章を学習。昨日はyieldまでを学んだ。

Proc

Procクラスは、ブロックをオブジェクト化するためのクラス。なので、Procクラスのインスタンスといえば、ブロック(何らかの処理の塊)を指す。

Procクラスのインスタンス(オブジェクト)を生成するには、Proc.newを用いる。

hello_proc = Proc.new do
  'hello'
end

# do...endではなく下の書き方でもOK
hello_proc = Proc.new { 'hello' }

生成したProcオブジェクトは実行されてはじめて効力を持つ。callメソッドを使用して呼び出す。

# 先ほど作ったProcオブジェクト
hello_proc.call
#=> hello

実行時に引数を利用するProcオブジェクトを定義することもできる。

add_proc = Proc.new do |a, b|
  a + b
end

# もしくは
add_proc = Proc.new { |a, b| a + b }

add_proc.call(10, 20)
#=> 30

# 初期値をつけておくことも可能
add_proc = Proc.new { a = 10, b = 20| a + b }

また、Proc.newを用いずとも、procメソッドを利用することでも生成できる。

# Proc.newを利用しない
add_proc = proc { |a, b| a + b }
Procオブジェクトをブロックの代わりに渡す

Procオブジェクトとブロックの異なる点は、Procオブジェクトにした場合はオブジェクトとして扱うことができる点。

これで、変数に入れて別のメソッドに渡したり、Procオブジェクトに対してメソッドを呼び出すことができる。

前回、ブロックを引数として受け取る学習をしたが、ここで使ったarityメソッドは、実はProcクラスのインスタンスメソッドらしい。

つまり、arityメソッドを呼び出すときにブロックがProcオブジェクトに変化しているということらしい。

このとき利用していたブロックの部分を代わりにProcに置き換えるというテクニックをRuby本では紹介してある。

あらかじめ作成したProcオブジェクトを渡す場合にも、手前に&をつける必要がある(&がないと普通の引数が渡されたとみなされる)。

例 greeting(&hello_proc)

また、Ruby本ではProcオブジェクトを普通の引数として渡す方法についても説明してある。

引数として渡す場合は、逆に&をつけないようにする。

メソッドが受け取れるブロックは最大で1つだが、Procオブジェクトの場合は、ただのオブジェクト扱いになるため、引数として渡すぶんには最大数に制限がない。

(あまりにも全部そのまま引用してしまうことを避けるためこのような記述で済ませることにする)

Proc.newとラムダ

上ではすでに2つのProcオブジェクトの作成方法を学習した。

  • Proc.newを用いる
  • procメソッドを用いる

このほかにもまだ二種類あり、どの方法を使っても作成されるものはProcクラスのオブジェクトになるが、以下の方法で作成したものは挙動が異なるらしい。

  • lambdaメソッドを用いる
lambda { |a, b| a + b }
  • ->構文を用いる(アロー演算子と呼ばれる)
    ->ラムダを作成するためのラムダリテラル
->(a, b) { a + b }

# かっこは省略可能
-> a, b { a + b }
# do...endも使用可能
->(a, b) do
  a + b
end
# 引数がなければ全て省略可能
-> { 'hello' }

上二つの場合、引数のあるメソッドを呼び出す際に、引数の過不足があってもエラーが起こったりしない

しかし、下二つのラムダで作成しているProcオブジェクトは、引数の数に対して厳密なチェックが行われる。よって、引数の過不足があればエラーが発生するようになっている

Procオブジェクトがラムダかどうかを調べたい場合は、lambda?メソッドを利用する。ラムダであればtrueになる。