Swift进化建议SE-0094在Swift 3.0中实现,引入了全局序列函数:
> sequence(first:next:)
> sequence(state:next:)
后者声明如下
06000
并在swift/stdlib/public/core/UnfoldSequence.swift中实现.语言参考提供了以下使用它的示例(请注意缺少显式类型注释)
06001
但是,我不能让上面的例子工作(例如使用let seq1 = 1 … 3,让seq2 = 4 … 6),但是会出现相当奇怪的错误消息
error: ambiguous reference to member ‘
sequence(first: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
这不是我希望使用序列(state:next :)的方式,但是,因为我宁愿在即时应用程序中看到它,其中类型推断可以正常工作,避免所有的显式性.
题
>我们是否打算使用序列(first:next :)函数和上面的显式类型注释?由于inout参数关闭,这个函数是否有一些限制,或者我错过了什么?
第一个是Swift目前没有推断出没有任何外部上下文的多行闭包的类型.然而,正如Apple开发人员Jordan Rose在SR-1570的评论中所证实的那样,这是预期的行为:
This is correct behavior: Swift does not infer parameter or return types from the bodies of multi-statement closures. But the diagnostic could be a lot better.
因此理论上,您只需要显式定义传递给sequence()的next:参数的闭包的返回类型,因为参数类型可以从外部上下文推断(即传递给state的类型:参数):
let seq1 = 1...3 let seq2 = 4...6 let combined = sequence(state: (false,next: { iters -> Int? in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })
(编辑:现在在Swift 3.1中编译)
但是,这仍然无法编译 – 这是由于第二个问题,编译器无法推断Swift 3中的inout闭包参数的类型(在Swift 2中不是这种情况).这是一个可疑的错误,已经提交(见SR-1976和SR-1811).
因此,正如您在问题中所述,这意味着(非常不满意)您必须显式注释您传递给下一个的完整闭包签名::
let combined = sequence(state: (false,ClosedRangeIterator<Int>)) -> Int? in iters.0 = !iters.0 return iters.0 ? iters.1.next() : iters.2.next() })