2017-05-16 3 views
2

hier ein funktionstüchtiges Beispiel Runnable für Fn() implementieren (so dass wir direkt einen & Schluß zur run_the_runnable Funktion übergeben können):Implementierung Merkmal ist für Fn (& etwas) in Rust

trait Runnable { 
    fn run(&self); 
} 

impl<F> Runnable for F where F: Fn() { 
    fn run(&self) { 
     self(); 
    } 
} 

fn run_the_runnable(runnable: &Runnable) { 
    runnable.run(); 
} 

fn main() { 
    // runnable without parameters 
    struct MyRunnable; 
    impl Runnable for MyRunnable { 
     fn run(&self) { 
      println!("Hello from MyRunnable"); 
     } 
    } 

    // from struct instance (WORKS) 
    run_the_runnable(&MyRunnable); 

    // from closure (WORKS) 
    run_the_runnable(&|| { 
     println!("Hello from run() closure"); 
    }); 
} 

(Rust playground)

Jetzt

, lassen Sie sich die runnable run() Verfahren ändern, um einen Referenzparameter (&i32) zu akzeptieren und implementieren Fn(&i32):

trait Runnable { 
    fn run(&self, x: &i32); 
} 

impl<F> Runnable for F where F: Fn(&i32) { 
    fn run(&self, x: &i32) { 
     self(x); 
    } 
} 

fn run_the_runnable(runnable: &Runnable, x: &i32) { 
    runnable.run(x); 
} 

fn main() { 
    // runnable without parameters 
    struct MyRunnable; 
    impl Runnable for MyRunnable { 
     fn run(&self, x: &i32) { 
      println!("Hello from MyRunnable {}", x); 
     } 
    } 

    let x = 42; 

    // from struct instance (WORKS) 
    run_the_runnable(&MyRunnable, &x); 

    // from closure (DOES NOT WORK) 
    run_the_runnable(&|x| { 
     println!("Hello from run(&i32) closure {}", x); 
    }, &x); 
} 

(Rust playground)

die Schließung Passing funktioniert nicht mehr:

error[E0271]: type mismatch resolving `for<'r> <[[email protected]<anon>:30:27: 32:10] as std::ops::FnOnce<(&'r i32,)>>::Output ==()` 
    --> <anon>:30:26 
    | 
30 |   run_the_runnable(&|x| { 
    | __________________________^ starting here... 
31 | |    println!("Hello from run(&i32) closure {}", x); 
32 | |   }, &x); 
    | |_________^ ...ending here: expected bound lifetime parameter , found concrete lifetime 
    | 
    = note: concrete lifetime that was found is lifetime '_#63r 
    = note: required because of the requirements on the impl of `Runnable` for `[[email protected]<anon>:30:27: 32:10]` 
    = note: required for the cast to the object type `Runnable` 

error[E0281]: type mismatch: the type `[[email protected]<anon>:30:27: 32:10]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r i32,)>` is required (expected concrete lifetime, found bound lifetime parameter) 
    --> <anon>:30:26 
    | 
30 |   run_the_runnable(&|x| { 
    | __________________________^ starting here... 
31 | |    println!("Hello from run(&i32) closure {}", x); 
32 | |   }, &x); 
    | |_________^ ...ending here 
    | 
    = note: required because of the requirements on the impl of `Runnable` for `[[email protected]<anon>:30:27: 32:10]` 
    = note: required for the cast to the object type `Runnable` 

Es gibt viele Fragen zu diesem Fehler:

Aber ich bin immer noch dieses spezifische Lebensdauer zu lösen Problem nicht in der Lage.

+2

Hinzufügen von expliziten Typenannotationen helfen. Sagen Sie zum Beispiel '& | x: & i32 | {...} 'löst das Problem bereits. Rust scheint Probleme zu haben, Typen in diesen Situationen zu folgern:/zumindest denke ich, dass das Problem ist. –

Antwort

2

Wie vorgeschlagen in einem comment, die explizite Art in dem Verschluss Parameter geben behebt das Problem:

@@ -26,8 +26,8 @@ fn main() { 
    // from struct instance (WORKS) 
    run_the_runnable(&MyRunnable, &x); 

- // from closure (DOES NOT WORK) 
- run_the_runnable(&|x| { 
+ // from closure with annotated type (WORKS) 
+ run_the_runnable(&|x: &i32| { 
     println!("Hello from run(&i32) closure {}", x); 
    }, &x); 
} 

(Rust playground)

Verwandte Themen