1-6 クロージャの基本的な使用法
クロージャは、名前を持たない無名の関数のようなものです。
クロージャは、変数や引数に代入することができ、関数の戻り値としても使用できます。
また、クロージャは、無名関数(むめいかんすう)とも呼ばれます。
![](https://programmerrikochan.com/wp-content/uploads/2023/07/cropped-cropped-IMG_5515.jpg)
クロージャとか、無名関数とかって言われると身構えるけど、
関数みたいなもので、関数とちょっと書き方が違って、
関数よりスマートで直感的に書くことができるものです。
つまり、クロージャとは、「関数の書き方の一種」です。
クロージャの基本構文
let クロージャの名前: () -> 返り値 = {
// 処理
// returnがある場合は、ReturnTypeに合わせて返り値を記述
}
関数の構文とほとんど同じですね。
それでは、関数の書き方と、クロージャの書き方を比べて見てみましょう。
是非、実際に操作しながら学んでいきましょう。
以下でSwiftのブラウザ実行環境が使えます。 print()で出力される文字を確認してみましょう。https://paiza.io/ja/projects/new
関数の構文
func person(name: String, age: Int) -> String {
return "こんにちは \(name)です。 年齢は \(age) 歳です。"
}
// 関数の呼び出し
let message = person(name: "RIKO", age: 26)
print(message) // こんにちは RIKOです。 年齢は 26 歳です。
クロージャの構文
let person: (String, Int) -> String = { name, age in
return "こんにちは \(name)です。 年齢は \(age) 歳です。"
}
// クロージャの呼び出し
let message = person("RIKO", 26)
print(message) // こんにちは RIKOです。 年齢は 26 歳です。
以下のようにpersonという変数を定義せずに、直接呼び出すこともできます。
let message = { (name: String, age: Int) -> String in
return "こんにちは \(name) です。 年齢は \(age) 歳です。"
}("RIKO", 26)
print(message) // こんにちは RIKOです。 年齢は 26 歳です。
関数 と クロージャ の違い
func キーワードの有無
- 関数は func キーワードを使って宣言されます
- クロージャはそのようなキーワードがありません
名前の有無
- 関数は名前を持ち、呼び出す際にはその名前を使用します
- クロージャは無名(名前がない)か、変数や定数に代入されたときに名前がつくこともあります
簡略構文
- クロージャでは、引数や戻り値の型を省略したり、簡略構文($0 など)を使用したりできることがあります
クロージャは、関数と形では似ていますが、クロージャは関数の特別な書き方であり、関数よりコンパクトな書き方ができるのです。
では、クロージャの書き方について更に詳しく見ていきましょう。
クロージャ の いろいろな書き方
// 完全な構文 (省略しないクロージャの構文)
let add: (Int, Int) -> Int = { (a: Int, b: Int) -> Int in
return a + b
}
print( add(3, 4) ) // 7
// 型省略の構文 (クロージャの戻り値の型を省略)
let add: (Int, Int) -> Int = { a, b in
return a + b
}
print( add(3, 4) ) // 7
// 色々省略した構文 (引数も戻り値も省略)
let add: (Int, Int) -> Int = { $0 + $1 }
print( add(3, 4) ) // 7
一応、関数の書き方もおさらい(クロージャじゃないよ)
func add(_ a: Int, b: Int) -> Int {
return a + b
}
print( add(3, 4) ) // 7
上記のプログラムは、全て同じことをやっています。
![](https://programmerrikochan.com/wp-content/uploads/2023/07/cropped-cropped-IMG_5515.jpg)
難しいですよね。クロージャーで省略することを覚えると、難しいことができるようになった!と思って、使いたくなると思います。
私も、覚えたての時に、イキって
let add: (Int, Int) -> Int = { $0 + $1 }
この書き方をよく使っていましたが、
先輩から、「僕の好みですが、この書き方は、パッと見なにやってるか分かりずらいです。可読性を意識した時に、何が相応しいか見直しましょう」
というコメントをもらったことがあります。
コードをチェックしてくれるレビュアーや、今後、このコードを読み解く人のためにも、可読性を意識したコードを書きたいと思いました。
例えば、配列を扱う際のクロージャも、以下のように省略することができます。
let numbers = [1, 2, 3, 4, 5]
// 各要素を2倍にするクロージャ
let doubled = numbers.map({ (number: Int) -> Int in
return number * 2
})
print(doubled) // [2, 4, 6, 8, 10]
let numbers = [1, 2, 3, 4, 5]
// 型省略の構文 (クロージャの戻り値の型を省略)
let doubled = numbers.map({ number in
return number * 2
})
print(doubled) // [2, 4, 6, 8, 10]
let numbers = [1, 2, 3, 4, 5]
// 引数・戻り値型の省略と$0の利用
let doubled = numbers.map { $0 * 2 }
print(doubled) // [2, 4, 6, 8, 10]
まとめ
- クロージャは「無名関数」(名前を持たない関数) である
- クロージャは、省略した書き方ができる
![](https://programmerrikochan.com/wp-content/uploads/2023/07/cropped-cropped-IMG_5515.jpg)
仕事で、ソースコードを読んでいると、クロージャがたくさん登場します。
クロージャの書き方を習得していなくても、動くプログラムは書けますが、
ソースコードを読んでいるとクロージャが頻繁に出てくるので、「こういう書き方がある!」というのは知っておくと良いと思います。
ドリル
// 完全な構文 (省略しないクロージャの構文)
let fullName: (String, String, Int) -> String = { (firstName: String, lastName: String, age: Int) -> String in
return "私の名前は、\(lastName) \(firstName)。\(age)歳です。"
}
print(fullName("ジョブズ", "スティーブ", 56))
// 型省略の構文 (クロージャの戻り値の型を省略)
let fullName: (String, String, Int) -> String = { firstName, lastName, age in
return "私の名前は、\(lastName) \(firstName)。\(age)歳です。"
}
print(fullName("ジョブズ", "スティーブ", 56))
// 色々省略して$0などを利用する構文 (引数も戻り値も省略)
let fullName: (String, String, Int) -> String = { "私の名前は、\($1) \($0)。 \($2)歳です。" }
print(fullName("ジョブズ", "スティーブ", 56))
メモ
![](https://programmerrikochan.com/wp-content/uploads/2024/01/IMG_9378-1024x810.jpg)