LoginSignup
4
5

More than 5 years have passed since last update.

Rubyのcase式で気を付けること

Posted at

case式での一般的なRangeオブジェクトの使い方

Cool!に書けますよねー

range_case.rb
def range_case(year)
  case year
  when 1912..1926
    "T"
  when 1926..1989
    "S"
  else
    "H"
  end
end

range_case(1926)  # => "T"
range_case(1973)  # => "S"
range_case(2012)  # => "H"

case式でRangeオブジェクト同士の比較には気を付けて

Range(, Regexp, Module)オブジェクト同士の比較にcase式は使わない方がイイかも?Cool!な書き方によるトラップ

strange_case.rb
def strange_case(obj)
  case obj
  when obj
    true
  else
    false
  end
end

strange_case( "1" )       # => true
strange_case( :"1" )      # => true
strange_case( 1 )         # => true
strange_case( [1, 2, 3] ) # => true
strange_case( {"1"=>1} )  # => true
strange_case( (1..3) )    # => false
strange_case( /.*/ )      # => false
strange_case( Fixnum )    # => false

なので、ArrayオブジェクトはRangeオブジェクトのようにはならないよね

Arrayオブジェクトでも「*」で展開すればOKですけど、そのままでは上の例の通りNGです。

array_case.rb
def array_case(year)
  case year
  when [*1925, 1926]
    "T"
  when [*1926..1989]
    "S"
  else
    "H"
  end
end

array_case(1926)          # => "H"
array_case(1973)          # => "H"
array_case(2012)          # => "H"

ArrayオブジェクトもRangeオブジェクトと同じ仕組みを持たせれば同様な動きになるよ

ArrayをオープンしてRange#include?と同様にArray#include?のエイリアスにArray#===を追加する
「*」で展開しなくてもOKになる

ex_array_case.rb
class Array
  alias :=== :include?
end

def ex_array_case(year)
  case year
  when [*1925, 1926]
    "T"
  when [*1926..1989]
    "S"
  else
    "H"
  end
end

ex_array_case(1926)       # => "T"
ex_array_case(1973)       # => "S"
ex_array_case(2012)       # => "H"

でも、当然弊害でるよ

Arrayオブジェクト同士の比較もNGに。
Range#include?のエイリアスにRange#===があるのに、Array#include?のエイリアスにArray#===がないのは何故?って思ってたけど、これが理由なのかな?

arara_case.rb
require './strange_case.rb'

strange_case( "1" )       # => true
strange_case( :"1" )      # => true
strange_case( 1 )         # => true
strange_case( [1, 2, 3] ) # => false
strange_case( {"1"=>1} )  # => true
strange_case( (1..3) )    # => false
strange_case( /.*/ )      # => false
strange_case( Fixnum )    # => false
4
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
4
5