Как подстрочный словарь Swift Dictionary устраняет неоднозначность ключей и индексов Int?

В настоящее время я работаю над структурой данных, предназначенной для уникального хранения пар ключ-значение и их сортировки по ключам. По сути, это отсортированный словарь, и поэтому я стараюсь сохранить как можно больше семантики Swift для коллекции и словаря.

В документации и исходном коде Swift (насколько я могу найти) словари имеют две подписки. Одним из них является наиболее часто используемый индекс по ключу (источник на Github):

extension Dictionary {
  ...
  public subscript(key: Key) -> Value? {
    @inline(__always)
    get {
      return _variantBuffer.maybeGet(key)
    }
    set(newValue) {
      if let x = newValue {
        // FIXME(performance): this loads and discards the old value.
        _variantBuffer.updateValue(x, forKey: key)
      }
      else {
        // FIXME(performance): this loads and discards the old value.
        removeValue(forKey: key)
      }
    }
  }
  ...
}

И второе - это индекс по положению / индексу (Github) источника как часть его соответствия протоколу Collection:

extension Dictionary: Collection {
  ...
  public subscript(position: Index) -> Element {
    return _variantBuffer.assertingGet(position)
  }
  ...
}

При использовании этих словаря с ключом, отличным от Intони ведут себя точно так, как ожидается, поскольку индексы различаются по типам параметров, а именно: String против Int,

let stringKeys = ["One": 1, "Two": 2, "Three": 3]
stringKeys["One"]   // 1
stringKeys[1]       // ("Two", 2)

когда Ints используются в качестве ключей, нижний индекс ключа используется по желанию.

let intKeys = [1: "One, 2: "Two, 3: "Three"]
intKeys[1]   // "One"

Как это делает тип Dictionary? Мне кажется, что Index а также Key параметры подписки оба Int и что компилятор не должен знать, для чего он предназначен. Действительно, когда я реализую те же подписки для моего пользовательского словаря, компилятор выдает именно эту ошибку - "неоднозначное использование" подстрочного "" - когда я тестирую его с Int ключи.

Сначала я задавался вопросом, было ли одно по умолчанию предоставлено в расширении протокола и переопределено более конкретной реализацией, но из того, что я могу сказать выше, это не так. Единственная другая теория, которую я имею, состоит в том, что Index имеет некоторый другой тип, кроме 'Int`, такой, что он остается однозначным, но я не могу найти свой путь ко всему, что подтверждает это. Может кто-нибудь пролить некоторый свет на это? Помимо моих непосредственных потребностей, это довольно умное поведение в Swift, которое я хотел бы понять.

Спасибо всем за чтение и за вашу помощь!

1 ответ

Единственная другая теория, которая у меня есть, заключается в том, что Index относится к другому типу, кроме "Int", так что он остается однозначным, но я не могу найти пути ко всему, что подтверждает это.

Именно так и есть. Dictionary имеет два метода индекса:

public subscript(key: Dictionary.Key) -> Dictionary.Value?
public subscript(position: Dictionary<Key, Value>.Index) -> Dictionary.Element { get }

Первый принимает ключ и возвращает (необязательное) значение, второй принимает Dictionary.Index ( исходный код) и возвращает (необязательно) Dictionary.Element пара ключ-значение. Пример:

let d : Dictionary = [1 : "one"]
if let idx = d.index(forKey: 1) {
    print(String(reflecting: type(of: idx))) // Swift.Dictionary<Swift.Int, Swift.String>.Index
    let kv = d[idx]
    print(String(reflecting: type(of: kv)))  // (key: Swift.Int, value: Swift.String)
}

Dictionary.Index также используется в других методах, таких как

public var startIndex: Dictionary<Key, Value>.Index { get }
public var endIndex: Dictionary<Key, Value>.Index { get }
public func index(where predicate: ((key: Key, value: Value)) throws -> Bool) rethrows -> Dictionary<Key, Value>.Index?

которые являются частью Collection протокол.

Как правило, связанные Index тип Collection не обязательно Int Другой пример String который имеет свой собственный String.Index тип.

Другие вопросы по тегам