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
      

      希望这对你有帮助

    • 是的,现在它被添加到swift中

    • 很少解释

             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