 # Unbound reference to mutating method

When writing mutating / non-mutating method pairs, one generally implements the mutating version to avoid extraneous allocations, then makes the non-mutating version call it. The bodies of the non-mutating versions are nearly identical, for example see these arithmetic operators of a `Matrix` implementation:

``````extension Matrix {
static func + (lhs: Matrix, rhs: Matrix) -> Matrix {
var result = lhs
result += rhs
return result
}

// repeat with - for subtraction
// repeat with .* for elementwise multiplication
// repeat with ./ for elementwise division
// repeat with +, -, *, and / for matrix-scalar arithmetic
}
``````

In an effort to reduce this boilerplate, I spun off a helper function:

``````func outOfPlace<T, U>(_ t: T, _ f: (inout T, U)->(), _ u: U) -> T {
var result = t
f(&result, u)
return result
}
``````

Which turned the non-mutating operators into one-liners:

``````extension Matrix {
static func + (lhs: Matrix, rhs: Matrix) -> Matrix { outOfPlace(lhs, +=, rhs) }
static func - (lhs: Matrix, rhs: Matrix) -> Matrix { outOfPlace(lhs, -=, rhs) }
static func .* (lhs: Matrix, rhs: Matrix) -> Matrix { outOfPlace(lhs, .*=, rhs) }
static func ./ (lhs: Matrix, rhs: Matrix) -> Matrix { outOfPlace(lhs, ./=, rhs) }
static func + (lhs: Matrix, rhs: Element) -> Matrix { outOfPlace(lhs, +=, rhs) }
static func - (lhs: Matrix, rhs: Element) -> Matrix { outOfPlace(lhs, -=, rhs) }
static func * (lhs: Matrix, rhs: Element) -> Matrix { outOfPlace(lhs, *=, rhs) }
static func / (lhs: Matrix, rhs: Element) -> Matrix { outOfPlace(lhs, /=, rhs) }
}
``````

That worked quite well, so I attempted to use similar helpers for more things. The unary negation operator seemed like a prime candidate:

``````static prefix func - (m: Matrix) -> Matrix {
var result = m
result.negate()
return result
}
``````

So I wrote another helper:

``````func outOfPlace<T>(_ f: (inout T)->()->(), _ t: T) -> T {
var result = t
f(&result)()
return result
}
``````

However, when I tried to call it, there was an error:

``````static prefix func - (m: Matrix) -> Matrix {
outOfPlace(negate, m)
// error: Partial application of 'mutating' method is not allowed
}
``````

Is there any way around this?

I don’t actually want to partially-apply `negate` here, I want to call it immediately upon binding a value to it. I would, in fact, prefer if the type of `Matrix.negate` were `(inout Matrix)->()` instead of `(inout Matrix)->()->()`.

Are there any plans to allow partial application of mutating methods in the future?

If not, I would like to raise the possibility of flattening the type of unbound mutating methods. This would be entirely source-compatible, since unbound mutating methods are currently disallowed. (We get the same error for “`let f = Matrix.negate`”.)

In the general case, with more parameters and a return value, the flattened version would work like this:

``````struct Foo {
mutating func bar(x: Int) -> String {
return "whee"
}
}

let f = Foo.bar     // (inout Foo, Int) -> String
var x = Foo()
let w = f(&x, 1)    // "whee"
``````

Is this potentially reasonable and feasible?

2 Likes