このところは 演算子
の基本的なところについて眺めていってみてますけれど、今回はその中で少し気になった 三項演算子
に着目してみます。何かと意見がすれ違いがちな気がするこの機能ですけれど、世の中的にどんな感じの捉え方がされているのか、そんなあたりを窺えたらいいなと思ってます。よろしくお願いしますね。
———————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #319
00:00 Start 00:18 前回のおさらい 00:56 今日は三項演算子のお話 01:08 三項演算子は独自定義できる? 03:37 そもそもの、演算子の独自定義方法は 05:40 三項演算子を独自定義する手段がなさそう 06:15 三項条件演算子 07:38 三項演算子と同等のコード 10:00 三項演算子がある利点 10:32 独自定義は "解釈" が必要 12:43 三項演算子は避けられがち? 13:26 表現が複雑になる可能性はどれも一緒 15:21 世間が思う三項演算子 16:27 三項演算子の学習コスト 18:23 三項演算子は避けるのが賢明? 21:13 inline if や ternary if とも呼ばれる? 21:22 if 式 23:52 条件演算子以外の三項演算子は存在する? 24:12 参照透過性とは 28:12 三項演算子は、わかりにくい? 29:20 3つの項それぞれがどれか判別しにくい 31:08 優先順位を扱いづらい 31:39 次回の展望 ————————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #319
今日も引き続き「The Swift Programming Language」の勉強をしていきます。今回は演算子についてのお話です。以前に単項演算子、二項演算子、三項演算子の3種類があることを確認しました。単項演算子は一つの対象に対して何かしらの操作を行うもので、二項演算子は二つの対象を操作します。そして三項演算子は三つの対象に対して操作を行いますが、これは少し特殊です。
そこで、今回は三項演算子に注目し、特にどのあたりが特徴的なのかについてお話しします。まず、単項演算子と二項演算子は独自に定義が可能ですが、三項演算子は独自の定義ができません。Swiftに限らず、他の言語でも演算子の独自定義が提供されていることがありますが、この中で三項演算子が独自に定義できないように感じます。
実際にSwiftのプレイグラウンドを起動して試してみましたが、独自定義はやはりできません。Swiftで独自演算子を定義する際にはoperator
という予約語を使い、記号を定義します。しかし、三項演算子の独自定義の例は見つかりませんでした。
プレイグラウンドで試行錯誤しながら、独自演算子の定義を行うことはできるのですが、三項演算子に関してはシステムが用意しているものしか使えません。そのため、三項演算子として利用できるのは条件演算子だけです。
条件演算子は、例えば以下のように使います。condition ? trueValue : falseValue
という形です。条件式が真の場合はtrueValue
が返り、偽の場合はfalseValue
が返ります。このように、Swiftでは三項演算子が少し特殊な位置づけとなっています。 プログラムの実行において、条件によって結果が変わる場合があります。例えば、条件式を設定し、その結果が真の場合はこれ、それが偽の場合はこれ、というように処理を分けることがよくあります。昔は、このような条件分岐をサポートする演算子が用意されていなかったので、独自の関数を用意して、条件に応じて適切な値を返す、といった方法が一般的でした。条件式を評価し、真偽値によって異なる処理を行う関数を何度も作成することは手間であったため、参考演算子(例えばSwiftの三項演算子 condition ? trueValue : falseValue
)を利用することで、コードをシンプルにすることができました。
ただ、参考演算子や条件演算子を使わずに、頻繁に出現するこうしたパターンを独自定義した関数で取り扱い、それによって値を調整することも一つの方法ですが、このアプローチには関数を記憶する必要や実装の手間が伴います。プログラマーの思考負担を軽減するためには、直感的に理解できるコードを書くことが重要です。
人間が一日に下すことができる判断の数には限界があるという説もあり、それを考慮すると、既知の方法を活用して頭のリソースを節約することが賢明かもしれません。そのためには、頻繁に使われる汎用的なパターンを覚えることで、考える必要を減らすことができます。
具体的に言えば、三項演算子(参考演算子)は、簡便で直感的に理解しやすい場合が多いです。例えば、Swiftで条件演算子を使って簡潔に書ける 24行目から31行目のコード例では、シンプルさや再利用を考慮しないのであれば、28行目のように準備が不要なコードが最適になります。状況に応じて、参考演算子がより適している場合と独自関数が適している場合を判断することが必要です。
世の中には、参考演算子を使うべきでないという意見もありますが、状況に応じて最適な方法を選択することが大事です。場面によっては、条件の分岐を行うのに参考演算子を使うことで、よりシンプルで効率的なコードになることもあります。 if文やswitch文を使っていると、処理が複雑になってきたときに関数に分離しようという話になるのは自然なことですよね。つまり、これらの構文はどれも同等に扱えるものでしょう。しかしながら、三項演算子は一般的に避けるべきだと考えられているようですね。それについてどう思いますか?具体的には、「三項演算子は使うべきではない」という意見をよく耳にしますが、皆さんの意見もぜひ聞いてみたいです。
私は個人的にはif文やswitch文、三項演算子をどれも対等に扱っていますが、三項演算子を良くないと思う人たちもいるようですね。これが本当に適切かもしれません。少し前の循環参照の話でも、クロージャとインスタンスの循環参照を避けるために、アンオーンドで対応するか、ウィークで安全を確保するかという点で議論になりますよね。私はついついアンオーンドを使ってしまうのですが、確かに良くない場合もあるので、難しいところです。
結局、どれが正解かは分かりませんし、時代によっても変わることがあります。最終的には、自分の理想を持ちながら進めていけば良いのではないかと思います。ただ、参考演算子が世の中でどのような立ち位置にあるのかは気になります。独自定義についても気になる部分ですが、個人的な趣味に過ぎませんので、そこまで気にしていません。
また、三項演算子について調べると、適切な使い方やWikipediaにさえ記載がないように感じます。違いは構文の違いだけで、機能自体はそれほど複雑ではない気がします。とはいえ、三項演算子を知らない人がいる可能性があるので、使用を避けましょうという話を聞いたことがあります。しかし、私はそのような発想は良くないと思います。
そのように考えてしまうと、Swiftでプロトコルを使用する際に、「バイナリーインターフェースを使用するのは分からない人がいるからやめましょう」という話になってしまい、進歩が止まってしまいますよね。ジェネリックスの使用をやめましょうという話も聞いたことがありませんし、もしあるとしたら、ジェネリックスを使わないようにするより、使えるように努力する方が健全ではないでしょうか。難しいから分からないからやめましょうという風に何かを避けることはお勧めしたくありません。
Pythonについては詳しくないので、よく分からない部分もあります。しかし、以前話題に上がった「特異変転期」の話のように、古いブログや資料を参照してみるのも良いかもしれません。三項演算子についても「異論は認める」スタンスで、異なる意見を受け入れることが重要ですね。とはいえ、大げさになり過ぎることも注意しなければいけません。意見を募ることで、新たな視野を得られるかもしれません。 異論という言葉が少し大げさに感じるかもしれませんが、異なる意見をただ捉えれば良いだけの話です。先ほどの話で、「参考演算子は悪い」という表現がありました。参考演算子に関して注意が必要な可能性があるということで、無視していいわけではありません。「参考演算子は悪へ導いている感じが強い」という印象があるようですが、一度考慮してみましょう。
「参考演算子」は別名「条件演算子」とも言われています。他にも「インラインif」という言葉もあります。例えば、y = condition ? true_value : false_value
という形で、インラインifとして動作します。この形が一行で表せるため、確かにインラインifと呼んでも良いかもしれません。
そして、多くのプログラミング言語では、疑問符とコロンの記号(? :
)が参考演算子として存在します。他の参考演算子がある言語は私も知らないのですが、もしあるとすれば面白いかもしれません。
「参照等価性」という言葉も出てきましたが、プログラムにおける参照等価性とは、ある式がその値に置き換えても、プログラムの振る舞いが変わらないことを指します。これは副作用がない関数に当てはまる概念です。参照等価性とは、入力が同じならば出力も必ず同じになることを意味していると言えます。
また、参照という言葉が指しているものが何であり、どういった状態になれば等価であるとされるのか気になるところです。このように考えを巡らせていくことで、プログラミングの理解が深まるのではないでしょうか。 透明ではなく明瞭に、インプットに対してアップは必ず決まるという雰囲気を感じます。これを訳すときに「参照等価性」と訳したりします。透明でなく明瞭であることを「参照明瞭性」と言うのですが、「参照」という言葉にはもう少し工夫が必要かもしれませんね。
さて、リピーターに戻ります。参考演算子は参照等価性を提供しています。条件式に何を置くかや、その条件式が真や偽の場合に何を置くかによって、透明性は変わってきます。ここに関数を置くこともできますが、その関数が煩雑に感じられることもあります。条件演算子の中で、「?」と「:」が組み合わされていると、条件が複雑になると判断が難しくなりますね。
演技場開設式以外にAに代入できない言語も存在します。Swiftもその一つです。これに関してはJavaやJavaScriptも同様で、柔軟な言語ではないため、特定のパターンに依存しがちです。ただ、状況によってはこのような制限が必要になることもあります。
複雑な式で参考演算子を使用すると、単に分かりにくくなります。これによって一部のプログラマーは使用を避けることもあるでしょう。一画面プログラミングが流行していた頃、参考演算子のような機能はなかったですが、似たような方法で多くの処理を一つの画面に収める工夫がなされていました。
参考演算子の使用は、記号が組み合わさると厄介で、オプショナルチェーニングなどが混ざると「?」の意味が曖昧になることがあります。このように記号がぶつかると、読みづらくなりがちです。
演算子に優先順位があるのですが、これは間違えてもコンパイル時にエラーが出るので大丈夫です。しかしながら、読みやすさを保つためには優先順位を明記することが建設的だと思います。
今回、参考演算子の使用をあまりおすすめしないという意見に触れましたが、逆におすすめしたい記事もあるので、次回はそれを取り上げたいと思います。
今日のところはこれで終わりにしますね。お疲れ様でした。ありがとうございました。