Per risolvere this question, ho giocato con una struttura personalizzata che implementa il protocollo Hashable. Sto provando a vedere quante volte viene chiamato il sovraccarico dell'equivalente operatore (==
) a seconda che si verifichi una collisione hash o meno quando si popola un Dictionary
.In che modo il dizionario utilizza il protocollo Equatable in Swift?
Aggiornamento
@matt scritto un esempio molto più pulito di una struttura personalizzata che implementa il protocollo hashable e mostra come spesso hashValue
e ==
vieni chiamato. Sto copiando his code qui sotto. Per vedere il mio esempio originale, controlla lo edit history.
struct S : Hashable {
static func ==(lhs:S,rhs:S) -> Bool {
print("called == for", lhs.id, rhs.id)
return lhs.id == rhs.id
}
let id : Int
var hashValue : Int {
print("called hashValue for", self.id)
return self.id
}
init(_ id:Int) {self.id = id}
}
var s = Set<S>()
for i in 1...5 {
print("inserting", i)
s.insert(S(i))
}
Questo produce i risultati:
/*
inserting 1
called hashValue for 1
inserting 2
called hashValue for 2
called == for 1 2
called hashValue for 1
called hashValue for 2
inserting 3
called hashValue for 3
inserting 4
called hashValue for 4
called == for 3 4
called == for 1 4
called hashValue for 2
called hashValue for 3
called hashValue for 1
called hashValue for 4
called == for 3 4
called == for 1 4
inserting 5
called hashValue for 5
*/
Dal hashable utilizza equatable di differenziare collisioni hash (presumo comunque), mi aspetterei func ==()
solo per essere chiamato in caso di collisioni hash. Tuttavia, non ci sono mai collisioni di hash nell'esempio di @ matt sopra, eppure ==
viene ancora chiamato. Nei miei altri esperimenti che hanno forzato le collisioni di hash (vedi la cronologia delle modifiche di questa domanda), ==
sembrava essere chiamato un numero casuale di volte.
Cosa sta succedendo qui?
Detesto dare una risposta o un commento, ma questo è un dettaglio di implementazione interno di Swift. Possono ottimizzare il tipo come vogliono a patto che sia conforme alle API del dizionario documentate. E i documenti non forniscono alcuna garanzia sulla frequenza con cui le chiavi verranno controllate per l'uguaglianza - richiedono semplicemente che forniate quell'interfaccia '=='. Immagino che lo sapremo più avanti quest'anno quando Swift diventerà open source. Inoltre, vedi il mio commento simile alla tua [altra domanda] (http://stackoverflow.com/questions/31664159/how-to-handle-hash-collisions-for-dictionaries-in-swift). – justinpawela
Ecco un test più semplice (credo): https://gist.github.com/mattneub/430fef70e3496f5ce6917aa35c98f419 L'output rende molto esplicito quante volte vengono chiamati 'hashValue' e' == 'per ogni inserimento. – matt
@matt, sì, questo è un test molto più semplice e chiaro. Ma ora sono più confuso di quanto pensassi. Il tuo esempio non ha collisioni hash, giusto? E tuttavia '==' viene ancora chiamato. Prima ero convinto che '==' venisse chiamato solo per trattare i casi di collisione dell'hash. – Suragch