swift:将函数类型赋给变量

时间:2022-01-10 16:55:48
    struct System {
        var method: (() -> ())?
        var curMethod: Int

        init() {
            method = nil
curMethod = 0
        }

        mutating func method1() {
            curMethod = 1
        }

        mutating func method2() {
            curMethod = 2
        }
    }

    var sys = System()
    sys.method = System.method1
    sys.method!()

I get an error cannot assign value of type (inout System) -> () -> ()' to type '(() -> ())?. What am I doing wrong?

我得到一个错误,不能分配类型的值(inout系统) - >() - >()'来键入'(() - >())?我究竟做错了什么?

2 个解决方案

#1


1  

First of all, your line sys.method = System.method1 is wrong, as it would require method1 to be a static function (like a class function) rather than an instance function, so it should be changed to sys.method = sys.method1. But this isn't allowed - the error is "error: partial application of 'mutating' method is not allowed".

首先,你的行sys.method = System.method1是错​​误的,因为它需要method1是一个静态函数(比如一个类函数)而不是一个实例函数,所以它应该改为sys.method = sys。方法1。但这是不允许的 - 错误是“错误:不允许部分应用'变异'方法”。

If you make System a class (rather than a struct), it will work if you replace the System.method1 with sys.method1.

如果将System设为类(而不是结构),则在使用sys.method1替换System.method1时它将起作用。

The reason for this is that a mutating func is actually quite a lot more than a simple function under the hood - it is a curried function (curried with a compiler generated function) that effectively creates a new copy of the struct with the "new" value - hence, you A) can't access it it directly ("partial application is not allowed") and B) you can't assign it to a ()->() variable.

这样做的原因是,变异函数实际上远远超过了一个简单的函数 - 它是一个curried函数(用编译器生成的函数计算),它有效地创建了一个带有“new”的结构的新副本。值 - 因此,你A)不能直接访问它(“不允许部分应用程序”)和B)你不能将它分配给() - >()变量。

#2


0  

So, there're 3 variants suggested by participants. Everything is working, and using class instead of struct seems to me less complicated.

因此,参与者建议有3种变体。一切正常,使用类而不是结构对我来说似乎不那么复杂。

struct System1 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

struct System2 {

    var method: ((inout System2) -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func callCurrentMethod() { method?(&self) }
    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

class System3 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    func method1() { curMethod = 1 }
    func method2() { curMethod = 2 }

}

var struct1 = System1()
var struct2 = System2()
var class1 = System3()

print(struct1.curMethod)
let curried = System1.method1
let unsafe = curried(&struct1)
unsafe()
print(struct1.curMethod)

print(struct2.curMethod)
struct2.method = { $0.method1() }
struct2.callCurrentMethod()
print(struct2.curMethod)

print(class1.curMethod)
class1.method = class1.method1
class1.method!()
print(class1.curMethod)

#1


1  

First of all, your line sys.method = System.method1 is wrong, as it would require method1 to be a static function (like a class function) rather than an instance function, so it should be changed to sys.method = sys.method1. But this isn't allowed - the error is "error: partial application of 'mutating' method is not allowed".

首先,你的行sys.method = System.method1是错​​误的,因为它需要method1是一个静态函数(比如一个类函数)而不是一个实例函数,所以它应该改为sys.method = sys。方法1。但这是不允许的 - 错误是“错误:不允许部分应用'变异'方法”。

If you make System a class (rather than a struct), it will work if you replace the System.method1 with sys.method1.

如果将System设为类(而不是结构),则在使用sys.method1替换System.method1时它将起作用。

The reason for this is that a mutating func is actually quite a lot more than a simple function under the hood - it is a curried function (curried with a compiler generated function) that effectively creates a new copy of the struct with the "new" value - hence, you A) can't access it it directly ("partial application is not allowed") and B) you can't assign it to a ()->() variable.

这样做的原因是,变异函数实际上远远超过了一个简单的函数 - 它是一个curried函数(用编译器生成的函数计算),它有效地创建了一个带有“new”的结构的新副本。值 - 因此,你A)不能直接访问它(“不允许部分应用程序”)和B)你不能将它分配给() - >()变量。

#2


0  

So, there're 3 variants suggested by participants. Everything is working, and using class instead of struct seems to me less complicated.

因此,参与者建议有3种变体。一切正常,使用类而不是结构对我来说似乎不那么复杂。

struct System1 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

struct System2 {

    var method: ((inout System2) -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    mutating func callCurrentMethod() { method?(&self) }
    mutating func method1() { curMethod = 1 }
    mutating func method2() { curMethod = 2 }

}

class System3 {

    var method: (() -> ())?
    var curMethod: Int

    init() {
        method = nil
        curMethod = 0
    }

    func method1() { curMethod = 1 }
    func method2() { curMethod = 2 }

}

var struct1 = System1()
var struct2 = System2()
var class1 = System3()

print(struct1.curMethod)
let curried = System1.method1
let unsafe = curried(&struct1)
unsafe()
print(struct1.curMethod)

print(struct2.curMethod)
struct2.method = { $0.method1() }
struct2.callCurrentMethod()
print(struct2.curMethod)

print(class1.curMethod)
class1.method = class1.method1
class1.method!()
print(class1.curMethod)