LoginSignup
2
4

More than 3 years have passed since last update.

~個人メモ~ [swift] 関数・クロージャの基本的な仕様について

Posted at

※この記事はswift学習中の筆者のノートです。

ちょっと振り返りたい時に、都度本(swift実践入門)を開いて該当ページを探すのがめんどくさかったので簡単に纏めました。

関数

関数とは

"名前を持ったひとまとまりの処理"のことで、外部から処理を呼び出し実行することができる機能のことをいう。

定義方法

関数はfuncキーワードで宣言、そして関数名、引数、戻り値の型、文を定義する

func 関数名(引数名1: , 引数名2: , ...) -> 戻り値の型 {
  関数呼び出し時に実行される文
  必要に応じてreturn文で戻り値を返却
}

例:数値を2倍する関数

func double(number x: Int) -> Int {
    return x * 2
}

double(number: 150)      // 300

引数について

仮引数と実引数

  • 関数の定義時に宣言するもの・・・仮引数
  • 関数の呼び出し時に指定するもの・・・実引数
func printInt(_ int: Int) {
    print(int)
}
// 関数の定義時に宣言している'int'が仮引数

printInt(1)
// 関数の呼び出し時に指定している'1'がが実引数

外部引数名と内部引数名

  • 外部からの呼び出し時に使用するもの・・・外部引数名
  • 関数内で使用されるもの・・・内部引数名
func sample(外部引数名 内部引数名: ) {
    関数の内部では内部引数名を使用する
}

sample(外部引数名: )

外部引数名は省略することもできる。
その場合は関数の定義時に(_ 内部引数名: )のように外部引数名に_を使用する。
呼び出し時には、:も省略し、値のみの記述で呼び出す。

可変長引数

引数定義の末尾に...を加えることでArrey型となる。
(実引数が複数あっても配列として受け取ることができる)

func printStrings(strings: String...) {    
    for string in strings {
        print("\(string)")
    }
}

printStrings(strings: "abc", "def", "ghi")
// 実行結果
// abc
// def
// ghi

クロージャ

クロージャ(closure)とは

"名前を持たないひとまとまりの処理"のこと。
特徴的なのは名前が不要ということ型推論により省略可能範囲が広いということ変数に代入でき、クロージャをパラメータとして受け取ることができるということなどが挙げられる。

定義方法

クロージャ式と呼ばれる、処理を{}で囲むフォーマットで引数・戻り値の型・文を定義する。

{ (引数名1: , 引数名2: , ...) -> 戻り値の型 in
    実行される文
    必要に応じてreturn
}

例:数値を2倍するクロージャ

let double = { (x: Int) -> Int in
    return x * 2
}

double(2)    // 4

型推論

決まった型にクロージャを代入する場合は、型を省略できる。

// 型を省略しない場合
let double: (Int) -> Int

double = { (x: Int) -> Int in
    return x * 2
}

double(2)   // 4

// 型推論により省略した場合

let triple: (Int) -> Int

triple = { x in
    return x * 3
}

triple(2)   // 6

実行方法

定義した定数名+()内に引数をいれ実行する。
渡された引数に対して処理が実行される。

let lengthString = { (mozi: String) -> Int in
    return mozi.count
}

lengthString("文字数を知りたい")   // 8

ちなみに同じ処理を関数にするとこんな感じ

func lengthString2(mozi2: String) -> Int {
    return mozi2.count
}

lengthString2(mozi2: "mozisuuwosiritai")   // 16

クロージャの引数

関数の引数との違いは以下の通り

  • 関数 => 外部引数名と内部引数名がそれぞれ指定できる
  • クロージャ => 内部引数名のみ指定できる

すなわちクロージャの場合は()内には値のみ入るということ

また、クロージャではデフォルト引数も指定できない仕様となっている。

簡略引数名

クロージャでは簡略引数名を利用し、引数名の定義も省略することが可能である。
簡略引数名は$にインデックス番号をつける。
※型推論できない場合はコンパイルエラーとなる。

let array = [1,2,3,4,5]
let newArray = array.map { $0 * 5 }
// 配列の要素の1番目を $0 と表現している。
// mapメソッドの引数がクロージャ
// mapメソッドは要素を一つ一つ取り出して実行するから、取り出された要素は毎回一つ目の要素となる$0
// map( {() -> Int In return $0 * 5 } ) みたいな形が省略前の形と思う
newArray // [5, 10, 15, 20, 25]

変数と定数のキャプチャ

クロージャ自身が定義されたスコープの変数の値はreturn後も保持される.

let counter: () -> Int
do {
    var count = 0
    counter = {
        count += 1
        return count
    }
}

counter()  // 1
counter()  // 2

引数としてのクロージャ

クロージャを関数や別のクロージャとして利用する場合の仕様として、
属性トレイリングクロージャがある

属性は2種類

クロージャの型の前に、@属性名を追記して指定する

@escaping
関数に引数として渡されたクロージャが、関数のスコープ外で保持される可能性があることを示す属性
この属性が付与されているかどうかで、コンパイル時にクロージャがキャプチャを行うか判断される

@autoclousure
引数をクロージャで包むことで遅延評価を実現するための属性

トレイリングクロージャ

引数のクロージャを外に出すこと。
最後の引数がクロージャの場合のみ可能。

func hoge(A: Int, B: Int, Cl: () -> Int { 
    クロージャの処理 
})

のような関数を呼び出したい場合。

以下、呼び出し時

//通常
hoge(A: 1, B: 5, Cl: { Print(Int) })

//トレイリングクロージャ
hoge(A: 1, B: 5) { Print(Int) }

と書く事ができる

引数が一つだけの場合、()も省略でき、クロージャを外にだせる。
hoge { clouser }みたいな形。
けっこうよく見かける形。可読性がよくなる。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4