Swift进化建议SE-0094在Swift 3.0中实现,引入了全局sequence功能:
sequence
sequence(first:next:)
sequence(state:next:)
后者声明如下
func sequence<T, State>(state: State, next: @escaping (inout State) -> T?) -> UnfoldSequence<T, State>
并在swift / stdlib / public / core / UnfoldSequence.swift中实现。语言参考提供了以下使用它的示例(请注意,缺少显式类型注释)
// Interleave two sequences that yield the same element type sequence(state: (false, seq1.makeIterator(), seq2.makeIterator()), next: { iters in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })
// Interleave two sequences that yield the same element type sequence(state: (false, seq1.makeIterator(), seq2.makeIterator()), next:
{ iters in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })
但是,我无法使上面的示例正常工作(例如,使用let seq1 = 1...3,let seq2 = 4...6),但是出现了非常奇怪的错误消息提示
let seq1 = 1...3
let seq2 = 4...6
错误:对成员’ sequence(first:next:)‘的引用不明确
仅当我State在next闭包中显式键入注释可变参数及其返回类型时,以上示例才会编译
State
next
let seq1 = 1...3 let seq2 = 4...6 for i in sequence(state: (false, seq1.makeIterator(), seq2.makeIterator()), next: { (iters: inout (Bool, ClosedRangeIterator<Int>, ClosedRangeIterator<Int>)) -> Int? in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() }) { print(i) } // 1 4 2 5 3 6
sequence(state:next:)但是,这不是我希望使用的方式,因为我宁愿在动态应用程序中看到这种方式,在这种应用程序中类型推断应按应有的方式工作,避免了所有显式性。
inout
这看起来像是两个问题的组合。
首先是Swift目前没有任何外部上下文都无法推断多行闭包的类型。但是,这是预期的行为,正如Apple开发人员Jordan Rose在SR-1570的评论中所证实的那样:
这是正确的行为:Swift不会从多语句闭包的主体中推断参数或返回类型。但是诊断可能会好得多。
因此,从理论上讲,您只需要显式定义传递给sequence()的next:参数的闭包的返回类型,因为可以从外部上下文推断出参数的类型(即传递给state:参数的类型):
sequence()
next:
state:
let seq1 = 1...3 let seq2 = 4...6 let combined = sequence(state: (false, seq1.makeIterator(), seq2.makeIterator()), next: { iters -> Int? in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })
(编辑:现在可以在Swift 3.1中进行编译)
但是,这仍然无法编译-这是由于第二个问题,在第二个问题中,编译器无法推断inoutSwift 3中闭包参数的类型(在Swift 2中不是这种情况)。这是一个可疑的错误,已经提交(请参见SR-1976和SR-1811)。
因此,正如您在问题中指出的那样,这意味着(相当不令人满意)您必须显式地注释传递给next:以下内容的完整闭包签名:
let combined = sequence(state: (false, seq1.makeIterator(), seq2.makeIterator()), next: { (iters: inout (Bool, ClosedRangeIterator<Int>, ClosedRangeIterator<Int>)) -> Int? in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })