我正在整理我在我的应用中使用的一些常用功能,并提出了以下扩展程序:
public extension CollectionType {
public func toArray() -> [Self.Generator.Element] {
return self.map { $0 }
}
}
public extension Array {
public func any(fn: (Element) -> Bool) -> Bool {
return self.filter(fn).count > 0
}
public func all(fn: (Element) -> Bool) -> Bool {
return self.filter(fn).count == self.count
}
public func take(count:Int) -> [Element] {
var to = [Element]()
var i = 0
while i < self.count && i < count {
to.append(self[i++])
}
return to
}
public func skip(count:Int) -> [Element] {
var to = [Element]()
var i = count
while i < self.count {
to.append(self[i++])
}
return to
}
}
它们可以应用于SequenceType
等较低级别的类型吗?另外,我是否必须将@noescape
置于这些功能的任何位置?
答案 0 :(得分:3)
一般来说,只要没有保存闭包以供以后使用,就应该使用@noescape
,这似乎适用于你在这里的两个闭包。
“你能将它们应用于较低级别的类型”并不是很清楚你的意思“或多或少显然,你可以为其他一些协议创建这些扩展的版本,但你现有的skip
函数只能应用于Array
(顺便说一下,dropFirst
上的现有函数SequenceType
执行完全相同的操作)
对于take
和skip
,您可能希望实际考虑返回ArraySlice
,因为这样可以避免复制原始数组:
extension Array {
func take(count:Int) -> ArraySlice<Element> {
return self[0..<count]
}
func drop(count:Int) -> ArraySlice<Element> {
return self[count..<self.count]
}
}
请注意,对于这两者,您可能(可能)想要添加一些错误检测/处理,因为如果count > self.count
它们会爆炸。
同样,使用contains
实现any
和all
可能更有效,因为它不会导致为计数构建新数组:
extension Array {
func any(@noescape predicate:(Element)->Bool) -> Bool {
return contains(predicate)
}
func all(@noescape predicate:(Element)->Bool) -> Bool {
return !contains { !predicate($0) }
}
}
作为将其中一些定义为SequenceType
的扩展名的示例:
extension SequenceType {
func any(@noescape predicate:(Generator.Element)->Bool) -> Bool {
return contains(predicate)
}
func all(@noescape predicate:(Generator.Element)->Bool) -> Bool {
return !contains { !predicate($0) }
}
func drop(count:Int) -> Self.SubSequence {
return self.dropFirst(count)
}
}
并且,作为将take
实现为序列扩展的示例:
struct TakeFromSequenceSequence<S:SequenceType> : SequenceType {
var limit : Int
var sequence : S
func generate() -> AnyGenerator<S.Generator.Element> {
var generator = sequence.generate()
var limit = self.limit
return anyGenerator {
guard limit > 0 else {
return nil
}
limit = limit - 1
return generator.next()
}
}
}
extension SequenceType {
func take(count:Int) -> TakeFromSequenceSequence<Self> {
return TakeFromSequenceSequence(limit: count, sequence: self)
}
}