全局函数序列(状态:下一个:)和类型推断 [英] Global function sequence(state:next:) and type inference

查看:100
本文介绍了全局函数序列(状态:下一个:)和类型推断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

迅速发展的提议 SE-0094 在Swift 3.0中实现,引入了全局sequence函数:

Swift evolution proposal SE-0094 was implemented in Swift 3.0, introducing the global sequence functions:

后者声明如下

func sequence<T, State>(state: State, 
                        next: @escaping (inout State) -> T?) ->
         UnfoldSequence<T, State>

,并在 swift/stdlib/public/core/UnfoldSequence.swift .语言参考提供了以下使用它的示例(请注意缺少显式类型注释)

and is implemented in swift/stdlib/public/core/UnfoldSequence.swift. The language reference gives the following example for using it (note the lack of explicit type annotation)

// 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...3let seq2 = 4...6),但是出现了非常奇怪的错误消息提示

I cannot, however, get the example above to work (e.g. using let seq1 = 1...3, let seq2 = 4...6), but is prompted with the rather curious error message

错误:对成员'sequence(first:next:)'的含糊引用

仅当我在next闭包中显式地键入可变的State参数的注释及其返回类型时,以上示例才会编译

Only if I explicitly type annotate the mutable State parameter in the next closure, as well as the return type of it, does the example above compile

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:)的方式,因为我宁愿在即时应用程序中看到它,而类型推断应按应有的方式进行,从而避免了所有显式性.

This is not the way I hope to use sequence(state:next:), however, as I'd rather see it in on-the-fly applications where type inference works as it should, avoiding all the explicitness.

  • 我们是否打算将sequence(first:next:)函数与上述显式类型注释一起使用?由于inout参数关闭,此功能是否存在某些限制?还是我缺少某些东西?
  • Are we intended to use the sequence(first:next:) function with explicit type annotations as above? Is there some limitation in this function due to the inout parameter closure, or am I missing something?

推荐答案

这看起来像是两个问题的组合.

This looks like a combination of two issues.

首先,Swift当前无法在没有任何外部上下文的情况下推断出多行闭包的类型.但是,这是预期的行为,如Apple开发人员Jordan Rose在 SR-1570

The first is that Swift currently doesn't infer the type of a multi-line closure without any external context. This is however intended behaviour, as confirmed by Apple developer Jordan Rose in the comments of SR-1570:

这是正确的行为:Swift不会从多语句闭包的主体中推断参数或返回类型.但是诊断可能会好很多.

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:参数):

Therefore in theory, you would just need to explicitly define the return type of the closure you pass to sequence()'s next: parameter, as the parameter type can be inferred from external context (namely the type you pass into the state: parameter):

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中进行编译)

( This now compiles in Swift 3.1)

但是,这仍然无法编译-这是由于第二个问题,在第二个问题中,编译器无法推断Swift 3中inout闭包参数的类型(在Swift 2中不是这种情况).这是一个可疑的错误,已经被归档(请参见 SR-1976 & ; SR-1811 ).

However, this still doesn't compile – which is due to the second issue, where the compiler cannot infer the type for an inout closure parameter in Swift 3 (which wasn't the case in Swift 2). This is a suspected bug, which has already been filed (see both SR-1976 & SR-1811).

因此,正如您在问题中指出的那样,这意味着(相当不令人满意)您必须显式地注释传递给next:的完整闭包签名:

Therefore, as you note in the question, this means (quite unsatisfactorily) that you have to explicitly annotate the full closure signature that you pass to 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()
})

这篇关于全局函数序列(状态:下一个:)和类型推断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