0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Ruby】ブロックとProc

Posted at

Proc

本来オブジェクトにできないブロックをオブジェクト化するもの。これにより再利用性を高め、柔軟で動的なコードにすることができる。

ブロックとは?

  • ブロックは、メソッドに渡すことができるコードの塊
  • {} または do..end で囲まれたコードで表される
  • メソッドは yield を使用してブロックを呼び出すことができる
  • Rubyは全てのコードがオブジェクトと言われているが、例外的にブロックはオブジェクトではない。従来であれば、ブロックはオブジェクトにできなかったが、Procを用いることでブロックをオブジェクトとして扱うことができる
# do..endの箇所がブロックで、timesの引数
3.times do |i|
  puts a 
end
#=> 0 1 2

# {}の箇所がブロックで、timesの引数
3.times { |i| puts i }
#=> 0 1 2

何が嬉しいの?ある時代とない時代の処理の違い

可搬性・再利用性・柔軟性

Procがない時代には、ブロックをオブジェクト化できないため、同じような処理を行う場合に同じコードを何度も書かなければならなかったり、特定の構造の中でしかコードを実行できないという制限があった

しかし、Procを使うと、コードの断片を変数に割り当てたり、メソッドの引数として渡したりすることができるため、プログラムの可搬性・再利用性・柔軟性の向上を期待できるようになった。

メソッドを使った場合(その1)
def handle_text(text, mode)
  # modeが増えるたびに条件分岐を増やさなければならない
  if mode == :uppercase
    puts text.upcase
  elsif mode == :reverse
    puts text.reverse
  else
    puts text
  end
end

handle_text("hello", :uppercase)  # "HELLO"
handle_text("hello", :reverse)    # "olleh"
handle_text("hello", :normal)     # "hello"
# modeが増えるたびにhandle_textに条件分岐を追加しなければならないが、これはメソッドの柔軟性やテスタビリティを損なう。
Procを使った場合(その1)
def handle_text(text, operation)
  operation.call(text)
end

uppercase_proc = Proc.new { |t| puts t.upcase }
reverse_proc = Proc.new { |t| puts t.reverse }

handle_text("hello", uppercase_proc)  # "HELLO"
handle_text("hello", reverse_proc)    # "olleh"
# Procの利用は、プログラムの柔軟性を高め、既存のメソッドを変更せずに新しい機能を追加できるようにするという点で、オープン・クローズドの原則と似た目的を持っている
メソッドを使った場合(その2)
# 通常のメソッド
def multiply(number, factor)
  number * factor
end

def divide(number, factor)
  number / factor
end

def add(number, factor)
  number + factor
end

def perform_calculation(number, factor, operation)
  case operation
  when :multiply
    result = multiply(number, factor)
  when :divide
    result = divide(number, factor)
  when :add
    result = add(number, factor)
  end
  puts "結果: #{result}"
end

# 異なる計算を実行
perform_calculation(10, 3, :multiply)  # 乗算: 結果: 30
perform_calculation(10, 3, :divide)    # 除算: 結果: 3.333...
perform_calculation(10, 3, :add)       # 加算: 結果: 13
Procを使った場合(その2)
# Procの例
multiply = Proc.new { |number, factor| number * factor }
divide = Proc.new { |number, factor| number / factor }
add = Proc.new { |number, factor| number + factor }

def perform_calculation(number, operation)
  result = operation.call(number, 3)
  puts "結果: #{result}"
end

# 異なる計算を実行
perform_calculation(10, multiply)  # 乗算: 結果: 30
perform_calculation(10, divide)    # 除算: 結果: 3.333...
perform_calculation(10, add)       # 加算: 結果: 13
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?