[Swift] 三項演算子の使い方

Swift

     
⌛️ < 1 min.
難しくないと思うのにあまり理解されない 三項演算子 を説明します。

三項演算子

三項演算子は、条件式の真偽によって取る値を変えることができる演算子です。

三項演算子は、その名の通り 3つの項で構成されるものです。それぞれの間に、 ? と : を置いて、
“第1項 ? 第2項 : 第3項” という構文になっています。

第1項が 条件式にあたります。

第2項は、条件式が真であれば、値として採用されるものです。

第3項は、条件式が偽であれば、値として採用されるものです。

上記の3つの項で構成されるために、”三項”演算子と呼ばれます。

三項演算子がよく使われる ”いずれか小さい方の値を取る”という 三項演算子 をみてみます。

以下の式は、a, b のいずれか小さい方の値を minimum に代入しています。

三項演算子


let minimum = a < b ? a : b

1番めの項は、”a < b” であり、この評価の値(真か偽が)によって、式の評価が変わります。

2番めの項は、”a” なので、1番めの項である “a < b” が真、つまり “a が b より小さい時”に、a の値が採用されます

3番めの項は、”b” なので、1番めの項である “a < b” が偽、つまり “a が b より小さくない時”に、b の値が採用されます

ですので、三項演算子を使った式 “a < b ? a : b” は、”a, b いずれか小さい方の値を取る” という式になります。

やっていることは非常にシンプルなのですが、3つの構成要素を持つことが複雑に見えるのか プログラミングを始めたばかりの人は敬遠しがちな気がします。

ですが、うまくつかうと、コードが 短く わかりやすく なります。

三項演算子を使うメリット

三項演算子を使うメリットを少し詳しめに説明してみます。

ポイントとしては、「三項演算子でしか書けないロジックはありません」。

先の 小さい方の値を取得する処理も “if文” を使っても実装できます。
では、どのような違いがあるのか比較してみます。

三項演算子を使わずに書けるか?

まず 三項演算子を使わない処理を書いてみます。

以下のコードは、三項演算子を使わずに、a, b のいずれか小さい方の値を minimum に代入します。(機能的には、先のコードと同等です)

小さい方の値を取得するコード


let a = 4.5
let b = 2.3
...
let minimum: Int
if a < b {
    minimum = a
} else {
    minimum = b
}

if 文を使った処理の考察/比較 (1) : let で定義するが一時的に未設定になる

2つのコードを比較すると、変数を 定義している箇所で 値も設定しているかどうかが違うことがわかります。

if 文で処理する場合は、値を1文で設定することができないため、定義する場所と設定する場所が離れてしまいます。

「定義する場所と設定する場所が離れること」の何が問題なのか? ですが、
コードを読む人からすると、変数が定義された時にその値に注意が向きます。定義した箇所で設定されていればわかりやすいです。
特に、let で定義している変数は、一度設定すると後では変更できないので その時点での設定値の意味を理解すれば その変数を理解したことになります。
ですが、定義と設定が別の箇所で行われていると、「この変数を設定している”すべて”の箇所で”どのような値”を使っているか」を確認しなければいけません。

今回の例のように、制御構文(if など)を使って、複数箇所で設定されているとを、どのような条件でどの値が使用されるかを読み解かなければいけません。

関数やメソッドの中という比較的狭いスコープですが、その範囲での制御フローを理解してかつ、変数を設定しているすべての箇所を理解しなければいけないというコードは、理解しやすいコードとは言い難いでしょう。

このことは、Apple が言う “local reasoning(ローカル リーズニング)” に反することにもつながっていきます。

local reasoning

local reasoning は、直訳すると “近いところでの理由づけ”です。
つまり、コードを理解するために読まなければいけない範囲をできるだけ狭くすることで、コードの可読性(ひいてはメンテナンス性)をよくすることです。

上の例では、処理を読む時に考慮しなければいけないことをできるだけ少なくするために、minimum の値が変わる可能性を排除したい ということです。

MEMO as of 2022.04.08

記事公開当初 let, var の違いで説明していましたが、どちらも let で記述できるので 説明を修正しました。

if 文を使った処理の考察/比較 (2) : 行数

一目瞭然ですが、三項演算子を使ったコードが 1行で済んでいるのに対し、if 文を使ったコードでは 6行必要です。
{ や } を 同一行にまとめていっても、(可読性を考えると)少なくとも2行以上必要になります。

行数が多いとそれだけ読む量が増えますので、可読性は下がります。

複雑な処理であれば、わかりやすさのために すこし ブレークダウンして記述することもありえるかと思いますが、小さい方の値を処理をそこまでブレークダウンすることは少ないかと思います。

まとめ:三項演算子とPros/Cons

三項演算子とPros/Cons
  • ? と : を使って、条件成立時/不成立時の値を指定できる
  • [Pros]変数定義と設定を、1ヶ所でできる。
  • [Pros]少ない行数でかける
  • [Cons]条件がシンプルでないとパッと読めない
  • [Cons]一行が長くなりがち

説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。

Swift おすすめ本

Swift を深く理解するには、以下の本がおすすめです。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です