我有这个自定义运算符:
infix operator ?> : NilCoalescingPrecedence
func ?> (lhs: Any?, rhs: @autoclosure ()->Any) {
if lhs == nil {
print("lhs is nil")
rhs()
}
}
用法:
optional ?> {
print("executing")
}
问题是,当lhs
为nil时,闭包没有执行。在控制台" lhs是零"正在打印,但没有"正在执行"正在打印。如何" lhs是零" print语句已执行但不是rhs
?
答案 0 :(得分:2)
导致此行为的原因是@autoclosure
,如果删除它,则可以正常工作。
这是因为@autoclosure
会将你的闭包包装成一个闭包,所以现在你有这样的东西:
{ { print("executing") } }
外部封闭返回Any
,对吗?所以它只会返回闭包{ print("executing") }
而不做任何其他事情。
如果您想保留@autoclosure
,可以这样使用运营商:
optional ?> print("executing")
答案 1 :(得分:1)
解决方案似乎是为操作符添加了一个具有完全相同签名的重载,除了它没有@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
。
答案 2 :(得分:0)
您需要在闭包方法的末尾添加()
,如下所示
optional ?> {
print("executing")
}()
答案 3 :(得分:0)
如果您打算在运算符之后添加花括号 ,则可以实现它(无需将rhs
声明为autoclosure):
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")
}
然而,声明autoclosure的目的是包装一个作为参数传递给函数的表达式:
这种语法上的便利性可以省略函数的大括号 通过编写普通表达式而不是显式来创建参数 闭合。
The Official Swift Documentation - Closures,Autoclosures
这意味着不需要花括号,在使用操作符时应该更自然:
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()