我需要为自己的结构实现类型擦除包装,非常类似于SequenceOf
,GeneratorOf
等。所以我开始尝试重新实现标准{{1}我自己。
我刚复制过&粘贴SequenceOf
的声明,将其重命名为SequenceOf
,并填写一些存根以获取:
MySequenceOf
我收到编译错误:" 同类型中的任何一种类型都不是指泛型参数或相关类型"。所以我假设Xcode生成的/// A type-erased sequence.
///
/// Forwards operations to an arbitrary underlying sequence with the
/// same `Element` type, hiding the specifics of the underlying
/// sequence type.
///
/// See also: `GeneratorOf<T>`.
struct MySequenceOf<T> : SequenceType {
/// Construct an instance whose `generate()` method forwards to
/// `makeUnderlyingGenerator`
init<G : GeneratorType where T == T>(_ makeUnderlyingGenerator: () -> G) {
fatalError("implement me")
}
/// Construct an instance whose `generate()` method forwards to
/// that of `base`.
init<S : SequenceType where T == T>(_ base: S) {
fatalError("implement me")
}
/// Return a *generator* over the elements of this *sequence*.
///
/// Complexity: O(1)
func generate() -> GeneratorOf<T> {
fatalError("implement me")
}
}
&#39; SequenceOf
&#34;约束真的意味着&#34; where T == T
&#34;,它给了我以下可编译的结构:
where G.Element == T
现在,很简单,我只需要从初始化程序中挂起struct MySequenceOf<T> : SequenceType {
init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
fatalError("implement me")
}
func generate() -> GeneratorOf<T> {
fatalError("implement me")
}
}
并从makeUnderlyingGenerator
调用它:
generate()
但这给了我错误:&#34; &#39; G&#39;不能转换为&#39; GeneratorOf&#39; &#34;
如果强制演员, 会编译:
struct MySequenceOf<T> : SequenceType {
let maker: ()->GeneratorOf<T>
init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
self.maker = { return makeUnderlyingGenerator() }
}
func generate() -> GeneratorOf<T> {
return self.maker()
}
}
但是它在运行时从动态演员表中崩溃了。
那么如何实现这样的类型擦除呢?它必须是可能的,因为Swift标准库做了很多(SequenceOf,GeneratorOf,SinkOf)。
答案 0 :(得分:5)
尝试:
struct MySequenceOf<T> : SequenceType {
private let _generate:() -> MyGeneratorOf<T>
init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
_generate = { MyGeneratorOf(makeUnderlyingGenerator()) }
}
init<S : SequenceType where S.Generator.Element == T>(_ base: S) {
_generate = { MyGeneratorOf(base.generate()) }
}
func generate() -> MyGeneratorOf<T> {
return _generate()
}
}
struct MyGeneratorOf<T> : GeneratorType, SequenceType {
private let _next:() -> T?
init(_ nextElement: () -> T?) {
_next = nextElement
}
init<G : GeneratorType where G.Element == T>(var _ base: G) {
_next = { base.next() }
}
mutating func next() -> T? {
return _next()
}
func generate() -> MyGeneratorOf<T> {
return self
}
}
实施ProtocolOf<T>
的基本策略是这样的:
protocol ProtocolType {
typealias Value
func methodA() -> Value
func methodB(arg:Value) -> Bool
}
struct ProtocolOf<T>:ProtocolType {
private let _methodA: () -> T
private let _methodB: (T) -> Bool
init<B:ProtocolType where B.Value == T>(_ base:B) {
_methodA = { base.methodA() }
_methodB = { base.methodB($0) }
}
func methodA() -> T { return _methodA() }
func methodB(arg:T) -> Bool { return _methodB(arg) }
}
添加在评论中回答@MartinR。
有一个特殊的原因,即_generate是一个闭包而不是发生器本身?
首先,我认为,这是规范或语义问题。
毋庸置疑,不同之处在于“何时创建发电机”。
考虑以下代码:
class Foo:SequenceType {
var vals:[Int] = [1,2,3]
func generate() -> Array<Int>.Generator {
return vals.generate()
}
}
let foo = Foo()
let seq = MySequenceOf(foo)
foo.vals = [4,5,6]
let result = Array(seq)
问题是:result
应为[1,2,3]
还是[4,5,6]
?我的MySequenceOf
和内置SequenceOf
会导致后者。我只是将行为与内置行为相匹配。
答案 1 :(得分:1)
以下是MySequenceOf
的示例实现,似乎有效:
struct MySequenceOf<T> : SequenceType {
let myGenerator : GeneratorOf<T>
init<G : GeneratorType where G.Element == T>(_ makeUnderlyingGenerator: () -> G) {
self.myGenerator = GeneratorOf( makeUnderlyingGenerator() )
}
init<S : SequenceType where S.Generator.Element == T>(_ base: S) {
self.myGenerator = GeneratorOf( base.generate() )
}
func generate() -> GeneratorOf<T> {
return myGenerator
}
}
使用示例:
let seq = MySequenceOf {
_ -> GeneratorOf<Int> in
var i = 0
return GeneratorOf {
i < 5 ? ++i : nil
}
}
for i in seq { println(i) }
您还可以通过以下方法从Swift库中替换GeneratorOf
MyGeneratorOf
:
struct MyGeneratorOf<T> : GeneratorType, SequenceType {
var nextFunc : () -> T?
init<G : GeneratorType where G.Element == T>(_ base: G) {
self.nextFunc = {
() -> T? in
var generator = base
return generator.next()
}
}
init(_ nextElement: () -> T?) {
self.nextFunc = nextElement
}
mutating func next() -> T? {
return nextFunc()
}
// Returns a copy of itself.
func generate() -> MyGeneratorOf<T> {
return MyGeneratorOf(nextFunc)
}
}
所以(据我所知,我远非了解所有通用序列
和发电机的东西)&#34;技巧&#34;是next()
的方法
发电机是一个闭合器,捕获给定的发电机,因此可以
转发next()
电话。不需要演员表。