如何测试函数和闭包的相等性?

97

5
据我所知,您也无法检查元类(例如 MyClass.self)的相等性。 - Jiaaro
1
多播闭包,就像C#中的那样。它们在Swift中必然更丑陋,因为你不能重载(T, U)“运算符”,但我们仍然可以自己创建它们。然而,由于无法通过引用从调用列表中删除闭包,我们需要创建自己的包装类。这很麻烦,也不应该是必要的。 - user652038
2
很棒的问题,但完全不同的事情是:你在 å 上使用变音符号来引用 a 的用法真的很有趣。你在这里探索的是一种约定吗?(我不知道我是否真的喜欢它;但它似乎非常强大,特别是在纯函数式编程中。) - Rob Napier
3
@Bill 我正在将闭包存储在数组中,但无法使用indexOf({$0 == closure}来查找和删除它们。现在我必须重构我的代码,因为我认为这是糟糕的语言设计导致的优化问题。 - Zack Morris
@ZackMorris,我有一个封装的字典,用于解决我在这里描述的问题:http://stackoverflow.com/questions/37155530/how-to-make-a-collection-of-blocks-in-swift - Omegaman
显示剩余3条评论
11个回答

0

我知道我回答这个问题已经晚了六年,但我认为看一下问题背后的动机是值得的。提问者评论道:

如果不能通过引用从调用列表中删除闭包,那么我们需要创建自己的包装器类。这很麻烦,也不应该是必须的。

所以我猜这位提问者想要维护一个回调列表,像这样:

class CallbackList {
    private var callbacks: [() -> ()] = []

    func call() {
        callbacks.forEach { $0() }
    }

    func addCallback(_ callback: @escaping () -> ()) {
        callbacks.append(callback)
    }

    func removeCallback(_ callback: @escaping () -> ()) {
        callbacks.removeAll(where: { $0 == callback })
    }
}

但是我们不能这样写removeCallback,因为==对于函数不起作用(===也不行)。

以下是另一种管理回调列表的方法。从addCallback返回一个注册对象,并使用该注册对象来删除回调。在2020年,我们可以使用Combine的AnyCancellable作为注册对象。

修改后的API如下:

class CallbackList {
    private var callbacks: [NSObject: () -> ()] = [:]

    func call() {
        callbacks.values.forEach { $0() }
    }

    func addCallback(_ callback: @escaping () -> ()) -> AnyCancellable {
        let key = NSObject()
        callbacks[key] = callback
        return .init { self.callbacks.removeValue(forKey: key) }
    }
}

现在,当您添加回调时,您不需要将其保留以便稍后传递给removeCallback。没有removeCallback方法。相反,您保存AnyCancellable,并调用其cancel方法来删除回调。更好的是,如果您将AnyCancellable存储在实例属性中,则在销毁实例时它将自动取消。

我们需要这个的最常见原因是为了管理发布者的多个订阅者。Combine可以解决这个问题,而不需要所有这些。C#允许我们查找两个闭包是否引用相同的命名函数,而Swift则不行。这也很有用,但发生的频率要少得多。 - user652038

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接