LoginSignup
26
12

More than 5 years have passed since last update.

Ruby ブロック

Last updated at Posted at 2017-07-16

ブロックについて

オブジェクト.メソッド名 do |ブロック変数|
  ブロック定義本体
end

do〜endの代わりに {〜} でもOK

オブジェクト.メソッド名{|ブロック変数|
  ブロック定義本体
}

ブロックを受け取るメソッドの作成

yieldを使ってみる

ブロック定義本体を実行するには「yield」を利用する。

def block_test
  5.times {yield()}
end

block_test{
  puts "ブロック本体"
}
実行結果
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロック本体

ブロックを宣言しない場合はエラーとなる。

ブロック宣言しない
def block_test
  5.times {yield()}
end

block_test
実行結果
block_test.rb:2:in `block in block_test': no block given (yield) (LocalJumpError)

ブロックの有無は「block_given?」で判定が行える。

ブロックの有無
def block_test
  if block_given?
    5.times {yield()}
  else
    puts "ブロックは宣言されていません"
  end
end

block_test
block_test{
  puts "ブロック本体"
}
実行結果
ブロックは宣言されていません
ブロック本体
ブロック本体
ブロック本体
ブロック本体
ブロック本体

ブロック変数を使ってみる

yieldに値を渡すことでブロック変数を使用できる。

ブロック変数を使う
def block_test
  if block_given?
    5.times {|i| yield(i)}
  else
    puts "ブロックは宣言されていません"
  end
end

block_test
block_test{|j|
  puts "ブロック本体#{j}"
}
実行結果
ブロックは宣言されていません
ブロック本体0
ブロック本体1
ブロック本体2
ブロック本体3
ブロック本体4

メソッドに引数を定義する

メソッドに引数を定義できる

メソッドに引数を定義
def block_test(t)
  if block_given?
    t.times {|i| yield(i)}
  else
    puts "ブロックは宣言されていません#{t}"
  end
end

block_test(9)
block_test(3){|j|
  puts "ブロック本体#{j}"
}
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2

ブロックをProcとして受け取る

ブロックをProcとして受け取る
def block_test(t, &block)
  if block
    t.times {|i| block.call(i)}
  else
    puts "ブロックは宣言されていません#{t}"
  end
end

block_test(9)
block_test(3) do |j|
  puts "ブロック本体#{j}"
end
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2

Procを渡す

Proc.newでProcを生成してcallメソッドで実行する。

Procを渡す
def block_test(t, f=nil)
  if f
    t.times {|i| f.call(i)}
  else
    puts "Procは渡されていません#{t}"
  end
end

procTest = Proc.new{|j|
  puts "Proc本体#{j}"
}
block_test(9)
block_test(3, procTest)
実行結果
Procは渡されていません9
Proc本体0
Proc本体1
Proc本体2

Procオブジェクトを「&変数名」でブロックとして渡す

指摘を受けての追記

Procオブジェクトをブロックとして渡す
def block_test(t)
  if block_given?
    t.times { |i| yield(i) }
  else
    puts "ブロックは宣言されていません#{t}"
  end
end

procTest = Proc.new{|j|
  puts "ブロック本体#{j}"
}
block_test(9)
block_test(3, &procTest)
実行結果
ブロックは宣言されていません9
ブロック本体0
ブロック本体1
ブロック本体2

&をつけて渡すとブロックとして認識してくれるので呼び出されるメソッド側はそのままでも大丈夫なんですね。
最初のは色々と余計なことをしているようでこちらのがスッキリしてますね。

26
12
2

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
26
12