2015-11-07 42 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