2015-04-10 7 views
6

Grundsätzlich möchte ich eine Funktion schreiben, die eine Schließung zurückgibt. Wie kann ich das tun, ohne Box<FnOnce(u32)> zurückgeben zu müssen?Wie erstellt man eine Größe Schließung oder implementieren Sie Fn/FnMut/FnOnce auf einer Struktur?

Aus der closures chapter of the rust book, ich lese, dass ein Abschluss ist nur syntaktischer Zucker für eine Struktur und ein Impl von FnOnce. Hier ist mein Versuch:

#[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(); 
} 

Aktuelle Zeit einen Fehler gibt:

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

Antwort

7

Die Syntax für manuell Fn* Merkmal auf einer Struktur Implementierung ist diese:

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

Hinweis dass alle Argumente als einzelnes Tupel angegeben sind.

Auch diese Syntax ist instabil und erfordern #![feature(core, unboxed_closures)], so dass Sie es nicht auf dem Beta-Kanal, nur Nightlies verwenden können.

In Ihrem Fall würde es wie folgt übersetzen:

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

Ist es unmöglich, 'Fn *' in stabiler zu implementieren? – Kapichu

+0

@Kapichu Es scheint so: Die Dokumente für die Methode ['call_once'] (https://doc.rust-lang.org/std/ops/trait.FnOnce.html#typmethod.call_once) verweisen auf [# 29625 ] (https://github.com/rust-lang/rust/issues/29625), die noch offen ist. –

Verwandte Themen