Swift更新至2.2版本 语言变化
1.允许(大部分)关键字作为参数标签
参数标签是swift函数的接口的一个重要组成部分,描述特定参数的函数,提高可读性。有时候,最自然的与语言关键字标签一个论点一致标签,例如,重复,或推迟。应该允许这样的关键词作为参数标签,允许更好的表达这些接口。
动机是什么?
在一些功能,标签为特定参数的最佳理由正好和语言关键字。例如,考虑一个module-scope函数,发现集合中的一个特定值的指数。自然语言是这样indexOf(_:in:):
indexOf(value, in: collection)
然而,因为在一个关键字,会需要使用引号的逃避,eg:
indexOf(value, `in`: collection)
在swift特定义新的api时,作者往往会选择其他non-keyword的话(如。within 例子中),即使他们并不理想.然而,这个问题也出现在导入objective - c api”省略不必要的词“启发式,要求摆脱使用这些api.例如:
event.touchesMatching([.Began, .Moved], `in`: view)
NSXPCInterface(`protocol`: SomeProtocolType.Protocol)
提出解决方案:允许使用的关键词除了inout、var,le t 参数标签。这会影响三个地方的语法:
1.调用表达式,比如上面的示例。在这里,我们没有这样的含糊不清,因为“:”不出现在任何语法在括号表达式列表。到目前为止,这是最重要的。
2.函数/下标/初始值设定项声明:除了上面的三个除外,这里没有歧义,因为关键字永远是紧随其后的是一个标识符,“:”,或者“_”。例如:
func touchesMatching(phase: NSTouchPhase, in view: NSView?) -> Set<NSTouch>
介绍的关键字或修改一个参数——目前只是“inout”,“let”,“var”——将需要保留以前的含义。如果我们发明一个API,使用这样的关键词,他们仍然需要back-ticked:
func addParameter(name: String, `inout`: Bool)
3.功能类型:# 2,这是很简单的,因为参数名称总是后跟一个“:”:
(NSTouchPhase, in: NSView?) -> Set<NSTouch> (String, inout: Bool) -> Void
2.元组比较运算符
== , != ,< , <= , > , >= 运算符进行比较
@warn_unused_result public func == <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2 } @warn_unused_result public func != <A: Equatable, B: Equatable, C: Equatable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { return lhs.0 != rhs.0 || lhs.1 != rhs.1 || lhs.2 != rhs.2 } @warn_unused_result public func < <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 < rhs.0 } if lhs.1 != rhs.1 { return lhs.1 < rhs.1 } return lhs.2 < rhs.2 } @warn_unused_result public func <= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 < rhs.0 } if lhs.1 != rhs.1 { return lhs.1 < rhs.1 } return lhs.2 <= rhs.2 } @warn_unused_result public func > <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 > rhs.0 } if lhs.1 != rhs.1 { return lhs.1 > rhs.1 } return lhs.2 > rhs.2 } @warn_unused_result public func >= <A: Comparable, B: Comparable, C: Comparable>(lhs: (A,B,C), rhs: (A,B,C)) -> Bool { if lhs.0 != rhs.0 { return lhs.0 > rhs.0 } if lhs.1 != rhs.1 { return lhs.1 > rhs.1 } return lhs.2 >= rhs.2 }
3. 用associatedtype 替换 typealias 关键字相关的类型声明、
介绍:
目前typealias关键字用于声明两种类型:
类型别名(替代名称为现有类型)
相关类型(占位符名称类型作为协议的一部分)
这两种声明是不同的,应该使用不同的关键字。这将强调它们之间的差异,减少周围的一些混乱的使用相关联的类型。拟议的新关键字是associatedtype。
动机是什么?
重用typealias相关类型声明是混乱在许多方面。它不明显,typealias协议意味着别的东西比在其他地方。初学者隐藏相关类型的存在,使他们误解了编写代码。目前还不清楚具体类型别名是禁止内部协议。特别是,2 + 3导致程序员编写
protocol Prot { typealias Container : SequenceType typealias Element = Container.Generator.Element }
没有意识到Element是一个新类型 用Container.Generator.Element的默认值去替换类型别名Container.Generator.Element。
然问 这样的代码
protocol Prot {
typealias Container : SequenceType
}
extension Prot {
typealias Element = Container.Generator.Element
}
作为一个类型别名Container.Generator.Element声明Element。这些微妙的目前需要仔细考虑理解的语言。
解决方案 :
对于声明相关的类型,用associatedtype替换typealias关键字。这可以解决上面提到的问题:typealias现在可以只用于声明类型别名。初学者现在被迫学习相关类型在创建协议。现在可以显示一个错误消息,当有人试图创建一个类型别名在一个协议。这消除了困惑显示在前面的代码片段。
protocol Prot {
associatedtype Container : SequenceType
typealias Element = Container.Generator.Element // error: cannot declare type alias inside protocol, use protocol extension instead 不能声明类型别名内部协议, 使用协议扩展
}
protocol Prot {
associatedtype Container : SequenceType
}
extension Prot {
typealias Element = Container.Generator.Element
}
选择关键词是:type
, associated
, requiredtype
, placeholdertype
, …
声明相关的类型,我建议添加associatedtype和轻视typealias在swift2.2中,和
完全
删除typealias 在swift3。作为另一个只是替换一个关键字,过渡到associatedtype可以轻易被自动化的风险没有任何破坏现有代码。
4.命名函数作为参数标签
介绍:
swift包括支持一级函数,这样任何函数(或方法)可以放在一个函数类型的值。然而,当指定一个函数的名称,我们只能提供基本名称,(如insertSubview)没有标签的论证。对于重载函数,这意味着人们必须消除
类型信息的基础上
歧义,这是尴尬的和冗长的。这个提议允许一个提供参数标签当引用一个函数,消除了在大多数情况下需要提供类型的上下文。
Swift-evolution线程:这个提议是这里讨论的初稿。它包括支持命名getter / setter(分别由迈克尔·亨森在这里继续)。乔Groff让我相信,眼镜是一种更好的方法来处理getter / setter,所以我把他们从这个版本的建议。
动机是什么?
extension UIView {
func insertSubview(view: UIView, at index: Int)
func insertSubview(view: UIView, aboveSubview siblingSubview: UIView)
func insertSubview(view: UIView, belowSubview siblingSubview: UIView)
}
调用这些方法
someView.insertSubview(view, at: 3)
someView.insertSubview(view, aboveSubview: otherView)
someView.insertSubview(view, belowSubview: otherView)
然而,当引用函数创建一个函数值,一个不能提供标签:
let fn = someView.insertSubview // ambiguous: could be any of the three methods
这个是模棱两可的:可以是任何的三个方法
可以使用消除歧义的类型注解:
let fn: (UIView, Int) = someView.insertSubview // ok: uses insertSubview(_:at:)
let fn: (UIView, UIView) = someView.insertSubview // error: still ambiguous! 仍然模棱两可
解决后者的情况下,一个人必须回到创建一个闭包:
let fn: (UIView, UIView) = { view, otherView in button.insertSubview(view, aboveSubview: otherView) }
这是痛苦的乏味。一个额外的动机:swift应该得到一些要求objective - c的方法选择器对于一个给定的方法(而不是写一个字符串)。这样的一个操作的参数可能会引用一个方法,将受益于任何方法能够名称,包括getter和setter。
解决方法:
我建议延长函数命名允许化合物swift名称(如。,insertSubview(_:aboveSubview:))可能发生的任何一个名字。具体地说,
let fn = someView.insertSubview(_:at:) let fn1 = someView.insertSubview(_:aboveSubview:)
具体来说,相同的语法也可以指的是初始化,例如,
let buttonFactory = UIButton.init(type:)
“产生给定方法的objective - c选择器”操作将一个单独的建议的主题。然而,这是一种可能性,插图如何利用提出的语法:
let getter = Selector(NSDictionary.insertSubview(_:aboveSubview:)) // produces insertSubview:aboveSubview:.
无参数的函数引用仍需要通过上下文类型信息消歧
func foo(x: Int, y: Int = 7, strings: String...) { ... }
let fn1 = foo(x:y:strings:) // okay
let fn2 = foo(x:) // error: no function named 'foo(x:)'
当所有参数_,这提供了任何方法名称的能力
aGameView.insertSubview(_, aboveSubview: _)
或者
{ aGameView.insertSubview($0, aboveSubview: playingSurfaceView) }
5.引用oc 选择器的方法
#selector 关键字 引入oc 的方法
let sel = #selector(((UIView.insertSubview(_:at:)) as (UIView) -> (UIView, Int) -> Void))
as可用于中同名迅速消除歧义的方法
6.限制AnySequence.init 任何序列
为了让AnySequence委托调用底层的序列,其初始化应该有额外的约束。