ops function
1 - trait core::ops::FnOnce
源码
Trait core::ops::FnOnce
的定义如下:
pub trait FnOnce<Args> {
/// The returned type after the call operator is used.
#[lang = "fn_once_output"]
#[stable(feature = "fn_once_output", since = "1.12.0")]
type Output;
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
官方文档
https://doc.rust-lang.org/core/ops/trait.FnOnce.html
具有按值接收者的调用运算符的版本。
可以调用 FnOnce
的实例,但可能无法多次调用。因此,如果唯一知道类型的是它实现 FnOnce
,则只能调用一次。
FnOnce
由可能消耗捕获变量的闭包以及实现 FnMut
的所有类型 (例如 (safe) 函数指针 (因为 FnOnce
是 FnMut
的特征) ) 自动实现。
由于 Fn
和 FnMut
都是 FnOnce
的子特性,因此可以在期望使用 FnOnce
的情况下使用 Fn
或 FnMut
的任何实例。
当您想接受类似函数类型的参数并且只需要调用一次时,可以使用 FnOnce
作为绑定。 如果需要重复调用该参数,请使用 FnMut
作为界限; 如果还需要它不改变状态,请使用 Fn
。
有关此主题的更多信息,请参见 Rust 编程语言 中关于闭包的章节。
还要注意的是 Fn
traits 的特殊语法 (例如 Fn(usize, bool) -> usize
)。对此技术细节感兴趣的人可以参考 Rustonomicon 中的相关部分。
示例
使用 FnOnce 参数:
fn consume_with_relish<F>(func: F)
where F: FnOnce() -> String
{
// `func` 使用其捕获的变量,因此不能多次运行。
println!("Consumed: {}", func());
println!("Delicious!");
// 再次尝试调用 `func()` 将为 `func` 引发 `use of moved value` 错误。
}
let x = String::from("x");
let consume_and_return_x = move || x;
consume_with_relish(consume_and_return_x);
// `consume_and_return_x` 现在不能再被调用
2 - trait core::ops::FnMut
源码
Trait core::ops::FnMut
的定义如下:
pub trait FnMut<Args>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
官方文档
https://doc.rust-lang.org/core/ops/trait.Fn.html
采用可变接收者的调用运算符的版本。
FnMut
的实例可以重复调用,并且可以改变状态。
FnMut
由闭包自动实现,闭包将可变引用引用到捕获的变量,以及实现 Fn
的所有类型,例如 (safe) 函数指针 (因为 FnMut
是 Fn
的特征)。 另外,对于任何实现 FnMut
的 F
类型,&mut F
也实现 FnMut
。
由于 FnOnce
是 FnMut
的 super trait,因此可以在期望 FnOnce
的地方使用 FnMut
的任何实例,并且由于 Fn
是 FnMut
的子特性,因此可以在预期 FnMut
的地方使用 Fn
的任何实例。
当您想接受类似函数类型的参数并需要反复调用它,同时允许其改变状态时,请使用 FnMut
作为绑定。 如果您不希望参数改变状态,请使用 Fn
作为绑定; 如果不需要重复调用,请使用 FnOnce
。
有关此主题的更多信息,请参见 Rust 编程语言 中关于闭包的章节。
还要注意的是 Fn
traits 的特殊语法 (例如 Fn(usize, bool) -> usize
)。对此技术细节感兴趣的人可以参考 Rustonomicon 中的相关部分。
示例
调用可变捕获闭包
let mut x = 5;
{
let mut square_x = || x *= x;
square_x();
}
assert_eq!(x, 25);
使用 Fn 参数:
fn call_with_one<F>(func: F) -> usize
where F: Fn(usize) -> usize {
func(1)
}
let double = |x| x * 2;
assert_eq!(call_with_one(double), 2);
3 - trait core::ops::Fn
源码
Trait core::ops::Fn
的定义如下:
pub trait Fn<Args>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
官方文档
https://doc.rust-lang.org/core/ops/trait.Fn.html
采用不可变接收者的调用运算符的版本。
Fn
的实例可以在不改变状态的情况下重复调用。
请勿将此 trait (Fn
) 与 函数指针 (fn
) 混淆。
Fn
由闭包自动实现,闭包只对捕获的变量进行不可变引用或根本不捕获任何内容,还有 (安全) 函数指针 (有一些警告,请参见其文档以获取更多详细信息)。
此外,对于实现 Fn
的任何类型 F
,&F
也实现了 Fn
。
由于 FnMut
和 FnOnce
都是 Fn
的 supertraits,因此 Fn
的任何实例都可以用作参数,其中需要 FnMut
或 FnOnce
。
当您要接受类似函数类型的参数并且需要反复调用且不改变状态 (例如,同时调用它) 时,请使用 Fn
作为绑定。 如果不需要严格的要求,请使用 FnMut
或 FnOnce
作为界限。
有关此主题的更多信息,请参见 Rust 编程语言 中关于闭包的章节。
还要注意的是 Fn
traits 的特殊语法 (例如 Fn(usize, bool) -> usize
)。对此技术细节感兴趣的人可以参考 Rustonomicon 中的相关部分。
示例
调用一个闭包:
let square = |x| x * x;
assert_eq!(square(5), 25);
使用 Fn 参数:
fn call_with_one<F>(func: F) -> usize
where F: Fn(usize) -> usize {
func(1)
}
let double = |x| x * 2;
assert_eq!(call_with_one(double), 2);