Swift是否有空合并运算符?如果没有,自定义运算符的示例是什么?
许多语言中的一个常见功能是二进制运算符,通常用于缩短以下类型的表达式:Swift是否有空合并运算符?如果没有,自定义运算符的示例是什么?,swift,Swift,许多语言中的一个常见功能是二进制运算符,通常用于缩短以下类型的表达式: x = possiblyNullValue NCO valueIfNull …其中,NCO是该语言的空合并运算符的占位符 目标C的空合并运算符为?:,因此表达式为: x = possiblyNullValue ?: valueIfNull 上述表达式也等效于使用第三运算符: x = someTestForNotNull( possiblyNullValue ) ? possiblyNullValue : valueI
x = possiblyNullValue NCO valueIfNull
…其中,NCO
是该语言的空合并运算符的占位符
目标C的空合并运算符为?:
,因此表达式为:
x = possiblyNullValue ?: valueIfNull
上述表达式也等效于使用第三运算符:
x = someTestForNotNull( possiblyNullValue ) ? possiblyNullValue : valueIfNull
零合并运算符的优点
- 可读性更强的代码(尤其是使用长的描述性变量名)
- 减少排版错误的可能性(测试的var仅键入一次)
- 在被测变量是getter的情况下,不会对被测变量进行双重计算,因为它只被访问一次(或者需要缓存它以故意避免双重计算)
- (另请参见)
不,Swift目前不支持空合并运算符
为Swift定义自定义空合并运算符
可以为Swift定义自定义运算符,并考虑以下有关Swift语言的因素:
迅捷零
Swift通过其可选类型(一种有区别的排序并集)支持空概念,该类型要么包含基础类型的值,要么不包含任何值(由nil表示),并且必须明确定义为可选:
var a : String?
非可选类型不能为nil,也不能指定为nil。因此,可以预期自定义中缀二进制NCO的第一个参数是可选的
Swift中自定义运算符的可用字符
在Swift中,自定义运算符只能由以下字符组成:
/ = - + * % < > ! & | ^ . ~
定义运算符
运算符中缀| | |{}
@中缀函数(左:T?,右:T)->T{
如果让l=left{返回l}
返回权
}
文卡特说的是正确的:没有,但你可以定义一个。
然而,他的实现并不理想,因为他忘了使用@auto\u closure
另外,我相信您可以重载|
,而无需定义新的运算符
我这里没有编译器,但我将尝试从内存中为您提供代码:
func |||<T> (maybe: Optional<T>, defaultValue: @auto_closure () -> T) -> T {
if let some = maybe {
return some
}
return defaultValue()
}
func | | |(可能:可选,默认值:@auto_closure()->T)->T{
如果让一些=也许{
还一些
}
返回defaultValue()
}
编辑:感谢Martin R用编译器测试了这一点。见评论。显然,重载
| |
是可能的,但可能无法按预期工作,因为Swift处理重载运算符解析的方式(这是未记录的,因此我不知道是否可以解决)。我已将上述函数更改为使用| | |
我在博客中介绍了一个提供零合并的自定义运算符函数:
我选择的操作员是
将逻辑not运算符(!)和展开运算符(!)组合为“如果无法展开”语义。看来我来晚了,因为这条线已经一个多月了。不管怎样,这是我的实现,以防你感兴趣
operator infix !! {}
@infix func !! <T> (
value: T?,
defaultValue: @auto_closure () -> T)
-> T
{
return value ? value! : defaultValue()
}
运算符中缀!!{}
@中缀函数!!(
值:T?,
默认值:@auto_closure()->T)
->T
{
返回值?值!:defaultValue()
}
从Swift 2.2(Xcode 6,beta 5)开始,它是?
var x: Int?
var y: Int? = 8
var z: Int = x ?? 9000
// z == 9000
z = y ?? 9001
// z == 8
a??b
相当于以下代码:
a != nil ? a! : b
从Beta 6开始,您可以这样做:
x ?? y ?? 1 == 8
希望这对你有帮助
var anumber:Int? = someValue
var banumber = 2
anumber = ( anumber != nil) ? anumber : banumber ------- (a)
println(anumber!)
anumber = anumber ?? banumber
及
该运算符也可以在同一表达式中多次使用。
像
你可以查看下面的操场代码
import UIKit
var personalSite : String?
let defaultSite = "http://www.google.com"
var website = personalSite ?? defaultSite
据我所知,它最接近的东西是
?。
用于可选值,例如让x=optionalObject?。如果未设置optionalObject
,则值不会导致异常。它不会悄悄地计算。value
,x将是一个未设置的(即nil
)可选值。自定义二进制运算符的使用很好,+1建议:在运算符声明中添加左关联性
,以便您可以键入:let x=foo | | | bar | | baz | | | |“它是nil”
我试图理解为什么它实际上接受两个选项,比如option1 | | | option2
返回nil
如果两者都是nil
或者{some x}
如果其中一个等于x。似乎当rhs是可选的时,T
类型本身就变成了可选的。至少在操场上,a | | |“它是零!”
返回true
,即使定义重载也是如此。如果您的操作符被称为| | |
,它将按预期工作。它不会在重载定义上出错,但不会使用它。不幸的是,没有正式解释Swift如何解决重载的文档。如果您手头有编译器,您可以尝试一些实验,或者我们可以等待苹果提供更多文档。目前,只需使用自定义操作符即可。我将编辑答案以反映您的发现。在编译的应用程序中,结果相同。@Teejay他的实现在两个参数中都是严格的,我的实现在第一个参数中都是严格的。您希望这种运算符至少在第二个参数(也称为“短路”)中具有惰性语义,并且如果已经存在值,则根本不计算默认值。这就是我所做的,他没有。@Teejay这是为了自动创建围绕论点的闭包。这就是短路在应用程序顺序语言中的实现方式。您创建了一个闭包,该闭包可能会被延迟计算,而不是传递一个值(按应用程序的顺序使计算变得严格)??Y1
在beta 5中没有像您预期的那样工作(它将返回x
),但在beta 6中它工作(在这种情况下返回y
,或者如果y,则返回1
)<
anumber = anumber ?? banumber
firstNumber ?? secondNumber ?? thirdNumber.
import UIKit
var personalSite : String?
let defaultSite = "http://www.google.com"
var website = personalSite ?? defaultSite