クロージャ式の省略形

クロージャ式の省略形

Swiftにおいてクロージャ式は多用されるので、さまざまな省略形が用意されています。基本的な省略形を見ていきましょう。

引数の型と戻り値の型を省略する

クロージャ式の引数と戻り値の型には推論が働くので、型が推測できれば、引数と戻り値の型(上記の例ではInt)は省略可能です。前述の例は、宣言時に型アノテーションすることで、引数の型と戻り値の型の両方を省略できます。

リスト7:引数の型と戻り値の型を省略

let sum: (Int, Int) -> Int = {(num1, num2) in
    return num1 + num2
}

上記の例の場合、型アノテーションなしでも、戻り値の型から引数の型が推測できるので、引数の型は省略できます。

リスト8:戻り値の型があれば引数の型を省略できる

let sum = {(num1, num2) -> Int in
    return num1 + num2
}

同様に引数の型を指定すれば、戻り値の型は省略できます。

リスト9:引数の型があれば戻り値の型を省略できる

let sum = {(num1:Int, num2:Int) in
    return num1 + num2
}

処理が一つの場合returnは省略可能

クロージャ式内のステートメントがreturn文の1行のみの場合には「return」は省略可能です

リスト10:処理が1行だけなら「return」を省略できる

let sum = {(num1, num2)->Int in
    num1 + num2
}

以下のように、全体を1行で記述しても構いません。

リスト11:1行で記述

let sum:(Int, Int) -> Int = {(num1, num2) in num1 + num2}

引数名を省略する

クロージャ内部では引数は順に$0、$1……という特別な変数名でアクセス可能です。この場合、引数名やinも省略できます。

リスト12:引数名を省略

let sum:(Int, Int) -> Int = {$0 + $1}

引数や戻り値がない場合の表記に注意

引数がない場合には、引数の型部分に「()」のみを記述します。次の例は「大吉」「吉」「凶」のいずれかの文字列をランダムに戻すクロージャの例です。

リスト13:引数がない場合の例

let uranai = {() -> String? in ["大吉", "吉", "凶"].randomElement()}
print(uranai()!) // -> 「大吉」「吉」「凶」のどれか

戻り値がない場合には、戻り値の型部分に「()」を記述します。次の例は単に「こんにちは」と表示するクロージャです。

リスト14:戻り値がない場合の例

let sayHello = {() -> () in print("こんにちは")}
sayHello() // -> 「こんにちは」

カウンタをクロージャ式で戻す

今回の連載の最初に、カウンタのクロージャを戻すcounterFactory()関数について説明しました。

リスト15:再掲counterFactory()関数

func counterFactory(initValue:Int) -> () -> Int {
    var num = initValue
    func counter() -> Int {
        num += 1
        return num
    }
    return counter
}

これまでの説明を踏まえて、counterFactory()関数の内部の関数をクロージャ式で記述すると次のようになります。

リスト16:クロージャ式を用いて記述する

func counterFactory(initValue:Int) -> () -> Int {
    var num = initValue
    return { num += 1; return num }
}

func文と比較して、よりシンプルに記述できることがおわかりいただけるでしょう。

クロージャ式の使い所

Swiftには、関数を引数にとる関数やメソッドが少なくありません。その場合、クロージャ式を引数にするとシンプルに記述できます。

map()メソッドを使用する

例えば配列(Array)には、各要素を順に処理して、結果を新たな配列として戻すmap()メソッドがあります。次のような形式で実行します。

let 新しい配列 = 元の配列.map(要素を処理する関数)

ここでは平成の年が格納されている配列heisei_yearsから、西暦の年の配列seireki_yearsを生成する例を示しましょう。map()メソッドの引数に、func文で定義した関数を渡すには次のようにします。

リスト17:map()メソッドの使用例

let heisei_years = [1, 27, 4, 25, 9, 30]
func toSeireki(year:Int) -> Int { // (1)
    return year + 1988
}
let seireki_years = heisei_years.map(toSeireki) // (2)
print(seireki_years)

リスト18:実行結果

