Swiftでは名前付きパラメタを関数に設定することができる。
func add3(#v1: Int, #v2: Int, #v3: Int) -> {
return v1 + v2 + v3
}
add3(v1: 1, v2: 2, v3: 3) // -> 6
#
でパラメタ名と同じラベルを自動的に生成してくれるので呼び出すときにはこれを各パラメタの前につけてあげればいい。
ちなみに名前付きパラメタを生成した場合は必須となるらしく、名前を指定せずに利用しようとするとエラーになる。
add3(1, 2, 3) // -> Missing argument labels 'v1:v2:v3' in call
Curried function
このことを踏まえると実はカリー化された関数では不思議なことが起きる。
先ほどの関数をカリー化する
func add3(#v1: Int, #v2: Int)(#v3: Int) -> Int {
return v1 + v2 + v3
}
add3(v1: 1, v2: 2)(v3: 3) // -> 6
名前つきパラメタを生成したくない場合は#を外してみるが、
func add3(v1: Int, v2: Int)(v3: Int) -> Int {
return v1 + v2 + v3
}
add3(1, 2)(3) // -> Missing argument label 'v3:' in call
エラーが出てしまう。どうやらv3
のラベルが必要なみたい。以下のように呼んであげると正しく動作する。
add3(1, 2)(v3: 3) // -> 6
どうやらカリー化された最後の呼び出し部分は勝手に名前付きパラメタにされてしまうらしい。これはつらい
どうしたらいいのか?
Advanced Swiftにクラスのinitializerを名前付き引数から解放する方法が載ってた。
普通は以下のようになる。
class SomeClass {
let v1: Int
let v2: Int
init(v1: Int, v2: Int) {
self.v1 = v1
self.v2 = v2
}
}
let sc = SomeClass(v1: 1, v2: 2)
でもinitializerに名前付き引数は要らないのでパラメタをダイレクトに渡したい場合は以下のようにする
class SomeClass {
let v1: Int
let v2: Int
init(_ v1: Int, _ v2: Int) { // _をつけてあげる
self.v1 = v1
self.v2 = v2
}
}
let sc = SomeClass(1, 2)
これがつかえないかとやってみた
func add3(v1: Int, v2: Int)(_ v3: Int) -> Int {
return v1 + v2 + v3
}
// -> Extraneous '_' in parmeter 'v3' has no keyword argument name
add3(1, 2)(3) // -> Missing argument label 'v3: in call
何故かWarningがでる。もともと名前付きパラメタじゃないから余分だよみたいなことを言われる。でもやっぱり呼び出すときはv3
ラベルが必要みたい。結局どうしたらいいかはまだ分かっていません