英文:
Efficiently reusing unwrapped Option variable based on a condition in Rust
问题
在Rust中,我有一个名为pb
的Option
变量,我需要在代码的多个部分中使用它。然而,我不想每次访问pb
以获取解包后的值时都重复解包的逻辑,当变量progress_bar_on
为true
时,我希望pb
应该有一个值。是否有一种干净而高效的方法,在代码中解包pb
一次,然后在整个代码中使用解包后的值,而不会用重复的匹配语句使代码混乱?
这是一个示例:
// ...
let pb = if progress_bar_on {
// ...
Some(tmp_pb)
} else {
None
}
if progress_bar_on {
pb.unwrap().update_var();
pb.unwrap().set_val();
}
// 更多的代码
// ...
if progress_bar_on {
pb.unwrap().set_val();
}
// 更多的代码
// ...
if progress_bar_on {
pb.unwrap().update_var();
}
我刚学到的一种感觉更清晰的方法是:
if let Some(pb) =
progress_bar_on.then(|| pb.unwrap())
{
pb.set_style(style_overall);
pb.set_message("Copying files...");
pb.set_length(src_n_files);
}
这是最干净的方法吗?还有更好的方法吗?
任何见解或建议将不胜感激。谢谢!
英文:
I have an Option
variable pb
in Rust that I need to use in multiple parts of my code. However, I don't want to repeat the unwrapping logic each time I access pb
to obtain the unwrapped value, when I now once the variable progress_var_on
is true
, pb
should have a value. Is there a clean and efficient way to unwrap pb
once and use the unwrapped value throughout my code without cluttering it with repeated match statements?
Here is an example:
// ...
let pb = if progress_bar_on {
// ...
Some(tmp_pb)
} else {
None
}
if progress_bar_on {
pb.unwrap().update_var();
pb.unwrap().set_val();
}
// more code
// ...
if progress_bar_on {
pb.unwrap().set_val();
}
// more code
// ...
if progress_bar_on {
pb.unwrap().update_var();
}
Something I just learn, and it feels cleaner is the next:
if let Some(pb) =
progress_bar_on.then(|| pb.unwrap())
{
pb.set_style(style_overall);
pb.set_message("Copying files...");
pb.set_length(src_n_files);
}
Is this the cleanest way? or there is a better way?
Any insights or suggestions would be highly appreciated. Thank you!
答案1
得分: 1
你实际上是将布尔值 progress_bar_on
转换为一个 Option
,因此你应该使用 Option
。
if let Some(pb) = pb {
pb.update_var();
}
然而,这仍然不够清晰,每次使用 pb
时仍然需要进行检查。更健壮的方式是创建一个 trait。
trait ProgressBar: Default {
fn update_var(&mut self);
fn set_val(&mut self);
}
#[derive(Default)]
struct RealProgressBar {
progress: u32,
}
impl ProgressBar for RealProgressBar {
fn update_var(&mut self) {
// 一些实际工作
self.progress += 1;
}
fn set_val(&mut self) {
// 一些实际工作
self.progress = 0;
}
}
#[derive(Default)]
struct DummyProgressBar;
// 当用作进度条时,这不会执行任何操作
impl ProgressBar for DummyProgressBar {
fn update_var(&mut self) {}
fn set_val(&mut self) {}
}
// 公共函数
pub fn do_operation(progress_bar_on: bool) {
// 将运行时的布尔值转换为编译时的 trait 实现
if progress_bar_on {
do_operation_progress::<RealProgressBar>()
} else {
do_operation_progress::<DummyProgressBar>()
}
}
// 具有所有逻辑的私有函数。它可以无条件地调用进度条上的方法。
fn do_operation_progress<P: ProgressBar>() {
let mut pb = P::default();
// 一些代码
pb.update_var();
// 更多代码
pb.set_val();
}
英文:
You're essentially converting the boolean progress_bar_on
into an Option
, so you should use the Option
.
if let Some(pb) = pb {
pb.update_var();
}
However, this is still not very clean and still has to do a check every time pb
will be used. The robust way to is to make a trait.
trait ProgressBar: Default {
fn update_var(&mut self);
fn set_val(&mut self);
}
#[derive(Default)]
struct RealProgressBar {
progress: u32,
}
impl ProgressBar for RealProgressBar {
fn update_var(&mut self) {
// Some real work
self.progress += 1;
}
fn set_val(&mut self) {
// Some real work
self.progress = 0;
}
}
#[derive(Default)]
struct DummyProgressBar;
// This does nothing when used as a progress bar
impl ProgressBar for DummyProgressBar {
fn update_var(&mut self) {}
fn set_val(&mut self) {}
}
// Public-facing function
pub fn do_operation(progress_bar_on: bool) {
// Convert the runtime boolean into a compile-time trait impl
if progress_bar_on {
do_operation_progress::<RealProgressBar>()
} else {
do_operation_progress::<DummyProgressBar>()
}
}
// Private function that has all the logic. It can unconditionally
// call methods on the progress bar.
fn do_operation_progress<P: ProgressBar>() {
let mut pb = P::default();
// some code
pb.update_var();
// some more code
pb.set_val();
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论