2015-06-09 18 views
6

Nel Rust Book c'è un esempio di chiamata filter() su un iteratore:Qual è la differenza tra filtro (| x |) e filtro (| & x |)?

for i in (1..100).filter(|&x| x % 2 == 0) { 
    println!("{}", i); 
} 

C'è una spiegazione al di sotto, ma sto avendo difficoltà a capire è:

This will print all of the even numbers between one and a hundred. (Note that because filter doesn't consume the elements that are being iterated over, it is passed a reference to each element, and thus the filter predicate uses the &x pattern to extract the integer itself.)

Questo, però non funziona :

for i in (1..100).filter(|&x| *x % 2 == 0) { 
    println!("i={}", i); 
} 

Perché è l'argomento alla chiusura un riferimento |&x|, inst ead di |x|? E qual è la differenza tra l'utilizzo di |&x| e |x|?

ho capito che l'utilizzo di un riferimento |&x| è più efficiente, ma sono perplesso dal fatto che non ho avuto a dereference il puntatore x utilizzando *x.

risposta

8

Quando utilizzato come pattern matching (e chiusura e funzionali argomenti sono anche pattern corrisponde), il &lega ad un riferimento, rendendo la variabile deindirizzato valore.

fn main() { 
    let an_int: u8 = 42; 
    // Note that the `&` is on the right side of the `:` 
    let ref_to_int: &u8 = &an_int; 
    // Note that the `&` is on the left side of the `:` 
    let &another_int = ref_to_int; 
    let() = another_int; 
} 

Ha l'errore:

error: mismatched types: 
expected `u8`, 
    found `()` 

Se guardate il vostro messaggio di errore per il vostro caso, indica che non si può dereferenziarlo, perché non è un riferimento:

error: type `_` cannot be dereferenced 

I didn't have to dereference the x pointer by using *x.

Questo perché implicitamente dereferenziato nel partita di modello.

I understand that using a reference |&x| is more efficient

Se ciò fosse vero, allora non ci sarebbe motivo di usare altro che riferimenti! Vale a dire, i riferimenti richiedono un'ulteriore indiretta per ottenere i dati reali. Esiste un punto di misura misurabile in cui il passaggio degli articoli in base al valore è più efficiente rispetto al passaggio dei riferimenti ad essi.

If so, why does using |x| not throw an error? From my experience with C, I would expect to receive a pointer here.

E si fa, nella forma di un di riferimento. x è un riferimento a (in questo esempio) un i32. Tuttavia, l'operatore % è fornito dal tratto Rem, che viene realizzato per tutte le coppie di riferimento/valore:

impl Rem<i32> for i32 
impl<'a> Rem<i32> for &'a i32 
impl<'a> Rem<&'a i32> for i32 
impl<'a, 'b> Rem<&'a i32> for &'b i32 

Questo permette di non è necessario in modo esplicito dereferenziarlo.

Or does Rust implicitly allocate a copy of value of the original x on the stack here?

Lo fa con enfasi non farlo. In effetti, non sarebbe sicuro farlo, a meno che gli articoli iterati non implementassero Copy (o potenzialmente Clone, nel qual caso potrebbe anche essere costoso). Questo è il motivo per cui i riferimenti sono usati come argomento di chiusura.

+0

Quindi 'let & x = my_pointer' è in realtà un'alternativa a' let x = * my_pointer', e funziona anche nelle dichiarazioni dei parametri di funzione? In tal caso, perché usare '| x |' non genera un errore? Dalla mia esperienza con C, mi aspetto di ricevere un puntatore qui. O arrugginisce implicitamente allocare una copia del valore dell'originale 'x' in pila qui? – jeremija

+0

Ohhh, ho molto da imparare :) Grazie - ora è molto più chiaro! – jeremija

Problemi correlati