当给定的参数是已知类型时,Array()是多么模糊?

时间:2018-03-12 18:42:40

标签: arrays swift

我看到的东西对我来说没有意义。这是我的代码......

dropFirst()

&#39;让&#39;即使ArraySlice<SeparatorToken>返回let remainingSeparatorTokens:[SeparatorToken] = Array(separatorTokens.dropFirst()) ,也会导致此编译错误。

  

如果没有更多的上下文,表达的类型是不明确的

为什么这个含糊不清?我错过了什么?

我也尝试过像这样完全合格,但这也不起作用......

{{1}}

3 个答案:

答案 0 :(得分:6)

在通用扩展中,类型参数绑定到它们的范围。我不确定这是不是一件好事(或者可能它真的是一个错误),但它会一直显示,所以这里的类型参数隐含地想要String

一个更简单的例子:

let x = Array()  // error: generic parameter 'Element' could not be inferred

这是有道理的。但是把它放在一个扩展名中:

extension Array {
    func f() {
        let x = Array()
    }
}

此编译,x的类型为[Element]

在您的情况下,您已将Element设置为String,因此致Array.init的电话想要创建一个[String]并且它已获得困惑因为SeparatorToken != String。您需要明确传递type参数(正如您已发现的那样):

let remainingSeparatorTokens = Array<SeparatorToken>(separatorTokens.dropFirst())

同样,我并不认为这是Swift中的一个功能,甚至可能被视为一个错误。但它非常一致。

答案 1 :(得分:1)

我只是在游乐场中运行您的代码并按如下方式更新,然后错误消失了:

import UIKit
import Foundation

enum SeparatorPaddingLocation{
    case beforeSeparator
    case afterSeparator
}

struct SeparatorToken{
    let separator          : Character
    let formattedSeparator : String
    let paddingLocation    : SeparatorPaddingLocation
}

extension Array where Element == String {

    func aligned(separatorTokens:[SeparatorToken]) -> [String] {

        // I update code here
        let remainingSeparatorTokens = Array<SeparatorToken>(separatorTokens.dropFirst())

        return self
    }
}

根据swift,当您使用Array初始化时,Array需要类型。

我希望这对你有用。

有关阵列访问的详细信息:https://developer.apple.com/documentation/swift/array

答案 2 :(得分:1)

这是一个错误,没有任何神秘或类似错误的事情。

不是错误:这是==子句中where运算符可用的原因:要求ElementString类型{1}} ,正如here所解释的那样。在页面中搜索“您还可以编写一个通用where子句,需要Item为特定类型”。

不像bug一样:当你进入扩展并调用Array初始值设定项时,编译器会使用where子句来指示{{1}的特化}} 你要。您的Array条款代表where,所以String就是Array<String>。将ArraySlice<SeparatorToken>传递给Array<String>初始化程序时,编译器无法读懂您的想法。你犯了错误,或者你真的想要Array<ArraySlice<SeparatorToken>>吗?因此关于歧义的错误信息。

以下是OP代码的简化和注释版本,以防有人发现它具有启发性。

class Foo<T> {
    var theFoo: T!

    init() { theFoo = nil }
    init(_ aFoo: T) { theFoo = aFoo }
}

extension Foo where T == Int {
    func bar() {
        // This one fails, because our where clause
        // says this extension applies to Foo<Int>,
        // but now we're trying to assign it to a Foo<String>
        let aFoo: Foo<String> = Foo()

        // This one also fails, for the same reason.
        // It uses the other initializer, but we're
        // still inside the Foo<Int> extension.
        let bFoo: Foo<String> = Foo("bFoo")

        // This one works, because we're expressly
        // overriding the where clause
        let cFoo: Foo<String> = Foo<String>("cFoo")
    }
}

歧义错误是有道理的。我在where子句中告诉编译器将其设为Int扩展名,因此创建了Foo<Int> s。但后来我尝试将它们分配给Foo<String>类型的变量。编译器无法判断我是否真的想要Foo<String>或者我犯了错误,所以它放弃了。