函数正在调用但未执行



我有这个自定义运算符:

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}

用法:

optional ?> {
print("executing")
}

问题是,当lhs为零时,闭包不会执行。在控制台中,"lhs is nil"正在打印,但之后没有"执行"正在打印。如何执行"lhs is nil"打印语句但不执行rhs

导致这种行为的是@autoclosure,如果您删除它,它可以正常工作。

这是因为@autoclosure会将您的闭包包装成闭包,所以现在您有这样的东西:

{ { print("executing") } }

外闭合返回Any,对吧?因此,它只会返回闭包{ print("executing") }而不执行任何其他操作。

如果要保留@autoclosure,可以这样使用运算符:

optional ?> print("executing")

解决方案似乎是使用完全相同的签名向运算符添加重载,除了它没有@autoclosure注释,并且两者的rhs都必须返回Void而不是Any

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Void) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
func ?> (lhs: Any?, rhs: ()->Void) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}

这样,如果我这样做:

optional ?> doSomething()

@autoclosure将被调用,无论doSomething()是否返回任何内容。

如果我这样做:

optional ?> {
doSomething()
doSomethingElse()
}

没有@autoclosure的那个将被调用,因为闭包的类型是()->Void.

您需要在闭包方法的末尾添加(),如下所示

optional ?> {
print("executing")
}()

如果您打算运算符后添加大括号,则可以将其实现(无需将rhs声明为自动闭包(:

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
var myString: String? = ""
// some case that made "string" to be nil...
myString = nil
myString ?> {
print("executing")
}

但是,声明自动闭包的目的是包装作为参数传递给函数的表达式:

这种语法便利性允许您省略函数 参数,通过编写普通表达式而不是显式表达式 关闭。

官方 Swift 文档 - 关闭、自动关闭

这意味着不需要大括号,这在与操作员一起工作时应该更自然:

infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
var myString: String? = ""
// some case that made "string" to be nil...
myString = nil
// you could use your operator like:
myString ?> print("executing")

但是等等!

可能会面临一个问题是:如果在运算符之后添加一段代码怎么办?

好吧,毫无疑问,您必须添加大括号:

let doSomething = {
print("executing")
print("second line of execution")
print("third line of execution")
}
myString ?> doSomething()

最新更新