在锈蚀中传递闭包是非常简单的,但是当存储闭包供重用时,有多种解决方案(使用泛型函数类型、引用闭包或方框、是否使用'static生存期的box?)。
虽然我已经多次使用不同类型的框,阅读类似的Q&A,甚至在回答这个问题时可能会有一个猜测。我对如何处理这个问题没有任何感觉,即使是简单/明显的情况,也没有一个好的起点。
为了使这个问题更加具体,如何使这个示例存储函数用于重用,使用构建器模式来存储闭包,以便稍后调用。
// This example looks a bit long but its really very simple.
// * This example is most of the way to implementing the builder pattern,
// it ust runs the code immediately instead of storing input
// to run on `build()`.
// * Changes should only be needed where the comment `stored closures:`
// has been written.
// * I've attempted to make this example as generic as possible,
// but not _so_ simple that the answer wont apply to real-world use (hopefully!).
struct MyActions {
num: i32,
times: i32,
// stored closures: should be stored here.
// update_fn: Option<Fn(...)>,
// twiddle_fn: Option<Fn(...)>,
}
impl MyActions {
pub fn new(num: i32) -> Self {
return MyActions {
num: num,
times: 1,
}
}
pub fn build(self) -> i32 {
// stored closures:
// should run both actions if they're defined and return the result.
return self.num;
}
pub fn num_times(mut self, times: i32) -> Self {
self.times = times;
self
}
pub fn num_update<F>(mut self, func: F) -> Self
where
F: Fn(i32) -> i32
{
// stored closures: run immediately for now
for _ in 0..self.times {
self.num = func(self.num);
}
self
}
pub fn num_twiddle<F>(mut self, func: F) -> Self
where
F: Fn(i32) -> i32
{
// stored closures: run immediately for now
for _ in 0..self.times {
self.num = func(self.num);
}
self
}
}
// no changes needed here
fn main() {
let act = MyActions::new(133);
let num_other: i32 = 4;
// builder pattern (currently executes immediately).
let result = act
.num_times(8)
.num_update(|x| x * 2 + num_other)
.num_twiddle(|x| (((x / 2) - 1) ^ (x + 1)) ^ num_other)
.build();
// Lets say we would want this example to work,
// where 'times' is set after defining both functions.
/*
let result = act
.num_update(|x| x * 2 + num_other)
.num_twiddle(|x| (((x / 2) - 1) ^ (x + 1)) ^ num_other)
.num_times(8) // <-- order changed here
.build();
*/
println!("done: {}", result);
}发布于 2017-01-19 13:47:06
为了完整起见,由于闭包所有权的一些语法并不明显,下面是我在这个问题中尝试使用代码的惯用/乡村版本。
(如有任何问题,请直接评论或更新)。
'static,这允许调用者在其环境中使用变量(请参阅问题中的num_other使用)。相反,在struct上使用一个生命周期。使用盒式闭包继承容器结构生存期的工作示例:
use std::boxed::Box;
struct MyActions<'a> {
num: i32,
times: i32,
update_fn: Option<Box<dyn Fn(i32) -> i32 + 'a>>,
twiddle_fn: Option<Box<dyn Fn(i32) -> i32 + 'a>>,
}
impl <'a> MyActions<'a> {
pub fn new(num: i32) -> Self {
return MyActions {
num: num,
times: 1,
update_fn: None,
twiddle_fn: None,
}
}
pub fn build(self) -> i32 {
let mut num = self.num;
if let Some(update_fn) = self.update_fn {
for _ in 0..self.times {
num = update_fn(num);
}
}
if let Some(twiddle_fn) = self.twiddle_fn {
for _ in 0..self.times {
num = twiddle_fn(num);
}
}
return num;
}
pub fn num_times(mut self, times: i32) -> Self {
self.times = times;
self
}
pub fn num_update<F>(mut self, func: F) -> Self
where
F: 'a,
F: Fn(i32) -> i32,
{
self.update_fn = Some(Box::new(func));
self
}
pub fn num_twiddle<F>(mut self, func: F) -> Self
where
F: 'a,
F: Fn(i32) -> i32,
{
self.twiddle_fn = Some(Box::new(func));
self
}
}
// no changes needed here
fn main() {
let act = MyActions::new(133);
let num_other: i32 = 4;
// builder pattern (currently executes immediately).
let result = act
.num_times(8)
.num_update(|x| x * 2 + num_other)
.num_twiddle(|x| (((x / 2) - 1) ^ (x + 1)) ^ num_other)
.build();
println!("done: {}", result);
// Lets say we would want this example to work,
// where 'times' is set after defining both functions.
let act = MyActions::new(133);
let result = act
.num_update(|x| x * 2 + num_other)
.num_twiddle(|x| (((x / 2) - 1) ^ (x + 1)) ^ num_other)
.num_times(8) // <-- order changed here
.build();
println!("done: {}", result);
}https://stackoverflow.com/questions/41738049
复制相似问题