LoginSignup
52
43

More than 5 years have passed since last update.

Ruby Procについて学ぶ

Last updated at Posted at 2015-08-21

Ruby力の基礎固めとして、Procについて学んだことをまとめます。

Procクラスとは

ブロックとして記述された手続きを運ぶためのクラス | たのしいRuby P415

作り方と実行の仕方

# 1
hello_1 = Proc.new do |name|
  puts "Hello, #{name}" # 最後に評価される式の値が戻り値
end

# 2
hello_2 = proc do |name|
  puts "Hello, #{name}" # 最後に評価される式の値が戻り値
end

hello_1.call("bob")
hello_2.call("cathy")

メソッド定義でできることならだいたいできる
- |*配列|での不定引数の受け取り
- デフォルト引数
- キーワード引数
など

lambda

Proc.newやprocで作成したProcオブジェクトよりメソッドの動きに近い動きをする

主な違いは2つある。

1 引数の数のチェック

proc = lambda do |a, b, c|
  p [a, b, c]
end
proc.call(1, 2)
=> ArgumentError: wrong number of arguments (2 for 3)

2 returnの抜ける範囲

def foo
  f = Proc.new { return :foo }
  f.call
  return
end

def foo2
  f = proc { return :foo2 }
  f.call
  return
end

def bar
  f = lambda { return :bar }
  f.call
  return
end

def h
  yield
end

def hoge
  h{ return :hoge }
  nil
end

p foo()
#=> :foo
p foo2()
#=> :foo2
p bar()
#=> nil
p hoge()
#=> :hoge

            return                     next                     break
Proc.new    メソッドを抜ける            手続きオブジェクトを抜ける  例外が発生する
proc        メソッドを抜ける            手続きオブジェクトを抜ける  例外が発生する
lambda      手続きオブジェクトを抜ける   手続きオブジェクトを抜ける  手続きオブジェクトを抜ける
イテレータ   メソッドを抜ける            手続きオブジェクトを抜ける  メソッドを抜ける

to_proc

メソッドにブロックを指定する際に「&オブジェクト」の形式で渡すと
オブジェクト.to_procが自動的に呼ばれる
シンボル.to_procはシンボルと同名のメソッドを呼ぶprocオブジェクトを作成する

["42", "39", "56"].map{ |i| i.to_i }

["42", "39", "56"].map(&:to_i)

Procクラスの特徴

クロージャ

手続きと同時に変数などの環境を保持する手続きオブジェクトのこと

def counter
  c = 0
  Proc.new do
    c += 1
  end
end

c1 = counter
p c1.call => 1
p c1.call => 2
p c1.call => 3

c2 = counter
p c2.call => 1
p c2.call => 2

p c1.call => 4

Procクラスのインスタンスメソッド

Procオブジェクトを実行する

prc = Proc.new{|a, b| a + b}
prc.call(1, 2)
prc[3, 4]
prc.yield(1, 2)
prc.(3, 4)
prc === [9, 10]

procオブジェクトでfizzbuzz


fizz = proc{|n| n % 3 == 0 }
buzz = proc{|n| n % 5 == 0 }
fizzbuzz = proc{|n| n % 3 == 0 && n % 5 == 0}
(1..100).each do |i|
  case i
  when fizzbuzz then puts "Fizz Buzz #{i}"
  when fizz then puts "Fizz #{i}"
  when buzz then puts "Buzz #{i}"
  else puts i
  end
end

そのほか

prc.arity # ブロック変数の数
prc.parameters # ブロック変数の詳細
prc.lambda? # lambdaで定義されたかどうか
prc.source_location # procが定義されたソースコードの位置 (ソースファイルと行番号)

参考

52
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
43