Loading
BLOG 開発者ブログ

2020年12月11日

クロージャの省略形について

swiftのクロージャでよくみる$0ってなんだろう?
勉強していて躓いたクロージャの省略の形式についてまとめました。

この記事は アイソルート Advent Calendar 2020 11日目の記事です。

 

こんにちは。モバイルソリューショングループのfujinami.mです。
iOSの開発に携わりたく、swiftを勉強していたときに躓いた点がありました。
それは、「$0ってなんだろう?」「コードを書く人によって、なんで書き方がこんなに違うんだろう…」
この疑問でした。
「$0」はよくクロージャの記載でよく見るのですが、初心者の私にはクロージャの省略形が全然わからず、コードを読んでもなかなか理解できなかったのです。
今回はそのクロージャの省略形について、どんな流れで省略されているのかをまとめました。

 

目次

 

はじめに

swiftのクロージャって慣れるまで読みにくいと思います。
例えば…

let division = { $0 / 2 }

print(division(40))

このような単純なコードでも、私のようなswift初心者でクロージャというものを知らなかった人には「なにか割ってるけど、$0はなにを指しているんだろう…」という状態になりました。

上の例は、元になる基本形から省略できるコードをどんどん省略していって簡単に記載したものになっているので、基本形もわからず読もうとすると理解しづらいと思います。
何をどのように省略していったものなのか、少しずつ流れに沿ってを例に書いていきます。

 

基本形

まず、定義の基本形は以下になっています。

{ (引数名: 引数型) -> 戻り値の型 in
    //ここで処理を実施
}

 

これを今回は「年齢から未成年かどうかのメッセージを返す処理」の例に当てはめて書いていきます。

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { (age: Int) -> String in
    let message: String
    if age < 20 {
        message = "未成年ですよ"
    } else {
        message = "成人してますよ"
    }
    return message
}

//クロージャを実行する
print(ageCheckMessage(29))

//実行結果
成人してますよ

少々無理やりですが、基本形に当てはめた状態と実行結果になります。
省略形がわからなくても何をしたいのか、どんな処理なのかはわかると思います。

 

少しずつ省略していく

では基本形に当てはめた処理を少しずつ省略していきたいと思います。
省略できるようにするには条件があったりするので、順番に処理を省略していこうと思います。

 

1.処理を一行に省略

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { (age: Int) -> String in
    return age < 20 ? "未成年ですよ" : "成人してますよ"   
}
//クロージャを実行する
print(ageCheckMessage(29))

//実行結果
成人してますよ

まず、省略をするにあたって、実行処理が1行の必要があるものがあるので実行処理自体を省略していきます。スコープ内での処理を三項演算子を使って一行にします。
分岐していた処理を省略してreturnで返すように処理を省略します。

 

2.returnを省略する

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { (age: Int) -> String in
    age < 20 ? "未成年ですよ" : "成人してますよ"
}

//クロージャを実行する
print(ageCheckMessage(26))

//実行結果
成人してますよ

処理が一行の場合、「return」を省略することが出来ます。
さっきまで明示的に「return」と記載した部分を省略します。

 

3.戻り値の型を省略する

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { (age: Int) in
    age < 20 ? "未成年ですよ" : "成人してますよ"
}

//クロージャを実行する
print(ageCheckMessage(26))

//実行結果
成人してますよ

型推論ができる場合は、型の表記を省略することが出来ます。
どういうことかというと、「(age: Int) -> String」の「-> String」の部分を省略することが出来ます。
少しずつよく見るクロージャの形式になってきました。

 

4.引数の()と型を省略する

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { age in
    age < 20 ? "未成年ですよ" : "成人してますよ"
}

//クロージャを実行する
print(ageCheckMessage(26))

//実行結果
成人してますよ

引数が一つの場合、()を外すことが出来ます。()を外し引数の型を省略します。
最初と比べると色々なものを省略することが出来ました。

 

5.引数自体を省略する

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = {
    $0 < 20 ? "未成年ですよ" : "成人してますよ"
}

//クロージャを実行する
print(ageCheckMessage(26))

//実行結果
成人してますよ

更に引数自体を省略することが出来ます。「age in」の部分を省略します。
この時に引数の1つ目を使いたい場合、「$0」として使用することが出来ます。
私が最初に疑問に思った「$0」とは、第一引数のことでした。
また、引数が2つ以上であれば、同様に「$1,$2,…」として使用することが出来ます。

 

最終的な形

最終的には以下のようなスッキリしたものになりました。

//年齢から、成人済みかのメッセージを返す
let ageCheckMessage = { $0 < 20 ? "未成年ですよ" : "成人してますよ" }

//クロージャを実行する
print(ageCheckMessage(26))

//実行結果
成人してますよ

 

最初の基本形と比べると色々なものが省略されていますが、経緯がわかると何をするのかよくわかりますね!

 

おわりに

今回は私がswiftに触れてみて最初にあたった壁、クロージャの省略形について書かせて頂きました。
最初は「$0」が何を指しているのかもわかりませんでしたが、省略していった流れがわかると
ただ覚えようとするより頭に入りやすいかなと思います。
同じように躓いている方の参考になれば幸いです。

 

明日は watanabe.t さんの「FirebaseとBigQueryの連携」です。

fujinamimのブログ