2016-04-03 21 views
13

Posso passare una funzione come parametro in Rust (probabilmente sì), se possibile, come posso fare.In Rust come si passa una funzione come parametro?

Se non ci riesci, che è una buona alternativa.

Ho provato alcuni sintassi, ma non ho ottenuto


So che posso fare questo

..// 

let fun: fn(value: i32) -> i32; 
fun = funTest; 
fun(5i32); 

..// 
fn funTest(value: i32) -> i32 { 
    println!("{}", value); 
    value 
} 

ma non come passare la funzione come parametro a un'altra funzione

..// 
fn funTest(value: i32, (some_function_prototype)) -> i32 { 
    println!("{}", value); 
    value 
} 

risposta

22

Sicuro che è possibile:

fn funTest(value: i32, f: &Fn(i32) -> i32) -> i32 { 
    println!("{}", f(value)); 
    value 
} 

fn times2(value: i32) -> i32 { 
    2 * value 
} 

fn main() { 
    funTest(5, &times2); 
} 

Ma questo è Rust quindi è necessario prendere in considerazione il ownership and lifetime of the closure.

TL; DR; Fondamentalmente ci sono 3 tipi di chiusure (oggetti chiamabili):

  1. Fn: Il più generico, è una funzione pura.
  2. FnMut: Può modificare gli oggetti catturati.
  3. FnOnce: il più limitato. Può essere chiamato solo una volta perché quando viene chiamato consuma se stesso e le sue acquisizioni.

Se si utilizza un semplice puntatore come chiusura, il set di acquisizione è vuoto e si ha il sapore Fn.

Se vuoi fare cose più fantasiose, dovrai utilizzare le funzioni lambda.

+0

c'è una differenza nell'uso di oppure no (.., f: & Fn ...) le due opere, alcuni dettagli che ho bisogno di sapere? –

+0

@AngelAngel: Beh, 'Fn *' sono tratti, quindi si applica il solito '' vs '(t: & T)'. Il limite principale della soluzione non generica è che deve essere utilizzato con riferimenti. Quindi se vuoi 'FnOnce', che dovrebbe essere passato come copia, devi usare lo stile generico. – rodrigo

+2

Si noti che è più idiomatico usare i generici invece degli oggetti tratti (cioè '' invece di '(f: & Fn ...)'. E questo è per una ragione - i generici generano un invio statico, mentre gli oggetti tratti richiedono spedizione dinamica. –

6

Fn, FnMut e FnOnce, indicato nel altra risposta, sono chiusura tipi. I tipi di funzioni che si chiudono nel loro ambito.

Oltre a chiusure passeggera ruggine supporta anche passando funzioni semplici (non-chiusura), in questo modo:

fn times2(value: i32) -> i32 { 
    2 * value 
} 

fn fun_test(value: i32, f: fn(i32) -> i32) -> i32 { 
    println!("{}", f (value)); 
    value 
} 

fn main() { 
    fun_test (2, times2); 
} 

fn(i32) -> i32 ecco un function pointer type.

Se non si ha bisogno di una chiusura completa rispetto a lavorare con i tipi di funzione è spesso più semplice in quanto non deve occuparsi di quelle nicchie di chiusura.

Problemi correlati