Как подстрочный словарь 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)
когда Int
s используются в качестве ключей, нижний индекс ключа используется по желанию.
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
тип.