のほほん停留所

つぶやきのなりそこないの溜まり場

Swift3: カリー化

Swift3ではカリー化用のシンタックスが廃止されました。廃止には用途が限定的などの理由が挙げられていますが、たまに使うことがあるのでSwift3での記法のメモ書きです。

英語ですが廃止の詳しい理由は0002-remove-currying.mdに書かれています。

// Swift2
func curried(x: Int)(y: String) -> Float {
    return Float(x) + Float(y)!
}

curried(1)("2") // 3

// Swift3
func curried(_ x: Int) -> (String) -> Float {
    return {(y: String) -> Float in
        return Float(x) + Float(y)!
    }
}

curried(1)("2") // 3

ただカリー化された関数を使いたいときは上のコードでいけますが、ついでにカリー化の一般的な関数を定義してみました。

func curry<A, B, C>(_ function: @escaping (A, B) -> C) -> (A) -> (B) -> C {
    return {(a: A) -> (B) -> C in {
        (b: B) -> C in
            function(a, b)
        }
    }
}

func plus(x: Int, y: String) -> Float {
    return Float(x) + Float(y)!
}

curry(plus)(1)("2") // 3

これで特定の関数をカリー化せずに、使う際にcurry関数に関数を渡してあげると使えます。ただ、上のコードでも分かる通り、定義したcurry関数は引数を2つしか取れないので、引数が3つや4つになるときは都度定義する必要があります。