2016-01-11 30 views

risposta

5

modello legame può avere un po 'di utilizzare per;)

Per capire cosa fa il compilatore, è possibile utilizzare il let _:() = ...; trucco. Assegnando a una variabile di tipo (), si forza il compilatore a stampare un messaggio di errore che fornisce il tipo che ha dedotto per la variabile.


Nel primo esempio:

let vec = vec![1, 2, 3]; 
let &y = &vec; 
let _:() = y; 

otteniamo:

<anon>:5:17: 5:18 error: mismatched types: 
expected `()`, 
    found `collections::vec::Vec<_>` 
(expected(), 
    found struct `collections::vec::Vec`) [E0308] 
<anon>:5  let _:() = y; 
         ^
<anon>:5:17: 5:18 help: see the detailed explanation for E0308 

il tipo di y è Vec<i32>.

Che cosa significa è che siete:

  1. Prestito vec in una temporanea
  2. Cercando di spostare vec in y, che è proibito perché vec è già preso in prestito.

Il codice corretto equivalente sarebbe:

let vec = vec![1, 2, 3]; 
let y = vec; 

Nel secondo esempio:

let vec = vec![1, 2, 3]; 
let ref y = &vec; 
let _:() = y; 

otteniamo:

<anon>:5:17: 5:18 error: mismatched types: 
expected `()`, 
    found `&&collections::vec::Vec<_>` 
(expected(), 
    found &-ptr) [E0308] 
<anon>:5  let _:() = y; 
         ^
<anon>:5:17: 5:18 help: see the detailed explanation for E0308 

Quindi è &&Vec<i32>.

Questo ci permette di vedere che let ref a = b; è generalmente equivalente a let a = &b;, e quindi in questo caso: let y = &&vec;.

ref è realizzato per destrutturazione; per esempio, se si ha:

let vec = Some(vec![1, 2, 3]); 
if let Some(ref y) = vec { 
} 

si usa ref qui per essere in grado di legarsi a ysenza muoversi anche se vec ha qui Tipo Option<Vec<i32>>. Infatti, lo scopo di ref è di prendere un riferimento all'interno di un oggetto esistente durante la destrutturazione.

In generale, in un'istruzione let, non verrà utilizzato ref.

+0

C'è un caso legit dove vogliamo usare qualcosa come 'Let & y = &vec;'? – WiSaGaN

+0

@WiSaGaN: Non riesco a pensare a nessuno. –

+0

@WiSaGaN: questa costruzione può essere utilizzata ad esempio nelle chiusure. È usato nella funzione di ritenzione in Vec e così via. –

1

Prima di tutto, non è necessario il & nel tuo esempio di lavoro. Se lo usi, finisci con uno &&Vec<_>, di cui non hai veramente bisogno.

let vec = vec![1, 2, 3]; 
let ref y = vec; 

Il problema con il primo codice è che si stanno facendo due cose contemporaneamente. Consente lo scompone in due:

La prima parte crea un riferimento vec

let y1 = &vec; 

La seconda parte (la & prima della variabile vincolante), destructures.

let &y2 = y1; 

Questo significa che si sta cercando di uscire dal riferimento, che funziona solo se il tipo è Copy, perché allora ogni tentativo di spostare copierà l'oggetto invece.

2

Lo stesso simbolo (&) sta facendo due cose diverse quando viene utilizzato sul lato destro e sul lato sinistro di una rilegatura. Il lato sinistro funziona come un pattern matching, quindi:

let x = (y, z); // x contains a tuple with value (y, z) 
let (a, b) = x // x is destructured into (a, b), so now 
       // a has value y and b has value z 

Analogamente

let x = &y; // x is a reference to y 
let &z = x; // this is like let &z= &y, so we want z to be y 
      // this is equivalent to let z = *x 

Un ref rilegatura sul lato sinistro si dice "pattern matching per riferimento, non per valore" . Quindi queste due affermazioni sono equivalenti:

let ref y = vec; 
let y = &vec; 

sebbene in un let, il secondo è più idiomatico.

Si può vedere più esempi sul pointers/ref chapter on rust by example

Problemi correlati