2015-11-07 79 views
1

我想知道爲什麼map()filter()SequenceType同時返回Array。其實我並不認爲這是必要的。再次返回序列讓我感覺更加明智。在Swift中擴展序列類型

但是,我試圖添加順序版本時卡住了。這是我嘗試地圖:

extension SequenceType { 

    func seqMap<T, S: SequenceType where S.Generator.Element == T>(
     transform: Self.Generator.Element -> T) -> S 
    { 
     var sourceGen = generate() 
     let tGen: AnyGenerator<T> = anyGenerator { 
      if let el = sourceGen.next() { 
       return transform(el) 
      } else { 
       return nil 
      } 
     } 
     return AnySequence { tGen } 
    } 
} 

的XCode告訴我,在最後的return語句以下錯誤:

cannot invoke initializer for type 'AnySequence<T>' with an argument list of type '(() -> AnyGenerator<T>)' 
note: overloads for 'AnySequence<T>' exist with these partially matching parameter lists: (S), (() -> G) 

其實,我tGen() -> G型的,所以爲什麼不會的XCode認爲這是模糊的?

回答

3

的問題變得如果拆分return語句更加明顯:

let tSeq = AnySequence { tGen } 
return tSeq // error: cannot convert return expression of type 'AnySequence<T>' to return type 'S' 

編譯器會從一個方法調用的上下文 推斷佔位類型S,這可能是任何序列 類型與要素鍵入T,而不一定是AnySequence

下面是一個簡單的例子證明了同樣的問題:

protocol MyProtocol { } 
struct MyType { } 
extension MyType : MyProtocol { } 

func foo<P : Protocol>() -> P { 
    return MyType() // error: cannot convert return expression of type 'MyType' to return type 'P' 
} 

爲了解決該問題,改變返回類型AnySequence<T> 拖放一般類型S

extension SequenceType { 

    func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T> 
    { 
     var sourceGen = generate() 
     let tGen: AnyGenerator<T> = anyGenerator { 
      if let el = sourceGen.next() { 
       return transform(el) 
      } else { 
       return nil 
      } 
     } 
     return AnySequence { tGen } 
    } 
} 

其可以是寫得更緊湊,因爲

extension SequenceType { 

    func seqMap<T>(transform: Self.Generator.Element -> T) -> AnySequence<T> 
    { 
     var sourceGen = generate() 
     return AnySequence(anyGenerator { 
      sourceGen.next().map(transform) 
     }) 
    } 
} 

使用Optional類型的map()方法。

但需要注意的是SequenceType已經有一個lazy方法,它返回 一個LazySequenceType

/// A sequence containing the same elements as a `Base` sequence, but 
/// on which some operations such as `map` and `filter` are 
/// implemented lazily. 
/// 
/// - See also: `LazySequenceType` 
public struct LazySequence<Base : SequenceType> 

,你可以使用

someSequence.lazy.map { ... } 

得到映射值的(懶洋洋地評估)序列。

+0

非常感謝您的詳細解釋。我收到的錯誤信息有些誤導。我不知道這個懶惰的屬性。現在,這是有道理的。 – obecker