LoginSignup
1
4

More than 5 years have passed since last update.

Ruby のブロック付きメソッドを実装する

Last updated at Posted at 2017-05-20

シンプルな例

メソッド呼び出し(super・ブロック付き・yield) (Ruby 2.4.0) https://docs.ruby-lang.org/ja/latest/doc/spec=2fcall.html

ブロック付きメソッドとは制御構造の抽象化のために用いられる メソッドです。最初はループの抽象化のために用いられていたため、 特にイテレータと呼ばれることもあります。 do ... end または { ... } で囲まれたコードの断片 (ブロックと呼ばれる)を後ろに付けてメソッドを呼び出すと、その メソッドの内部からブロックを評価できます。 ブロック付きメソッドを自分で定義するには yield 式を使います。

ソースコード

# ブロック付きメソッド
def add(x, y)
  puts "begin: #{x}, #{y}"
  yield(x + y) # 足した結果をブロックに渡す
  puts "end: #{x}, #{y}"
end

# ブロック付きメソッドを呼び出す
add 2, 3 do |result|
  puts "answer: #{result}"
end

実行結果

begin: 2, 3
answer: 5
end: 2, 3

Proc オブジェクトを使う

class Proc (Ruby 2.4.0) https://docs.ruby-lang.org/ja/latest/class/Proc.html

ブロックをコンテキスト(ローカル変数のスコープやスタックフ レーム)とともにオブジェクト化した手続きオブジェクトです。
Proc は ローカル変数のスコープを導入しないことを除いて 名前のない関数のように使えます。ダイナミックローカル変数は Proc ローカルの変数として使えます。

ソースコード

# ブロック付きメソッド
def add(x, y)
  puts "begin: #{x}, #{y}"
  yield(x + y) # 足した結果をブロックに渡す
  puts "end: #{x}, #{y}"
end

# Procオブジェクトを生成
header = ''
p = Proc.new{|result|
  puts "#{header}: #{result}"
}
header = 'answer' # ブロック内で使う変数に値を代入

# ブロック付きメソッドを呼び出す
add 2, 3, &p

実行結果

begin: 2, 3
answer: 5
end: 2, 3

ループ処理

ソースコード

# ブロック付きメソッド
def double(array)
  array.each do |e|
    # 元の値と2倍した値をブロックに渡す
    yield(e, e * 2)
  end
end

# ブロック付きメソッドを呼び出す
double [2, 3, 5] do |src, dst|
  puts "#{src} -> #{dst}"
end

実行結果

2 -> 4
3 -> 6
5 -> 10

ブロックをコールバックする

ソースコード

class Slots

  def initialize()
    @slots = {}
  end

  # マッチしたときに実行するブロックを登録する
  def add(regexp, &block)
    @slots[regexp] = block
  end

  # 文字列にマッチしたら対応するブロックを実行する
  def match(str)
    @slots.each do |regexp, block|
      if matchdata = str.match(regexp)
        puts "[match] #{block.yield(matchdata)}"
      end
    end
  end
end

slots = Slots.new
slots.add(/hell/i) {|m| "'#{m.string}' has 'hell'."}
slots.add(/hello/i){|m| "'#{m.string}' has 'hello'."}

slots.match('He')
slots.match('HELL')
slots.match('Hello, Goodbye')

実行結果

[match] 'HELL' has 'hell'.
[match] 'Hello, Goodbye' has 'hell'.
[match] 'Hello, Goodbye' has 'hello'.

参考資料

1
4
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
1
4