tapitapi’s blog

1日1杯タピオカ!エンジニア

【Ruby】ブロックをメソッドに渡す

ブロックをメソッドに渡して実行する方法まとめ(備忘録)

 

【目次】

1.ブロックを渡してyieldで実行

-1.1  引数1つ

-1.2 引数複数

2.ブロックを渡してcallで実行

-2.1  引数1つ

-2.2 引数複数

3.Procをブロックとして渡して実行(yieldでもcallでも可能)

-3.1  引数1つ

-3.2 引数複数

4.Procを普通の引数として渡してcallで実行

-4.1  引数1つ

-4.2 引数複数

5.lambdaをブロックとして渡して実行(yieldでもcallでも可能)

-5.1  引数1つ

-5.2 引数複数

6.lambdaを普通の引数として渡してcallで実行

-6.1  引数1つ

-6.2 引数複数

 

 

それではやっていきますーーー

 

1.ブロックを渡してyieldで実行

-1.1  引数1つ(check_condition メソッドに、条件のブロックを渡す)

def check_condition
if yield Random.rand(50)
puts "OK"
else
puts "NG"
end
end
 
check_condition do |condition|
puts condition
100 >= condition * 5
end

 

結果(2回実行)

12
OK
=> nil

44
NG

=> nil

 

-1.2 引数複数

def check_condition
if yield Random.rand(20),Random.rand(20)
puts "OK"
else
puts "NG"
end
end
 
check_condition do |condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2
end

 

結果(2回実行)

11
10
NG
=> nil

4
11
OK
=> nil

 

2.ブロックを渡してcallで実行

-2.1  引数1つ

def check_condition(&block)
if block.call(Random.rand(50))
puts "OK"
else
puts "NG"
end
end
check_condition do |condition|
puts condition
100 >= condition * 5
end

 

結果(2回実行)

19
OK
=> nil

32
NG
=> nil

 

-2.2 引数複数

def check_condition(&block)
if block.call(Random.rand(20),Random.rand(20))
puts "OK"
else
puts "NG"
end
end
 
check_condition do |condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2
end

 

結果(2回実行)

2
19
OK
=> nil

17
15
NG
=> nil

 

※callの代わりに、下記のようにyieldでも実行可能

def check_condition(&block)
if yield Random.rand(20),Random.rand(20)
puts "OK"
else
puts "NG"
end
end
 
check_condition do |condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2
end

 

3.Procをブロックとして渡して実行(yieldでもcallでも可能)

-3.1  引数1つ

def check_condition
if yield Random.rand(50)
puts "OK"
else
puts "NG"
end
end
 
condition = Proc.new{|condition1|
puts condition1
100 >= condition1 * 5}
 
# block として渡すので、&conditionとする
check_condition(&condition)
 

結果(二回実行)

39
NG
=> nil

5
OK
=> nil

 

block として渡すので、下記のようにcallでも実行可能

def check_condition(&block)
if block.call(Random.rand(50))
puts "OK"
else
puts "NG"
end
end
 
condition = Proc.new{|condition1|
puts condition1
100 >= condition1 * 5}
 
# block として渡すので、&conditionとする
check_condition(&condition)

 

-3.2 引数複数

def check_condition
if yield Random.rand(20),Random.rand(20)
puts "OK"
else
puts "NG"
end
end
 
condition = Proc.new{|condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2}
 
check_condition(&condition)

結果(二回実行)

12
11
NG
=> nil

8
9
OK
=> nil

 

block として渡すので、下記のようにcallでも実行可能

def check_condition(&block)
if block.call(Random.rand(20),Random.rand(20))
puts "OK"
else
puts "NG"
end
end

 

condition = Proc.new{|condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2}

 

check_condition(&condition)

 

4.Procを普通の引数として渡してcallで実行

-4.1  引数1つ

def check_condition(proc1)
if proc1.call(Random.rand(30))
puts "OK"
else
puts "NG"
end
end
 
condition = Proc.new{|condition1|
puts condition1
100 >= condition1 * 5}
 
# blockではなく普通の変数として渡すので、&はいらない
check_condition(condition)

 

結果(二回実行)

48
NG
=> nil

