structを使っていたら、
Partial application of 'mutating' method is not allowed
というエラーに遭遇しました。
僕の場合、原因は別件だったんですが、日本語情報があまりないエラーメッセージだったので、記事にしてみます。
僕のエラーの原因
僕の場合、
protocol aDelegate {
var aView: ViewClass
}
struct AStruct {
private weak var delegate: aDelegate?
private mutating func aFuncation() {
switch aView.aVariable { //この行で"Partial application of 'mutating' method is not allowed"
case .any
//any
default:
//any
}
}
}
という書き方をしたらこのエラーが出ました。
switch aView.aVariable
ここを
switch delegate?.aView.aVariable
とすればOKでした。
それで終わりなんですが、ついでなんでエラーメッセージの意味も調べてみました。
Partial application of 'mutating' method is not allowedってなんだ
Partial application
Partial applicationは、日本語にすると部分適用と訳される技術用語です。
関数型プログラミングっぽい用語で、日本語記事見ると、だいたいカリー化と一緒に紹介されている用語です。
複数の引数を持った関数に対して、普通は全変数に値を渡して、戻り値を得ます。
たとえば、f(a,b,c) = a + b + c という関数があったら、f(1,1,1) = 1 + 1 + 1 = 3 ですね?
これを部分適用だと、
f(a,b,c) = f(a, 1, 1) = f(a) + 2 = f(1) + 2 = 3
ただしf(a) = a, f(b, c) = b + c
みたいな計算ができます。
命令形言語使ってると、「何が嬉しいんだ……?」という気になりますが、
関数型言語だと関数が汎用的なので、利便性のために汎用性を減らしたいときがあるみたいです。
Partial application of 'mutating' method is not allowedの例
Partial application of 'mutating' method is not allowed
エラーメッセージでググったら一番上に出てくるのがこちらの記事。
struct MyStruct {
var count = 0
mutating func add(amount: Int) {
count += amount
}
}
var myStruct = MyStruct()
[1, 2, 3, 4].forEach(myStruct.add)
// Partial application of 'mutating' method is not allowed
想定している結果としては、1+2+3+4でcount=10となるのを想定していると思われます。
そもそもforEachの中にカッコ省略してメソッド書いて動くのか……?とかはあるんですが、とりあえず"Partial application of 'mutating' method is not allowed"でエラー。
記事の中でも動くコードの例は出てますが、下記でも動きます。
var count = 0
[1, 2, 3, 4].forEach({ amount in count += amount })
print(count) //10
なぜこれがエラーになるかというと、内部的には
myStruct.add(1)
↓
myStruct.add(2)
↓
myStruct.add(3)
↓
myStruct.add(4)
↓
myStruct.add(1,2,3,4) ※この関数の場合ここでは何もせず
という順番で処理する必要があり、これが部分適用になる訳ですね。
Swiftで部分適用?
Swiftで部分適用(カリー化)にある、
func addTwoNumbers(a: Int)(b: Int) -> Int {
return a + b
}
let add1 = addTwoNumbers(1)
add1(b: 2) //< 3
という書き方がその昔Swiftオフィシャルでできたらしいのですが、Swiftいくつからなのかは不明ですが、廃止されました。