在 Swift 中扩展 SequenceType
Extending the SequenceType in Swift
我想知道为什么 SequenceType
return 中的 map()
和 filter()
都是 Array
。
其实我觉得没必要。再次返回序列对我来说感觉更明智。
但是,我在尝试添加顺序版本时遇到了困难。这是我对地图的尝试:
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会觉得有歧义呢?
如果拆分 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'
}
要解决问题,请将 return 类型更改为 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
方法 returns
一个 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 { ... }
获取映射值的(延迟计算的)序列。
我想知道为什么 SequenceType
return 中的 map()
和 filter()
都是 Array
。
其实我觉得没必要。再次返回序列对我来说感觉更明智。
但是,我在尝试添加顺序版本时遇到了困难。这是我对地图的尝试:
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会觉得有歧义呢?
如果拆分 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'
}
要解决问题,请将 return 类型更改为 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
方法 returns
一个 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 { ... }
获取映射值的(延迟计算的)序列。