Swift/文法

Swiftの制御構造には、以下のような特徴があります。
Swiftは、#if文、#guard文、#switch文 の3種類の分岐文( Branch Statements )を持ちます。
Swiftのif文は、与えられた条件に従って処理を切り替えます。
Swiftのif文では、条件式にBool型の値を渡します。ただし、Optional型を使用して条件を指定することもできます。Optional型は、値が存在する場合は非Optional型を保持し、値が存在しない場合はnilを保持します。
if文の条件式にOptional型を指定した場合、そのOptional型が値を持っているかどうかを判定することができます。Optional型がnilを保持している場合、条件式はfalseとして扱われます。Optional型が値を持っている場合、条件式はtrueとして扱われます。
以下は、Optional型を使用したif文の例です。
上記の例では、optionalValueがOptional型であり、値を持っている場合には、valueにその値を束縛します。Optional型がnilを保持している場合には、elseブロックが実行されます。
Swiftにおいて、#availableと#unavailableディレクティブを使用して、特定のプラットフォームのバージョンでのみ利用可能なコードを記述することができます。これにより、実行時にクラッシュする可能性のあるコードを回避できます。
これは、iOS、macOS、watchOS、tvOSなどの特定のバージョンに依存するAPIの使用をチェックするのに便利です。
以下は、iOS 15で新しく追加されたasync/awaitを使用する場合の例です。
if #available(iOS 15.0, *) {
} else {
}
例えば、iOS 14で廃止されたAPIを使用する場合、以下のように書くことができます。
Swiftのguard文は、条件式がfalseの場合に、else節で定義された処理を実行する文法です。guard文は主に、事前条件を確認して、前提条件を満たさない場合はエラーを投げるか、処理を中断する場合に使用されます。
guard文のelse節では、return文やthrow文を使って、処理を中断させる必要があります。これは、else節内で定義された変数や定数が、guard文の外側でも有効になっているためです。
また、guard文を使うことで、if-let文などよりも、コードの可読性を高く保ちながら、エラー処理やオプショナルバインディングを実行することができます。
CaseIterableは、Swiftのプロトコルで、列挙型を定義するときに実装することができます。このプロトコルを実装することで、列挙型のケースを配列として取得できるようになります。
例えば、以下のようなFruitという列挙型があるとします。
この列挙型にCaseIterableプロトコルを実装することで、以下のように全てのケースを配列として取得できます。
このように、CaseIterableを使うことで、網羅性をチェックすることができます。網羅性とは、すべての可能性をカバーしているかどうかを表します。例えば、以下のような関数があったとします。
この関数は、Fruit列挙型のすべてのケースを網羅していません。しかし、FruitにCaseIterableプロトコルを実装した上で、以下のように修正することで、すべてのケースを網羅することができます。
このように、CaseIterableを使うことで、列挙型のすべてのケースを配列として取得でき、網羅性をチェックすることができます。
Swiftの「パターン」とは、値を分解して特定の部分を取り出すために使用される仕組みです。 パターンを使用することで、Swiftは値をより正確に特定し、コードの可読性を向上させることができます。
以下では、主要なパターンについて解説します。
ワイルドカードパターンは、アンダースコア(_)で表されます。このパターンは、値を特定せずに、単にマッチさせたい場合に使用されます。たとえば、以下のように使用できます。
このコードでは、xがどの値でも、ワイルドカードパターンにマッチしています。
識別子パターンは、値が識別子として解決できる場合に使用されます。たとえば、変数名や定数名が識別子パターンになります。
このコードでは、識別子パターンがlet yであり、yがマッチする値をバインドします。
列挙型ケースパターンは、列挙型の値をマッチさせるために使用されます。例えば、以下のように使用できます。
このコードでは、列挙型ケースパターンが.redであり、colorがColor.redとマッチすることになります。
オプショナルパターンは、オプショナル型の値をマッチさせるために使用されます。たとえば、以下のように使用できます。
このコードでは、オプショナルパターンが.some(let x)であり、optionalValueが値を持つ場合は、その値がxにバインドされます。
式パターンは、式と一致するかどうかをテストします。例えば、変数の値が特定の範囲内にあるかどうかをテストする場合に使用できます。以下は、式パターンの例です。
この例では、valueの値が1〜5の範囲にある場合は2番目のケースが実行されます。式パターンは、範囲演算子を使用することができるため、数値や文字列などの比較に特に便利です。
タイプキャスティングパターンは、オブジェクトの型と一致するかどうかをテストします。タイプキャスティングパターンは、is演算子を使用してテストすることができます。以下は、タイプキャスティングパターンの例です。
この例では、animals配列の要素がDog型かCat型かをテストしています。is演算子を使用することで、Dog型かCat型かどうかを簡単にテストすることができます。
Swiftは、#for-in文、#while文、#repeat-while文の3種類の繰返し文( Loop Statements )を持ちます。
Swiftの for-in 文は、シーケンスやコレクションの要素を反復処理するために使用されます。
Swiftのwhile文は、指定された条件がfalseになるまで、ブロック内のコードを実行し続けます。 whileループは、条件がtrueになるまで一度も実行されない場合があるため、最初から条件がfalseであることがわかっている場合は、repeat-while文を使う方が適しています。
Swiftのrepeat-while文は、指定された条件がtrueの場合に繰り返し処理を実行するための制御構文です。この文は、最低1回の実行を保証します。whileキーワードの後に条件が続き、実行が続けられるかどうかを判断します。
条件式はBool型かBool型の式か、BooleanTypeプロトコルを実装する型でなければなりません。
条件式を書くときに使う論理演算子や比較演算子の仕様は下記のとおり。
条件式には、optional-binding-condition を取ることができます。 構文的には、変数宣言(あるいは定数宣言)に似ていますが、nilを取り得るOptional型で、コンディションリストの最後の式の値が条件式の評価対象になります。
スコープを抜けた時に、自動的に実行される処理の登録。
throws、rethrowsキーワードが指定されたメソッドは、try、try?、try!のいずれかを指定してコールする必要があります。
#throwsキーワードも参照のこと。
関数とクロージャは第一級関数であり、普通のオブジェクトと同じように変数に入れたり、関数の引数や戻り値として受け渡しできます。
Swift の関数の構文は、おおむね下記のようになります。
上述のような構文で関数を書く場合、関数の呼び出し側では、関数の引数には外部引数名(external parameter name)を指定しなければなりません。下記コード例では5行目のweightが外部引数です。
対して関数内部のみで使用できる引数名はローカル引数名(local parameter names)と呼ぶ。下記コード1行目のweightがローカル引数です。
関数の呼び出し側にて外部引数名を省略させるためには、宣言時の外部引数名に _ (アンダースコア)を記述します。単に記述しなかった場合、外部引数名とローカル引数名に同じ値を指定したものとみなされます。
Swiftには、既存の型に新しい機能を追加するExtension機能があります。
このように、SwiftのExtension機能を使用すると、既存の型に新しいメソッドを追加することができます。 これにより、標準ライブラリの型にカスタム機能を追加したり、コードの再利用性を高めたりすることができます。
Swiftでは中括弧{}で囲まれたコードブロックは事実上全てクロージャとなります。 このとき、引数・戻り値と、本体の処理の間に「in」を書くことで、この2つの部分を区別します。
クロージャの型が推論可能な場合等では、各種省略記法を使用できます。
関数の最後の引数がクロージャである場合、それを括弧の外に出すことができます。また、それが唯一の引数である場合は括弧そのものを省略できます。
クロージャでキャプチャする変数の宣言。weak、unownedを指定すると、保持されない参照になります。
Swiftでは任意の型に対して、既存の演算子をオーバーロードして独自の振る舞いを定義することができます。 なお = -> . // /* */ は予約されておりオーバーロードしたりカスタム演算子(後述)として定義することはできません。
Swift標準の定義済み演算子(+、*、%など)の他に、全く新しい演算子を定義することができます。新しく定義したカスタム演算子は、標準の演算子と同じように演算子オーバーロードを実装できます。