3
OK
=> nil

 

※block ではなく、普通の引数として渡すので、yieldを使用してしまうとエラーになる

def check_condition(proc1)
# callではなくyieldを使う
if yield Random.rand(30)
puts "OK"
else
puts "NG"
end
end
 
condition = Proc.new{|condition1|
puts condition1
100 >= condition1 * 5}
 
check_condition(condition)

 

結果

no block given (yield)
(repl):2:in `check_condition'
(repl):11:in `<main>'

 

-4.2 引数複数

def check_condition(proc1)

if proc1.call(Random.rand(20),Random.rand(20))

puts "OK"

else

puts "NG"

end

end

 

condition = Proc.new{|condition1, condition2|

puts condition1

puts condition2

100 >= condition1 * condition2}

 

check_condition(condition)

 

結果(二回実行)

18
2
OK
=> nil

19
9
NG
=> nil

 

※応用:メソッドにprocを複数渡せる

def check_condition(proc1,proc2)
if proc1.call(Random.rand(50)) && proc2.call(Random.rand(20),Random.rand(20))
puts "OK"
else
puts "NG"
end
end
 
cond1 = Proc.new{|condition|
puts condition
100 >= condition * 5}
 
cond2 = Proc.new{|condition1, condition2|
puts condition1
puts condition2
100 >= condition1 * condition2}
check_condition(cond1,cond2)
結果(3回実行)
6
0
17
OK
=> nil

0
9
15
NG
=> nil
 
30
NG
=> nil
(最初のproc1でfalseになったため、proc2.callが実行されない)
 

 

5.lambdaをブロックとして渡して実行(yieldでもcallでも可能)

-5.1  引数1つ

def check_condition
if yield Random.rand(50)
puts "OK"
else
puts "NG"
end
end
 
# lambda生成
condition = ->condition1{
puts condition1
100 >= condition1 * 5}
 
check_condition(&condition)

 

結果(二回実行)

46
NG
=> nil

11
OK
=> nil

 

-5.2 引数複数
def check_condition
if yield Random.rand(20),Random.rand(20)
puts "OK"
else
puts "NG"
end
end
 
condition = ->condition1, condition2{
puts condition1
puts condition2
100 >= condition1 * condition2}
 
check_condition(&condition)

 

結果(二回実行)

11
6
OK
=> nil

18
8
NG
=> nil

 
 

6.lambdaを普通の引数として渡してcallで実行

-6.1  引数1つ

def check_condition(lambda1)
if lambda1.call(Random.rand(30))
puts "OK"
else
puts "NG"
end
end
 
condition = -> condition1{
puts condition1
100 >= condition1 * 5}
 
check_condition(condition)

 

結果(二回実行)

4
OK
=> nil

27
NG
=> nil

 

-6.2 引数複数

def check_condition(lambda1)
if lambda1.call(Random.rand(20),Random.rand(20))
puts "OK"
else
puts "NG"
end
end
 
condition = -> condition1, condition2{
puts condition1
puts condition2
100 >= condition1 * condition2}
 
check_condition(condition)

 

結果(二回実行)

15
7
NG
=> nil

18
0
OK
=> nil

 

※応用:メソッドにlambdaを複数渡せる

def check_condition(lambda1,lambda2)
if lambda1.call(Random.rand(50)) && lambda2.call(Random.rand(20),Random.rand(20))
puts "OK"
else
puts "NG"
end
end
 
cond1 = -> condition{
puts condition
100 >= condition * 5}
 
cond2 = -> condition1, condition2{
puts condition1
puts condition2
100 >= condition1 * condition2}
check_condition(cond1,cond2)
 
結果(3回実行)
 
6
10
3
OK
=> nil

11
15
18
NG
=> nil

29
NG
=> nil
(最初のlambda1でfalseになったので、lambda2が実行されない)

 

以上ですーーー!!

ブロックを渡すことで、メソッドの数を少なくできる(条件ごとにメソッドを作らなくていいなど。)ことがわかりました!

他にも色々と応用できそうです^^

 

yeildとcallの違いや、procとlambdaの違いなどは、今後まとめられればいいなと思いますーーー!

 

おやすみなさいいいぃぃぃ