8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Ruby]Procを使うべき場面、メリットとは

Last updated at Posted at 2019-08-09

はじめに

Procは他言語を学んできた者でもRubyではじめてでてきた概念であるため、理解するのに苦労する。
「Procとは何か?」については大体理解できたが、それを使用すべき場面や使用することによるメリットというのを実感するために、Procで実装してあるものをProc無しでの実装を試みてみる。

Procとは

Rubyで頻繁に使用するブロックは色んな場面で持ち出して利用していきたいが、ブロックはオブジェクトではない。
オブジェクト指向であるRubyはオブジェクトとして捉えられると何かと便利であるので、ブロックもオブジェクト化したい。

そこで登場するのがProcであり、Procは「ブロックをオブジェクト化」したものである。
このProcの機能を活かした、Procを用いた実装例から深く学んでいく。
#Procを使用した実装例
文字列をエフェクトをする仕組みをProcを使用して実装する。

今回実装する文字のエフェクトは3種類。
・リバース...逆順 例)'apple',reverse=>'elppa'
・エコー...残響化 例)'apple',echo(2)=>'aappppllee'
・ラウド...大声  例)'apple',loud(3)=>'APPLE!!!'

そして、これらのエフェクトを混合させる。
(以下、このことをWordSynthと表記する)
echo(2)→loud(3)→reverse => '!!!EELLPPPPAA'

この仕組をまずはProcを使用して作成する。
#Procを使用して実装
まずはEffectsに関しての実装。
メソッドの中でProcを作成している。

./lib/effects.rb
module Effects
  # reverseエフェクトについて関してのメソッド
  def self.reverse
    proc do |words|
      words.split(' ').map(&:reverse).join(' ')
    end
  end
  # echoエフェクトについて関してのメソッド
  def self.echo(rate)
    proc do |words|
      words.chars.map{|c| c==' ' ?  c:c*rate}.join
    end
  end
  # loudエフェクトについて関してのメソッド
  def self.loud(level)
    proc do |words|
      words.split(' ').map {|word| word.upcase + '!'*level }.join(' ')
    end
  end
end

WordSynthに関しての実装。
Effectsで実装したProcをcall()で呼び出す。

./lib/word_synth.rb
class WordSynth
  def initialize
    @effects =[]
  end
#effectを配列に加える
  def add_effect(effect)
    @effects << effect
  end
#配列に格納されたeffectを順々に実施
  def play(original_words)
    @effects.inject(original_words) do |words,effect|
      effect.call(words)
    end
  end
end

Effects,WordSynthに関して実行させる

./list/word_synth_execute.rb
require './lib/effects'
require './lib/word_synth'

# Effectsに関して
effect1 = Effects.reverse
effect2 = Effects.echo(2)
effect3 = Effects.loud(3)
puts effect1.call('Ruby is fun!')
puts effect2.call('Ruby is fun!')
puts effect3.call('Ruby is fun!')

# WordSynthに関して
synth = WordSynth.new
synth.add_effect(Effects.echo(2))
synth.add_effect(Effects.loud(3))
synth.add_effect(Effects.reverse)
puts synth.play('Ruby is fun!')

実行結果

ybuR si !nuf
RRuubbyy iiss ffuunn!!
RUBY!!! IS!!! FUN!!!!
!!!YYBBUURR !!!SSII !!!!!NNUUFF

Procを使用することによって、WordSynthを作成することはできた。
なんとなくProcを使用すると都合良く作成できた感触はある。
しかし、イマイチその威力がわかっていない。
Procを使わずに突き進もうとしたらどうなっていたのか検証してみた。
#Procを使用せずに実装を試みる
まずはEffecsの実装。
Procの引数で与えていた(words)をどうするか、、

effects_test.rb
module Effects
  def self.reverse(words)
    words.split(' ').map(&:reverse).join(' ')
  end
  def self.echo(words,rate)
    words.chars.map{|c| c==' ' ?  c:c*rate}.join
  end
  def self.loud(words,level)
    words.split(' ').map {|word| word.upcase + '!'*level }.join(' ')
  end
end

とりあえず、メソッドに第一引数,第二引数という形で引数wordsを与えた。
Procを使用せずとも問題ないのでは??

続いて、WordSynthの実装。

word_synth_test.rb
class WordSynth
  def initialize
    @effects =[]
  end

  def add_effect(effect)
    @effects << effect
  end

#  Procを使用していないとplay(original_words)を使用できない

  # def play(original_words)
  #   @effects.inject(original_words) do |words,effect|
  #     effect.call(words)
  #   end
  # end

end

Effectsの時点で引数に(words)を与えてしまうため、先程のplay(original_words)をうまく作ることができない。

そもそもこれでは@ effects =[]に格納するものがeffect機能ではなくて、既に与えられた文字を変換した文字列にしかならない。

何か工夫すればProcを使用せずとも同じ機能をもちあわせるメソッドを作成できそうではあるが、Procを使用すると簡単に上記の機能を作成することができるというのはわかった。

#Procを使用するメリットについて
検証からProcの強みを2つ実感した。
メソッドが受け取れるブロックの数は最大で1つであるが、Procを利用すれば複数のブロックを使用できるということ。
callのタイミングで引数を与えることができるということ。

play(original_words)ではcallを使用することで、メソッドの中で2つのブロックが機能していていることがわかる。
また、引数(words)をcallのタイミングで入れることができるという点も特徴的である。

反対にProcを使用していない方は、1つのメソッドにブロックは1つであり、引数(words)を与えるタイミングも他の引数と同時でなくてはいけなくなる。
#まとめ
Procを使用するメリットは他にもたくさんあると思うが、あくまで今回の検証からは2つのメリットを実感できる。

プログラミングの学習の際、どういった機能であるかを理解することも大事であるが、それをどの場面に使用すべきかを自分なりにイメージできるようになることも大切である。

#参考文献

この記事は以下の情報を参考にして執筆しました。

  • プロを目指す人のためのRuby入門 伊藤 淳一[著]
8
5
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
8
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?