ham-capのブログ

プログラミング学習の記録

【Ruby】case文をハッシュに置き換えると幸せになれるかもしれない話

rubocop大先生に怒られる

先日あるプログラムを書いていて、一応実装が終わったのでrubocop大先生の検閲を受けた際、こんなふうにoffenceが出て怒られました。

Style/HashLikeCase Consider replacing case-when with a hash lookup

どうやら「可能であればcase文をハッシュに置き換えろ」ということのようです。 一瞬なんのことかわかりませんでしたが、ググりつつやってみて理解できたのでまとめます。

解決法

結論から言うと、変数の中身の文字列と等しい値はどれか、のような単純な条件の場合にcase文で分岐させるのではなく変数を利用してハッシュから取り出すようなロジックにしろってことらしいのです。

例えばこんな場合。

fruit = 'apple'
case fruit
when 'lemon'
  puts '黄色'
when 'orange'
  puts ''
when 'apple'
  puts ''
end

変数fruitの中身とwhen節の値とを上から順番に照らし合わせていって、真だったwhen節の式が評価されます。この場合は「赤」と表示されるわけです。

これをcase文を使わずにハッシュで再現すると、

colors = {
  'lemon' => '黄色',
  'orange' => '',
  'apple' => ''
}
fruit = 'apple'
puts colors[fruit]

こうなります。

どちらも最終的には「赤」という文字列が出力されるのですが、やってること自体は全然違います。 これ個人的にすごくアハ体験でした。 野暮ったさがないような気がします。

なぜcase文をハッシュに置き換えるほうがいいのか

リファレンスマニュアルのcase文の説明にはこうあります。

case は一つの式に対する一致判定による分岐を行います。when 節で指定された値と最初の式を評価した結果とを演算子 === を用いて比較して、一致する場合には when 節の本体を評価します。

docs.ruby-lang.org

つまり、case文は最初に指定した式とwhen節で指定する値が等しいかどうかを演算子===を用いて判定することのみに特化した文であると考えられます。

そうなると、case文を用いた場合はwhen節を上から順にひたすら照合していくことになるため、場合によっては処理に時間がかかります。

それに対してハッシュを用いた方法の場合、やることはハッシュの中からキーを使って値を取り出すだけなのでcase文を用いた場合に比べて早く処理できる可能性が高いです。

rubocopにこのoffenceが実装されるきっかけになったissueがGitHubにあったのでリンクを貼っておきます。

github.com

このissue内でも処理速度について検証が行われていて、ハッシュを使ったほうがcase文を使うよりも処理速度が速いということを確認できます。

またこれは個人的な感想ですが、上にも書いたとおりハッシュを使ったほうが読みやすいように感じました。 case分はどうしてもwhen節が大量に連なって野暮ったくなりがちだと思うので。

僕のようにプログラミングを勉強中で、超小規模なプログラムしか書かないのであれば問題ないと思いますが、大きなプログラムを作る際にはcase文だと巨大になりすぎる場合もあるように思います。

しかも速度も遅いとなれば、プログラム全体の実行速度に悪い影響を与える要因になるかもしれません。

そのように考えていっても、case文をハッシュに置き換える意義は大きいですし、だからこそrubocopにもそのチェック機能が実装されたのだと思います。

奥が深いですね。

というわけで、今回はこんな感じです!

記載内容に間違い等があった場合にはこっそり教えていただければ幸いです。

最後までお読みいただきありがとうございました。