1.容許(大部分)關鍵字做爲參數標籤程序員
參數標籤是swift函數的接口的一個重要組成部分,描述特定參數的函數,提升可讀性。有時候,最天然的與語言關鍵字標籤一個論點一致標籤,例如,重複,或推遲。應該容許這樣的關鍵詞做爲參數標籤,容許更好的表達這些接口。swift
動機是什麼?api
在一些功能,標籤爲特定參數的最佳理由正好和語言關鍵字。例如,考慮一個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 }
選擇關鍵詞是:, , , , …typeassociatedrequiredtypeplaceholdertype
聲明相關的類型,我建議添加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委託調用底層的序列,其初始化應該有額外的約束。