Last active
September 26, 2022 15:37
-
-
Save nomyfan/e49941b5c7807f1e4bce064d17f1b0d0 to your computer and use it in GitHub Desktop.
Rust Fn vs. FnMut vs. FnOnce
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[derive(Copy, Clone)] | |
struct Foo { | |
val: i32, | |
} | |
impl Foo { | |
fn new(val: i32) -> Self { | |
Foo { val } | |
} | |
} | |
struct Foo1 { | |
val: i32, | |
} | |
fn impl_fn_mut_trait<F: FnMut()>(_closure: &F) {} | |
fn impl_fn_once_trait<F: FnOnce()>(_closure: &F) {} | |
fn impl_fn_trait<F: Fn()>(_closure: &F) {} | |
fn impl_copy_trait<F: Copy>(_closure: &F) {} | |
fn run_fn_once<F: FnOnce()>(f: F) { | |
f(); | |
// f(); // Compile error | |
} | |
fn run_fn_mut<F: FnMut()>(mut f: F) { | |
f(); | |
f(); | |
} | |
fn run_fn<F: Fn()>(f: F) { | |
f(); | |
f(); | |
} | |
// Q:为什么捕获的变量Copy了,那么闭包就实现了Copy trait? | |
// A:如果捕获的变量都可以copy,那么意味着匿名闭包结构体也可以copy。 | |
fn main() { | |
let mut foo = Foo::new(0); | |
// impl FnMut + Copy | |
let mut closure1 = move || { // move会触发foo的copy | |
foo.val += 1; | |
}; | |
impl_fn_mut_trait(&closure1); | |
impl_copy_trait(&closure1); | |
impl_fn_once_trait(&closure1); | |
// impl_fn_trait(&closure1); // Not satisfied. | |
closure1(); | |
closure1(); | |
println!("closure1 {}", &foo.val); | |
let mut foo = Foo::new(0); | |
// impl FnMut | |
let mut closure2 = || { // 这个闭包只是对foo使用了mut借用语义 | |
foo.val += 1; | |
}; | |
impl_fn_mut_trait(&closure2); | |
// impl_copy_trait(&closure2); // Not implemented. | |
impl_fn_once_trait(&closure2); | |
// impl_fn_trait(&closure2); // Not satisfied. | |
closure2(); | |
closure2(); | |
println!("closure2 {}", &foo.val); | |
let foo = Foo::new(0); | |
// impl Fn + Copy | |
let closure3 = move || { | |
println!("println! in closure3 {}", foo.val); | |
}; | |
impl_fn_mut_trait(&closure3); | |
impl_copy_trait(&closure3); | |
impl_fn_once_trait(&closure3); | |
impl_fn_trait(&closure3); | |
closure3(); | |
closure3(); | |
println!("{}", &foo.val); | |
let mut foo = Foo1 { val: 0 }; | |
// impl FnMut | |
let mut closure4 = move || { | |
foo.val += 1; | |
println!("println! in closure4 {}", foo.val); | |
}; | |
impl_fn_mut_trait(&closure4); | |
// impl_copy_trait(&closure4); | |
impl_fn_once_trait(&closure4); | |
// impl_fn_trait(&closure4); | |
closure4(); | |
closure4(); | |
// println!("{}", &foo.val); // Borrow error | |
let mut foo = Foo1 {val: 0}; | |
// impl FnOnce | |
let closure5 = move || { | |
foo.val += 1; | |
println!("println! in closure5 {}", foo.val); | |
drop(foo); | |
}; | |
// impl_fn_mut_trait(&closure5); | |
// impl_copy_trait(&closure5); | |
impl_fn_once_trait(&closure5); | |
// impl_fn_trait(&closure5); | |
closure5(); | |
// closure5(); // Compile error, it's FnOnce | |
// println!("closure5 {}", &foo.val); // Borrow error | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment