Swiftで HTTP StatusCode が400台だったら、みたいなif文を switch case 400..<500 みたいに簡潔に書きたかった時の話

例えばStatusCode400系のケースで一括処理をしたい時。 Case文ならこんな感じで書けて、条件のところが400..<500みたいにとても簡潔。

でも、400系のケースだけを判別したい時にわざわざswitch文を書くのは、無駄に行を消費している感じがしてエレガント感を損なう。

if (ほにゃらら) {ゴニョゴニョ}

程度で済ませたい。 じゃあStatusCode400系を表すのはどういう記述になるのかって、 普通に考えたらこうだ。

if (400 <= statusCode && statusCode < 500) { /* リトライしても意味ないんだからね! */ }

これは条件文が2つもくっついてて長くて読みにくい。 switch case 400..<500ぐらいでサクッと書けないものなのか。 あるだろ、Swiftなら、そういう方法が、きっと...!

そもそも switch case も 何かの演算子が暗黙的に使われてるんだったよなー... どこかでそんな情報を聞いたことがあった気が妙にすると思ったら、 なんだ、はてなSwiftの教科書にも書いてあった!

個々の case はパターンマッチによって評価される。パターンマッチによってマッチするかどうかは、~= という二項演算子の結果が利用される。

github.com

switch case でそのケースに合致するのかどうかは、 ~=演算子によって計算されている。 つまりif文でcase 400..<500みたいに書きたければ~=を使えば良い。

ちなみに(自分がこれを教科書で見かけたのだと気づかずに)いろいろ検索してみたところ、 ~=演算子はあんまり話が出てこなかった。比較演算子をたくさん並べている記事でもスルーされていたりする。 可哀想に。~=というヤツのことはどうやらエクスプレッションパターンと言うらしい。

Swiftはパターンによってエレガントな書き方でいろんなことが表現できる。 そのパターンを知らないと目の前のコードで何が起きているのかさっぱりわからないので、 パターンがSwiftのよく分からなさの一端を担っている気もする。

なんでそういう書き方をするんだ!なんであの書き方がこう書いても同じ処理なんだ! みたいな謎の正体が、実はパターンなのだというお話を Swift 2シンポジウム #2@_ishkawa さんがされていた。

speakerdeck.com

日本語訳したパターン集はQiitaの次の記事に色々書いてあるので、 興味がある人はじっくり読んでみるといいかも。 エクスプレッションパターンも書かれている。

qiita.com

というわけで、StatusCodeが400台だったら、みたいなif文をswitch文のcaseみたいに書くなら、こんな感じで書けるのでした。

贅沢を言うとすると、範囲演算子 400..<500 を左に書かなければならないのが辛い。 人間的には「A が Bに含まれるか」という順番のほうが頭にすんなり入る。 ま、if (400 <= statusCode && statusCode < 500) {}とかよりは美しいからいいけどね!

めでたしめでたし。

追記!

他にも色々な書き方ができますよ、といろいろ教えていただきました。範囲演算子.contains(X)というのも出来るのか!それも良いですね。ありがとございます!!