admin管理员组

文章数量:1122832

Consider the following code (see Compiler Explorer):

struct A {
    var data: Int
    mutating func setData(value: Int) -> Void {
        data = value
    }
}

func setA(a: inout A, setter: (inout A) -> (Int) -> Void) {
    setter(&a)(10)
}

var a = A(data: 0)
setA(a: &a, setter: A.setData)

This gives "error: cannot reference 'mutating' method as function value" when passing A.setData. A comment under this question says that this compiler error protects against shared mutable state of the struct. Since I do not bind an instance to the method, and an actual mutable (inout) version of A needs to be passed to setA, why is this the case?

A slight modification where I wrap the function in a lambda does work apparently (Compiler Explorer):

func setA(a: inout A, setter: (inout A, Int) -> Void) {
    setter(&a, 10)
}

var a = A(data: 0)
setA(a: &a, setter: {(a: inout A, i: Int) in a.setData(value: i)})

Consider the following code (see Compiler Explorer):

struct A {
    var data: Int
    mutating func setData(value: Int) -> Void {
        data = value
    }
}

func setA(a: inout A, setter: (inout A) -> (Int) -> Void) {
    setter(&a)(10)
}

var a = A(data: 0)
setA(a: &a, setter: A.setData)

This gives "error: cannot reference 'mutating' method as function value" when passing A.setData. A comment under this question says that this compiler error protects against shared mutable state of the struct. Since I do not bind an instance to the method, and an actual mutable (inout) version of A needs to be passed to setA, why is this the case?

A slight modification where I wrap the function in a lambda does work apparently (Compiler Explorer):

func setA(a: inout A, setter: (inout A, Int) -> Void) {
    setter(&a, 10)
}

var a = A(data: 0)
setA(a: &a, setter: {(a: inout A, i: Int) in a.setData(value: i)})
Share Improve this question asked yesterday user119879user119879 3611 silver badge7 bronze badges 1
  • 2 Might get knowledgeable response if posted on swift forums. – matt Commented yesterday
Add a comment  | 

1 Answer 1

Reset to default 1

This gets boiled down to the fact that you are doing A.setData.

If A was a class, that would return a curried function with a signature (A) -> (Int) -> Void. In order to use it you would need to pass an instance of A. Since A is a reference type you can pass any instance to it at any later point in time.

Now A is not a reference type but a value-type which obtains Swift's value-type semantics. Mutating methods modify self which is not possible without an instance and the compiler prevents the declaration of the curried function. If Swift allowed A.setData to be stored as (A) -> (Int) -> Void, what would it do when setter(a)(10) is called? Since setData modifies self, but a is a struct (a value, not a reference), setter(a)(10) would be working on a copy, not modifying a.

In your second example you are calling setData on an actual instance of A and there is no problem with that.

本文标签: swiftWhy can a mutating method of a struct not be passed as a function parameterStack Overflow