本日は Swift の
演算子
の大まかな 3 つのスタイルについての話をしていきますね。演算子の置き方みたいな話、馴染みあるようであまり着目して見ていく機会もあまりないと思うので、この機にゆっくり眺めてみましょう。よろしくお願いしますね。————————————————————————————
熊谷さんのやさしい Swift 勉強会 #318
00:00 Start
00:10 今回の展望
01:27 演算子に関する専門用語
02:01 四項演算子って存在する?
03:46 各種演算子を書いてみる
05:24 タプルスプラット
11:40 タプルスプラットを自分の関数で活用できる?
15:48 各種演算子の記載方法
17:03 三項演算子を if 式で書き換えてみる
19:12 三項演算子は読みにくいのか
19:58 if 文だと評価基準が変わるのが気になる
21:46 Unary, Binary, Ternary
22:28 符号に作用する単項演算子
24:44 前置演算子と後置演算子
27:15 中置演算子
28:18 三項演算子は特殊な立ち位置
29:35 クロージングと次回の展望
————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #318
今日はSwiftの基本的な演算子について説明します。今まではC言語を参考に、いくつかの改善が施されてきました。C言語にない便利な機能を追加したり、オーバーフロー演算子などが用意されていましたね。
今回の章では、Swiftの一般的な演算子について紹介します。この章の内容としては、演算子自体の基本について詳しく述べられていて、Advanced Operatorsという章で、独自演算子の定義や、独自型に対する標準的な演算子の実装など、より応用的な内容が後ほど取り上げられます。まずは基本的な演算子に焦点を当てて、その基礎を学びましょうという流れです。
さて、演算子には単行演算子、二項演算子、三項演算子の3つの種類があります。四項演算子のようなものはないですね。試しに調べてみましたが、やはり存在しないようです。
単行演算子、二項演算子、三項演算子の違いについては、まず演算をする対象とそれに対する演算という形で考えるとわかりやすいですね。演算対象が1つなら単行演算子、2つなら二項演算子、3つなら三項演算子です。四項演算子というものは存在しないということで良いでしょう。
演算子と関数の違いについてですが、引数が1つの関数、2つの関数、3つの関数といった形で、プログラムを書く際に引数の数に応じて使い分けます。しかし、実際のところ、昔のSwiftではタプルという扱いをしており、タプルスプラットのような使い方もありました。この機能はコンパイラーの複雑さ増大の懸念から廃止されましたが、本質的な違いはあります。
たとえば、
action
という関数を考えてみましょう。この関数が二つの整数を受け取り、結果を返す場合、引数をそれぞれ渡して機能させることができます。このようにして、Swiftの関数や演算子の基本的な部分を理解していきましょう。 引数リストとアプリを同じように見立てて渡せる言語もあるようですが、Swiftでは直接は渡せないことが多いですね。ただ、特定の場面ではタプル展開が許されているので、その性質をうまく活用するとAPIの設計が変わるかもしれません。例えば、タプルの要素数が一致していると、関数呼び出しの際に適切に処理されることがあります。このようにタプル展開が使える場所というのは限られているため、覚えておくと便利です。ただし、タプル自体を頻繁に使うことは少ないかもしれませんし、特にジェネリクスを介さないといけない場面では少し複雑になることがあります。ジェネリクスを使って型を扱う場合でも、例えばマップ関数のように型を強制して扱うことで、特定の型の要素に対する操作が行えます。
また、Swiftにおけるジェネリクスを活用するときは、型パラメータを適切に設定すれば、例えば特定の条件を確認するプリディケートを作ったり、様々な型に対して同じ操作が行える関数を定義したりできます。しかし、すべてのケースでこのような方法が有効ではないこともあり、特にオプショナル型や複雑な型の組み合わせでは注意が必要です。
このような言語機能は、実際のプログラム設計やAPI提供の場面で、柔軟に対応できる可能性がありますが、何が重要かを見極め、それをどう活用できるか考えることが大切ですね。 タプルスプラットの動きについて話していますが、吉野にアプリを渡す際の条件によって、その動きが変わるようです。このセッションでは参考演算子の話に戻ります。参考演算子について、例えば
A
が 1、B
が 2、C
が 7という値だったとき、参考演算子を使うと結果はマイナス1になります。この参考演算子は、A
が 1なら B
を、そうでなければ C
を選びます。現在、A
が 1なので、選ばれるのは B
の 2です。この状態でもし A
が 1でないとしたら、A
が 0であった場合には、計算は異なる結果を示します。例として、A
が 0のときにどうなるかを考えてみました。条件式は少し複雑になりがちです。
A
が 0であれば B
を選び、そうでなければ C
もしくはマイナス1のような表現が可能です。しかし、式が複雑になると読みやすさが損なわれてしまいます。このような場合、分かりやすくするために条件式を一つずつ細かく書き出すと良いかもしれません。A
が 0であれば B
で、そうでないとしたら B
が 0であれば C
、それ以外はマイナス1と書くと、一見すると少しわかりにくいかもしれません。しかし、ゆっくり読み進めれば理解は可能です。参考演算子の効果や評価方法をもう少し考察しましたが、使い方によっては複雑に見えることがあります。例えコードが短いとしても、見通しが悪ければ気持ち悪く感じることがあります。また、評価すべき変数がバラバラの場合は、将来的に管理しにくくなりそうだと不安に感じることさえあります。その場合は、条件式を再考したくなるものです。
最終的には、その状況に応じて適切な書き方を選択することが求められますが、無機質な変数名である
A
や B
では具体的なアドバイスに繋がりにくいかもしれません。それでも、リンゴとみかんを比較するのは理解できても、リンゴと家を比べるような変な結合の仕方は問題を引き起こす可能性があると警戒するわけです。参考演算子は便利なときもありますが、使いすぎると複雑さが増すことがあるため、特に複雑な条件の場合は
if
文で書くことをお勧めします。if
文で条件を整理することで、見直しやすさが向上します。次に、演算子についても整理しました。演算子には単項演算子(二項演算子とも呼ばれることもあります)があります。一般に単項演算子はユーナリーオペレーター、二項演算子はバイナリーオペレーター、三項演算子はターナリーオペレーターと呼ばれています。これらの用語が出てきたときに、何を指しているのかがわかれば理解しやすくなるかと思います。例としては、
-A
のような一つの対象を操作するものが単項演算子です。 Swiftでの演算子に関する話をしていました。マイナスAのような単項演算子について触れていますが、この部分は複数の言語に共通する概念であり、時には誤って A * -A
と書いてしまうこともあるかもしれませんが、単項のマイナスを使う方が一般的です。さらにSwiftではプラスの単項演算子として
+A
という表現も可能ですが、実際に見かけることは少ないかもしれません。用途としては数値の符号を強調することが想定されていますが、それほど頻繁に使われるわけではないようです。他には、ビックリマーク
!
を用いた否定演算子についても言及しています。ブーリアン値に対して使用されるもので、具体的には否定の意味を持ちます。また、Swift特有の強制アンラップのために使われる後置のビックリマークもあります。演算子の位置により用途が異なるケースの例ですね。続いて、前置と後置の演算子に関する簡単な説明も加えられました。特にC言語やC++ではおなじみの
++
演算子の前置と後置での違いが示されています。Swiftにおける同様の概念としては、プレフィックスオペレーター(前置演算子)、ポストフィックスオペレーター(後置演算子)、インフィックスオペレーター(中置演算子)が挙げられています。これらは演算子が現れる位置や利用方法で分類されています。また、三項演算子についても触れていましたが、Swiftでは三項演算子は条件演算子が唯一の例です。他の演算子では二項やそれ以下のものだけが許されます。
最後に少し次回への予告もありましたね。次回は、計算の裾野を広げていくような内容から始める予定だそうです。それでは、今日はここまでということでお疲れさまでした。ありがとうございました。


