为什么使用索引以外的参数名称会导致 'subscript(_:)' 的使用不明确

Why does using a parameter name other the index result in Ambiguous use of 'subscript(_:)'

采用下面的两个片段,上面的片段工作正常但下面的结果 'subscript(_:)'

的使用不明确

使用索引

extension Array {
    subscript(i index: Int) -> (String, String)? {
        guard let value = self[index] as? Int else {
            return nil
        }
        
        switch (value >= 0, abs(value % 2)) {
        case (true, 0): return ("positive", "even")
        case(true, 1): return ("positive", "odd")
        case(false, 0): return ("negative", "even")
        case(false, 1): return ("negative", "odd")
        default: return nil
            
        }
    }
}

不使用索引

extension Array {
    subscript(i: Int) -> (String, String)? {
        guard let value = self[i] as? Int else {
            return nil
        }
        
        switch (value >= 0, abs(value % 2)) {
        case (true, 0): return ("positive", "even")
        case(true, 1): return ("positive", "odd")
        case(false, 0): return ("negative", "even")
        case(false, 1): return ("negative", "odd")
        default: return nil
            
        }
    }
}

首先,名称index与问题无关;可以是任何名字。

实际问题是Array already has a subscript that takes an unlabeled Int.

您的第一个重载没有相同的输入签名。相反,它需要一个参数标签:

[1][i: 0] // ("positive", "odd")

可以仍然使用没有标签的重载…

extension Array where Element: BinaryInteger {
  subscript(: Int) -> (String, String) {
    let value: Element = self[]
    return (
      value >= 0 ? "positive" : "negative",
      value.isMultiple(of: 2) ? "even" : "odd"
    )
  }
}

...但是,正如下标主体本身所必需的那样,您需要始终显式键入结果,以便从标准库访问重载,因为您自己的模块中的任何内容都将优先考虑。

[1][0] // ("positive", "odd")
[1][0] as Int // 1

因此,我建议使用带标签的下标或方法。*


* 我推荐的是命名下标。但是 Swift 没有。但是,您可以使用更多类型来模拟它们。像这样:

extension Array where Element: BinaryInteger {
  struct InfoStrings {
    fileprivate let array: Array
  }

  var infoStrings: InfoStrings { .init(array: self) }
}

extension Array.InfoStrings {
  subscript(index: Int) -> (String, String) {
    let value = array[index]
    return (
      value >= 0 ? "positive" : "negative",
      value.isMultiple(of: 2) ? "even" : "odd"
    )
  }
}

[1].infoStrings[0]