LoginSignup
64

More than 5 years have passed since last update.

Ruby ブロックについて学ぶ

Last updated at Posted at 2015-08-04

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

ブロックとは

メソッド呼び出しの際に引数と一緒に渡すことのできる処理のかたまり | たのしいRuby P199

ブロックつきメソッド呼び出しの例

[1, 2, 3, 4, 5].each do |i| # do ~ end は { ~ } でもOK
   puts i ** 2
end
=> 1
   4
   9
   16
   25

ブロックの使い方

代表的な使い方が以下の3つです。
- 繰り返し
- 処理の隠蔽
- 処理の一部の差し替え

繰り返し

# 例)hash
sum = 0
outcome = {'join' => 1000, "shopping" => 1000, 'food' => 4000}
outcome.each do |item, price|
  sum += price
end
puts sum
=> 6000

# 例)file読込
file = File.open('sample.txt')
file.each_line do |line|
  print line
end
=> aaa
   bbb
   ccc
   ddd
file.close

処理を隠す

# 例)自動的にファイルが閉じられる
file = File.open('sample.txt') do |file|
  file.each_line do |line|
    print line
  end
end
=> aaa
   bbb
   ccc
   ddd

計算の一部の差し替え

# Array#sortの場合

a = [3, 4, 5, 2, 6, 1, 7]

# ブロックなし
sorted = a.sort
=> [1, 2, 3, 4, 5, 6, 7]

# デフォルトの処理と同じ
sorted = a.sort do |a, b|
  a <=> b
end
=> [1, 2, 3, 4, 5, 6, 7]

# リバース
sorted = a.sort do |a, b|
  b <=> a
end
=> [7, 6, 5, 4, 3, 2, 1]


str_a = ["udon", "yakisoba", "somen", "ra---men"]

# 文字数順
sorted = str_a.sort do |a, b|
  a.length <=> b.length
end
=> ["udon", "somen", "yakisoba", "ra---men"]

ブロックつきメソッドの作り方

ブロックの処理 → 合計値を算出するメソッドの例


def total(from, to)
  result = 0
  from.upto(to) do |num|
    if block_given?
      result += yield(num)
    else
      result += num
    end
  end
  return result
end

p total(1, 10)
=> 55
p total(1, 10){|num| num ** 2}
=> 385

ブロック変数とyieldの引数の関係

ブロック変数とyieldの引数の数はあわなくてもエラーにはならない


# ブロック変数がyield引数より多い場合
def block_args
  yield()
end
block_args do |a|
  p [a]
end
=> nil

# ブロック変数がyield引数より少ない場合
def block_arg
  yield(1,2,3)
end
block_arg do |a|
  p a
end
=> 1

# ブロック変数を*aで受け取る場合
def block_arg
  yield(1,2,3)
end
block_arg do | *a |
  p a
end
=> [1, 2, 3]

ブロックのオブジェクト化

Procを使う。ブロックを別メソッドに引き渡すことが可能になる

# Proc変数を使用する例
def total2(from, to, &block) # &引数名にすると与えられたブロックはProcオブジェクト化される
  result = 0
  from.upto(to) do |num|
    if block                # 判定式も変更
      result += block.call(num) # block.callで呼び出し
    else
      result += num
    end
  end
  return result
end

ローカル変数とブロック変数

主な特徴は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
64