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

More than 1 year has passed since last update.

else節ではraiseしたくなる

Last updated at Posted at 2022-06-19

はじめに

僕はcase文だったりswitch文のelse(default)節に正常処理を書くことが嫌いです。
ただ、if文のelse節には正常処理をガンガン書きます。
どうして、そうしているのか、その訳をつらつらと書いていきたいと思います。

Rubyの制御構造(条件分岐)

Rubyの制御構文、特に条件分岐に関するものは以下の三種類がある。

  • if文
  • unless文
  • case文

それぞれの構文は以下の通りだ。式を後置修飾するif修飾子およびunless修飾子については本題から逸れるので省略した。

if文

if 1
    処理1
elsif 2
    処理2
end

unless文

unless 
    処理1
else
    処理2
end

case文

case 0
when 1
    処理1
when 2
    処理2
else
    処理3
end

if文はelsif節を使って、case文はそもそもの構文として複数条件による分岐ができる。それに対して、unless文にはそれに該当する構文がない。
そのため、case文とif文はお互いに書き換えができ、実際、rubyの日本語リファレンスにもcase文からif文への書き換え方が記載されている。

ただ、僕はcase文とif文にはその目的、使用意図に決定的な違いがあると考えている。それどころか、個人的にはif文とunless文が同じ枠組みで、case文はそれらとは別物だと思っている。
if文とcase文の目的の違いこそが、僕にcase文のelse節でraiseしたい衝動を呼び起こしているのだ。

if文とcase文の違い

端的に表せば、それは条件式に期待されることだ。簡単に書くと次の通りだ。

  • if文:boolean
  • case文:ある集合に属する値

if文の場合、構文的にも条件式の値はbooleanとして解釈されるし、読み手もそれを期待する。(少なくとも僕はそうだ)
もちろん、Rubyはfalseとnilだけをfalseとして解釈し、それ以外の値を全てtrueとして評価するから、if文の条件式にboolean以外を与えることはできるし、それについては、nilをundefinedのように扱って、特定の値が存在すれば処理をする、のような書き方もできるから否定はしない。というか、割と使う。

case文の場合、そもそも条件の成立条件はそれぞれの処理に紐づいている条件式だけでは決まらない。なぜなら、大元の式の評価値とそれぞれの条件式の評価値の一致を条件の成立としているからだ。
そのため、個人的にはcase文はある変数が特定の値の内どれかであることが確定している場合に使うことが多い。
例として、あまり綺麗ではないが以下のコードを掲載しておく。

module Brother
    Taro = 1
    Jiro = 2
    Saburo = 3
end

def name(brother)
    case brother
    when Brother::Taro
        'taro'
    when Brother::Jiro
        'jiro'
    when Brother::Saburo
        'saburo'
    else
        raise "#{name} is not a brother"
    end
end
   

仮に、上の例のnameメソッドを以下のように書き換えると非常に気味が悪い。
なぜなら、変数brotherに兄弟ではないmichaelやjohnが来たとしても、saburoとして評価してしまうからだ。
実務的な理由から、raiseではなくロギングにとどめていることもあるが、それでもsaburoと返してしまうよりはマシだろう。
つまり、個人的にはcase文のelse節はそもそも限りなく例外に近いのだ。
契約を破った要求に対して、見当違いの応答をするぐらいなら拒否してくれたほうが、まだ良心的だ。

def name(brother)
    case brother
    when Brother::Taro
        'taro'
    when Brother::Jiro
        'jiro'
    else
        'saburo'
    end
end

最後に

なぜ、こんな考え方になったんだろう、と思い返すと、自分がシステムに埋め込んだあるバグと、攻撃的プログラミングという考え方、また、以前読んだあるエッセイに影響を受けていると思う。
参考までにそれぞれへのリンクを載せて終わることにする。

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