2015-04-10 10 views
6

Fondamentalmente, voglio scrivere una funzione che restituisce una chiusura. Come posso fare questo senza dover restituire Box<FnOnce(u32)>?Come creare una chiusura di dimensioni o implementare Fn/FnMut/FnOnce su una struttura?

Da closures chapter of the rust book, ho letto che una chiusura è solo zucchero sintattico per una struttura e un impianto di FnOnce. Qui è il mio tentativo:

#[derive(Debug)] 
struct MyError { 
    code: u32, 
    location: &'static str, 
} 
// Here is my closure: 
struct MyErrorPartial { 
    location: &'static str, 
} 
impl FnOnce(u32) for MyErrorPartial { 
    type Output = MyError; 

    fn call_once(self, args: u32) -> MyError { 
     MyError { 
      code: args, 
      location: self.location, 
     } 
    } 
} 
fn error_at(location: &'static str) -> MyErrorPartial { 
    MyErrorPartial {location: location} 
} 

fn function_returning_code() -> Result<(), u32> { 
    Err(123) 
} 
fn function_with_error() -> Result<(), MyError> { 
    try!(function_returning_code().map_err(error_at("line1"))); 
    try!(function_returning_code().map_err(error_at("line2"))); 
    Ok(()) 
} 
fn main() { 
    function_with_error().unwrap(); 
} 

Attualmente dà un errore:

<anon>:11:12: 11:17 error: associated type bindings are not allowed here [E0229] 
<anon>:11 impl FnOnce(u32) for MyErrorPartial { 
        ^~~~~ 

risposta

7

La sintassi per l'attuazione manuale di un Fn* tratto su una struct è questa:

impl FnOnce<(Arg1,Arg2,Arg3,)> for MyStruct { 
    type Output = MyOutput; 
    extern "rust-call" fn call_once(args: (Arg1, Arg2, Arg3,)) -> MyOutput { 
     // implementation here 
    } 
} 

Nota che tutti gli argomenti sono dati come una singola tupla.

Inoltre, questa sintassi è instabile e richiede #![feature(core, unboxed_closures)], quindi non è possibile utilizzarlo sul canale beta, solo notturni.

In te caso, sarebbe tradurre in questo modo:

impl FnOnce<(u32,)> for MyErrorPartial { 
    type Output = MyError; 

    extern "rust-call" fn call_once(self, args: (u32,)) -> MyError { 
     MyError { 
      code: args.0, 
      location: self.location, 
     } 
    } 
} 
+4

E 'impossibile implementare 'Fn *' in stabile? – Kapichu

+0

@Kapichu Appare così: i documenti per il collegamento del metodo ['call_once'] (https://doc.rust-lang.org/std/ops/trait.FnOnce.html#tymethod.call_once) al numero [# 29625 ] (https://github.com/rust-lang/rust/issues/29625), che è ancora aperto. –

Problemi correlati