Missing argument label in curried function


Swiftでは名前付きパラメタを関数に設定することができる。

func add3(#v1: Int, #v2: Int, #v3: Int) -> {
    return v1 + v2 + v3
}

add3(v1: 1, v2: 2, v3: 3) // -> 6

#でパラメタ名と同じラベルを自動的に生成してくれるので呼び出すときにはこれを各パラメタの前につけてあげればいい。

ちなみに名前付きパラメタを生成した場合は必須となるらしく、名前を指定せずに利用しようとするとエラーになる。
swift
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ラベルが必要みたい。結局どうしたらいいかはまだ分かっていません