随着我继续学习 Rust,我正在从事一个涉及广泛使用谓词函数的项目。我决定用 Rust 闭包来实现这些谓词,例如:
type Predicate = Box<Fn(&Form) -> bool>
.
我的程序使用应用于这些谓词的布尔逻辑。例如,两者and
以及or
都应用于这些谓词的值。我使用以下方法完成了这项工作Box::leak
:
struct Form {
name: String,
}
fn and(a: Option<Predicate>, b: Option<Predicate>) -> Option<Predicate> {
if a.is_none() {
return b;
} else if b.is_none() {
return a;
} else {
let a = Box::leak(a.unwrap());
let b = Box::leak(b.unwrap());
return Some(Box::new(move |form: &Form| a(form) && b(form)));
}
}
虽然这似乎可以按我Box::leak
的意愿工作,但似乎并不理想。我不太了解std::rc::Rc
并且std::cell::RefCell
不知道这些是否可以帮助我避免Box::leak
在这里使用它们可能需要对我的代码进行重大重组,但我想至少了解这里的惯用方法可能是什么。
有没有办法在保持相同功能的同时避免泄漏?
这是完整的示例:
struct Form {
name: String,
}
type Predicate = Box<Fn(&Form) -> bool>;
struct Foo {
predicates: Vec<Predicate>,
}
impl Foo {
fn and(a: Option<Predicate>, b: Option<Predicate>) -> Option<Predicate> {
if a.is_none() {
return b;
} else if b.is_none() {
return a;
} else {
let a = Box::leak(a.unwrap());
let b = Box::leak(b.unwrap());
return Some(Box::new(move |form: &Form| a(form) && b(form)));
}
}
}
fn main() {
let pred = Foo::and(
Some(Box::new(move |form: &Form| {
form.name == String::from("bar")
})),
Some(Box::new(move |_: &Form| true)),
)
.unwrap();
let foo = Foo {
predicates: vec![pred],
};
let pred = &foo.predicates[0];
let form_a = &Form {
name: String::from("bar"),
};
let form_b = &Form {
name: String::from("baz"),
};
assert_eq!(pred(form_a), true);
assert_eq!(pred(form_b), false);
}