2016-02-22 12 views

risposta

6

() è semplicemente una tupla senza valori; una tupla 0. Il tipo e il valore sono scritti allo stesso modo, entrambi (). Il tipo è talvolta noto come "tipo di unità"; in realtà era un tipo distinto nel compilatore, ma ora è trattato come una tupla degenerata. È un tipo di dimensioni 0; oggetti di questo tipo non occuperanno mai spazio, sebbene sia un tipo Sized, con una dimensione pari a 0.

Viene utilizzato per i casi in cui è necessario avere un valore o un tipo, ma si non hanno nulla di rilevante da mettere lì. Ad esempio, se si dispone di una funzione che non restituisce un valore e lo chiama in un luogo che si aspetta un valore, si scopre che in realtà restituisce il valore () di tipo ().

fn nothing() {} 

fn main() { 
    println!("{:?}", nothing()); 
} 

che stampa () (playpen).

Un altro utilizzo è quando si dispone di un tipo generico come Result<T, E>, che indica un esito positivo o negativo di qualche operazione e può contenere il risultato dell'operazione riuscita o un errore che indica il motivo per cui non è riuscito. Alcune operazioni, come ad esempio std::io::write che non hanno alcun valore da restituire in caso di successo ma vogliono essere in grado di indicare un errore, restituiranno un std::io::Result<()>, che in realtà è un sinonimo di Result<(), std::io::Error>; questo permette alla funzione di restituire Ok(()) nel caso di successo, ma qualche errore significativo quando fallisce.

È possibile confrontarlo con void in C o C++, che vengono utilizzati anche per la mancanza di valore di ritorno. Tuttavia, non è possibile scrivere un oggetto con tipo void, il che rende lo void molto meno utile nella programmazione generica; non potresti mai avere un tipo Result<void, Error> equivalente, perché non potresti mai costruire il caso Ok.

In questo caso, un Mutex normalmente esegue il wrapping e l'oggetto a cui si desidera accedere; quindi puoi mettere quell'oggetto nel mutex e poi accedervi dalla guardia che ottieni quando blocchi il mutex.Tuttavia, in questo esempio non sono presenti dati effettivi, pertanto viene utilizzato () poiché è necessario inserire qualcosa, e Mutex è generico sul tipo in modo che possa accettare qualsiasi tipo.

+0

Forse aggiungi la nozione di "vuoto"? La maggior parte dei programmatori conosce il "vuoto", quindi sarebbe d'aiuto, giusto? –

+1

@LukasKalbertodt: C'è un costo per 'void', tuttavia, è irregolare. Nella programmazione di template C++ per esempio 'void' è un incubo. D'altra parte, '()' è perfettamente integrato nel sistema di tipi => è solo una tupla come le altre. –

+0

@MatthieuM. Giusto, ma ** I ** penso ancora che sarebbe di aiuto ai programmatori provenienti da altre lingue per confrontarlo con 'void' ... –

8

è il tuple vuoto, chiamato anche unit type - una tupla senza tipi di membri. È anche l'unico valore valido di detto tipo. Ha a size of zero (nota che è ancora Sized, solo con una dimensione di 0), rendendolo inesistente in fase di runtime. Questo ha molti effetti utili, uno dei quali è usato qui.

Qui, () viene utilizzato per creare un Mutex senza dati di proprietà: è solo un mutex sbloccabile e bloccabile. Se abbiamo esplicitamente scrivere il tipo di inferenza con la turbofish operator::<>, potremmo anche scrivere:

Mutex::<()>::new(()) 

Cioè, stiamo creando un newMutex che contiene un () con il valore iniziale ().

+0

Mi sono sempre chiesto come si chiamava questa sintassi ... collegamento interessante. – squiguy

+0

Sì, è una delle cose che preferisco di Rust ... Sto cercando di cospargerlo ovunque posso farlo in modo che diventi più ricercabile. – thirtythreeforty

+0

Potrebbe anche essere utile notare se tipi di dimensioni zero come questo contano come "dimensionati" o meno. (Lo fanno, vero?) – LinearZoetrope

Problemi correlati