2014-11-22 15 views
9

Dato il seguente programma di ruggine:Come passare una funzione come argomento di Rust

fn call_twice<A>(val: A, f: fn(A) -> A) -> A { 
    f(f(val)) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    // println!("Res is {}", call_twice(10i, (x: int) -> int {x + x})); 
    //^this line will fail 
} 

Perché posso passare double come la funzione, ma non inline? Qual è un buon modo per ottenere lo stesso comportamento senza definire la funzione da qualche parte?

risposta

13

2016-04-01 Aggiornamento:

Come di Rust 1.0, il codice dovrebbe essere simile a questo:

fn call_twice<A, F>(val: A, mut f: F) -> A 
where F: FnMut(A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: i32) -> i32 {x + x}; 
    println!("Res is {}", call_twice(10, double)); 
    println!("Res is {}", call_twice(10, |x| x + x)); 
} 

La modifica del parametro di chiusura è perché la chiusura sono ora unboxed .

originale:

Per quanto ne so, non è possibile definire le funzioni in linea in quel modo.

Quello che desidera è una chiusura. Le seguenti opere:

fn call_twice<A>(val: A, f: |A| -> A) -> A { 
    let tmp = f(val); 
    f(tmp) 
} 

fn main() { 
    fn double(x: int) -> int {x + x}; 
    println!("Res is {}", call_twice(10i, double)); 
    println!("Res is {}", call_twice(10i, |x| x + x)); 
} 

Ci sono alcune cose da notare:

  1. funzioni costringono alla chiusura, ma il contrario non è vero.

  2. È necessario memorizzare il risultato di f(val) in modo temporaneo a causa delle regole sul prestito. Versione breve: è necessario un accesso univoco a una chiusura per chiamarla, e il controllore del prestito non è abbastanza intelligente per realizzare che le due chiamate sono indipendenti nelle loro posizioni originali.

  3. Le chiusure sono in fase di sostituzione da chiusure unboxed, quindi questo cambierà in futuro, ma non siamo ancora arrivati.

+0

Grazie per la spiegazione. È un po 'strano con la variabile temporanea, ma penso che verrà risolto in una versione più stabile. –

+0

Questo non sembra funzionare con ruggine 1.7: https://play.rust-lang.org/?gist=ad35b80eeae1d1966944a66a75d0ad80&version=stable –

+2

@SandeepDatta Questa risposta è del 2014; questo codice non sarebbe stato valido nemmeno in Rust 1.0. L'ho aggiornato. –

Problemi correlati