将数组扩展转换为 SequenceType?

Convert Array extension to SequenceType?

我将我在我的应用程序中使用的一些常用功能放在一起,并提出了以下扩展:

public extension CollectionType {
    public func toArray() -> [Self.Generator.Element] {
        return self.map { [=10=] }
    }
}

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 吗?

一般来说,@noescape 应该在闭包未保存以供日后使用的任何时候使用,它似乎适用于您这里的两个闭包。

你说的 "can they be applied to a lower level type" 的意思不是很清楚 或多或少,你可以为其他一些协议创建这些扩展的版本,但你现有的 skip 函数只能应用到 Array(顺便说一句,SequenceType 上有一个现有函数 dropFirst 做完全相同的事情)

对于 takeskip 你可能想要实际考虑返回一个 ArraySlice 因为这避免了复制原始数组:

extension Array {
    func take(count:Int) -> ArraySlice<Element> {
        return self[0..<count]
    }

    func drop(count:Int) -> ArraySlice<Element> {
        return self[count..<self.count]
    }
}

请注意,对于这两个,您可能(可能)想要添加一些错误 detection/handling,因为如果 count > self.count.

它们会爆炸

同样,使用 contains 来实现 anyall 可能更有效,因为它不会导致仅为计数构建新数组:

extension Array {
    func any(@noescape predicate:(Element)->Bool) -> Bool {
        return contains(predicate)
    }
    func all(@noescape predicate:(Element)->Bool) -> Bool {
        return !contains { !predicate([=11=]) }
    }
}

作为将其中一些定义为 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([=12=]) }
    }
    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)
    }
}