[1989, 2015, 1992, 2013, 1997, 2018]

この例では(1)でtoSeireki()という名前の関数を定義していますが、これは(2)のmap()メソッドの引数として使用するので、名前は必要ありません。また引数としてしか使用しない関数を定義するのは無駄ですし、名前が衝突する可能性もあります。そこで、クロージャ式の出番となります。

まず、前述の例の、map()メソッドの引数にfuncで定義した関数の代わりに、クロージャ式を省略なしで使用すると次のようになります。

リスト19:クロージャ式を用いる例

let heisei_years = [1, 27, 4, 25, 9, 30]
let seireki_years = heisei_years.map({(year:Int)->Int // (1)
    in return year + 1988})
print(seireki_years)

型を省略する

上記のクロージャ式(1)を、さらにシンプルにしていきましょう。引数と戻り値の型はmap()メソッドで定義されているので省略可能です。型を省略すると次のように記述できます。

リスト20:型の省略

let seireki_years = heisei_years.map({year
    in return year + 1988})

return文を省略する

続いて、return文を省略すると次のように記述できます。

リスト21:return文も省略

let seireki_years = heisei_years.map({year in year + 1988})

引数名を省略する

さらに引数名を省略し、引数を$0でアクセスしてみましょう。

リスト22:引数名も省略

let seireki_years = heisei_years.map({$0 + 1988})

後置記法にする

クロージャ式を関数の最後の引数として渡す場合には、関数呼び出しの()の後にクロージャ式を置くことができます。これを「後置記法」(Trailing Closures)と呼びます。

リスト23:後置記法

let seireki_years = heisei_years.map(){$0 + 1988}

後置記法では、関数やメソッドにクロージャの他に引数のない場合には関数名の後の()も省略できます。

リスト24:関数名の後のカッコも省略

let seireki_years = heisei_years.map{$0 + 1988}

省略前に比べると、すっきりシンプルになりました。

filter()メソッドを使用する

配列には、map()メソッドの仲間として、条件に一致する要素のみを抽出するfilter()メソッドが用意されています。filter()は。各要素に引数で指定した関数を実行し、その結果が「true」の要素のみを取り出して新たな配列として戻すメソッドです。例えば、前述の配列seireki_yearsから、2000年以降の年を取り出して配列over2000yearsを生成するには次のようにします。

リスト25:filter()メソッドの例

let over2000year = seireki_years.filter{$0 >= 2000}
print(over2000year)

リスト26:実行結果

[2015, 2013, 2018]

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored

ClickHouse Cloudが実現した広告運用SaaS「ATOM」のデータ基盤革新、パフォーマンスを向上しながら、運用負荷とコストを削減 11月11日 6:20 AIで開発が加速する時代、品質保証はどう変わる? Tricentisが示すAIエージェント活用の実像 11月9日 6:45 悪用までの猶予が「1分」に迫るフロンティアAI時代に開発と本番を貫く脆弱性管理が必要 10月29日 8:30 欧州CRA対応とSBOM運用。AI生成コードのOSS混入問題の対策とは ――スニペット単位で検出する「FossID」「Insignary Clarity」によるSBOM運用 9月16日 6:40 PostgreSQLからTiDBへ、稼働中SaaSで進める段階的DB移行の実践と再設計への展望 9月7日 6:30 機能安全開発におけるGoogleTestの活用を支援!「Parasoft C/C++test CT」で実現する効率化&AI連携 4月14日 6:30 【CNDW2025】Grafanaが明かす「オブザーバビリティの哲学」ー最小限の労力で実用的なインサイトを得るには 1月23日 6:30 【CNDW2025】プロダクト急増に備える基盤刷新 ーウェルスナビがECSからEKSへの移行で得た知見とは 1月15日 6:30 【CNDW2025】250環境を5人で運用、構築時間は30分に ーKINTOテクノロジーズが語るインフラ基盤組織の作り方 2025年12月18日 6:30 新たな自動化で熱視線! AIエージェントの「推論能力」を支える2つのコンポーネントとは? 2025年11月28日 6:30