代码之家  ›  专栏  ›  技术社区  ›  byaruhaf

为什么使用索引以外的参数名会导致“subscript(\:)”的使用不明确

  •  0
  • byaruhaf  · 技术社区  · 2 年前

    以下面的两个片段为例,上面的一个很好,但下面的一个结果是 “下标(\:)”的用法不明确

    使用索引 âœ

    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
                
            }
        }
    }
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Jessy    2 年前

    首先,名称 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
    

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


    *什么是我 希望 推荐是一个命名的下标。但斯威夫特没有。但是,您可以使用更多类型来模拟它们。这样地:

    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]