Bye Bye Moore

PoCソルジャーな零細事業主が作業メモを残すブログ

caseによってビミョーに違うメソッドを呼び出している場合の別実装

たとえば、次のようなタイプと値を指定すると特定の処理をしてくれるメソッドがあったとします。

def sortMethod(type,val)
  case type
  when :name then val.upcase  
  when :val then val.next  
  end  
end 

sortMethod(:name, "name")
#>> "NAME"

sortMethod(:val, 12)
#>> 13

これをリファクタリング……というか、別の方法で実装してみます。

別実装

Hashとlambda記法

値にlambdaをもつハッシュに置き換えてあげる事もできます。
動作はこんな感じ

altCase = {name: ->(x){ x.upcase}, val: ->(x){x.next} }

altCase[:name].call("name")
#>> "NAME"

altCase[:val].call(12)
#>> 13

見た目短いです。再帰なんか使う局面では有効そう?

クラスをつくる

まぁ、オブジェクト指向言語なんですから、クラスでかき分けるのがいいでしょね。
リファクタリング:Rubyエディションにもそう書いてある。

class SortMethodClass
  def self.name(x); x.upcase; end
  def self.val(x);  x.next; end
end

SortMethodClass.name("name")
#>> "NAME"

速度比較

Benchmark.ips do |x|
 x.report( "Method" )       { sortMethod(:name, "name") }
 x.report( "HashWithProc" ) { altCase[:name].call("name") }
 x.report( "Class" )        { SortMethodClass.name("name") }
 x.compare!
end

というベンチマークでみると

Calculating -------------------------------------
              Method    68.134k i/100ms
        HashWithProc    73.034k i/100ms
               Class    82.339k i/100ms
-------------------------------------------------
              Method      2.597M (±13.8%) i/s -     12.605M
        HashWithProc      1.930M (±20.2%) i/s -      9.056M
               Class      2.790M (±17.2%) i/s -     13.257M

Comparison:
               Class:  2789970.3 i/s
              Method:  2597019.6 i/s - 1.07x slower
        HashWithProc:  1929799.9 i/s - 1.45x slower

……クラスの方が早いじゃないか(憤怒)
可視性も拡張性も段違いなので、残念ながら今回は王道のクラス実装に軍配があがりますね。