2014-09-22 15 views
9

ho notato un sacco di veloci costruito ins prendere o tornare Int s e non UInt s:Qual è la logica dei metodi di risoluzione di Swift che utilizzano `Int`s?

Ecco alcuni esempi: Array

mutating func reserveCapacity(minimumCapacity: Int) 

var capacity: Int { get } 

init(count: Int, repeatedValue: T) 

mutating func removeAtIndex(index: Int) -> T 

Dato che la lingua è completamente nuovo, e assumendo che questa scelta progettuale non è stata arbitraria - Mi chiedo: Perché i dati incorporati rapidi prendono Int s e non UInt s?

Alcune note: Chiedendo perché sto lavorando su alcune collezioni me stesso e mi chiedo che tipo dovrei usare per cose come reserveCapacity ecc Quello che mi aspetto che naturalmente è per reserveCapacity di prendere una UInt invece.

risposta

1

Ecco una possibile spiegazione (io non sono un esperto in materia): Supponiamo di avere questo codice

let x = 3 
test(x) 

func test(t: Int) { 
} 

Questo compilerà senza un problema, in quanto il tipo di 'x' viene dedotto per essere Int.

Tuttavia, se si cambia la funzione di

func test(t: UInt) { 
} 

Il compilatore darà un errore di generazione ('Int' is not convertible to 'UInt')

Quindi la mia ipotesi è che è solo per convenienza, perché la sicurezza il tipo di Swift sarebbe altrimenti richiedi di convertirli manualmente ogni volta.

+0

Per quello che vale [è stata anche la mia ipotesi] (http://chat.stackoverflow.com/transcript/message/19026152#19026152) ma è un'ipotesi piuttosto selvaggia e facendo 'let x: UInt = 3 'lo aggiusterà o' test (UInt (x)) '. Entrambi sembrano molto più "Swiftic" –

+2

Beh, non sono d'accordo ;-) Penso che sembri molto più pulito senza l'annotazione/conversione del tipo. – Atomix

+0

In particolare, 'UInt (x)' potrebbe non essere nemmeno possibile. Potrebbe fallire. Devi pensarci ogni volta che lo usi.E se usi 'x: UInt', lo stesso problema si presenta se devi passarlo a qualcosa che richiede' Int'. Immagina il caso non raro in cui 'x' è' scala' e potrebbe essere applicato a entrambi i lati positivi o negativi, comprese le cose che dovrebbero essere solo positive. Si entra in un flip-flop, si cambia la costante 'scale' tra' Int' e 'UInt', cercando di ottenere quello che è più spesso quello che si desidera (o si creano * due * costanti, che è ancora più brutto). –

7

UInt è una causa comune di bug. È molto facile generare accidentalmente un -1 e terminare con loop infiniti o problemi simili. (Molti programmatori C e C++ hanno imparato nel modo più duro che dovresti semplicemente usare int a meno che non sia necessario per unsigned.) A causa di come Swift gestisce la conversione dei tipi, questo è ancora più importante. Se hai mai lavorato con NSUInteger con gli avvisi "firmati-non firmati" attivati ​​(che sono un errore in Swift, non un avvertimento opzionale come in C), sai che dolore è.

La programmazione Swift guida spiega la loro logica specifica nella sezione relativa UInt:

NOTA

Utilizzare UInt solo quando specificamente bisogno di un tipo intero senza segno con la stessa dimensione come dimensione della parola nativa della piattaforma . Se questo non è il caso, Int è preferito, anche quando i valori da memorizzare sono noti per essere non negativi. Un uso coerente di Int per valori interi aiuta l'interoperabilità del codice, evita la necessità di convertire tra diversi tipi di numeri e corrisponde l'inferenza del tipo intero, come descritto in Sicurezza di tipo e Inferenza di tipo.

+2

In Swift il problema che hai descritto è un non problema. Non puoi passare un int con un valore negativo come UInt e convertirlo in tipo. (Come hai detto tu, è un errore in Swift). –

+0

Esattamente. Quindi finisci spesso per dover fare "UInt (x) + y" per tenerlo nello spazio "UInt". Se crei una costante, ad esempio, sarà di tipo inferenza ad un 'Int', quindi devi lanciarlo. Se lavori con qualcosa che restituisce un 'Int '(e molte cose lo fanno), dovrai lanciarlo. Il cast diventa molto eccessivo, e smetti di prestare attenzione al fatto che il cast sia effettivamente sicuro; non puoi sempre lanciare un int a un non firmato o viceversa. Quando prendi in considerazione il comune errore non firmato di "while x <= y - 1" dove y può essere 0, è solo molto più pulito rimanere nello spazio Int. –

+0

Questa è una lezione appresa da C, ObjC e C++ che hanno problemi simili. Swift sta cercando di schivare quel bug comune. Consulta la guida di stile di Google C++ per uno dei molti posti raccomandando lo stesso comportamento nei predecessori di Swift: https://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Integer_Types "Non dovresti usare i tipi interi senza segno come come uint32_t, a meno che non ci sia una ragione valida come rappresentare un pattern di bit ... In particolare, non usare tipi non firmati per dire che un numero non sarà mai negativo, ma usa asserzioni per questo. " –

Problemi correlati