※この記事は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 }
みたいな形。
けっこうよく見かける形。可読性がよくなる。