如何避免使用可选消息参数的函数的重复代码?
How do I avoid duplicate code for a function that uses an optional message parameter?
我想编写自己的断言函数,它可以有选择地包含一条消息:
fn foo(msg: Option<&str>) {
if let Some(m) = msg {
panic!("{} - Something went wrong: {}", m, "additional info");
} else {
panic!("Something went wrong: {}", "additional info")
}
}
如何避免这样的重复代码?如何避免对消息字符串进行多次(重新)分配?
不打印时使用空字符串。
fn foo(msg: Option<&str>) {
panic!("{}{}Something went wrong: {}",
{ if let Some(m) = msg { m } else { "" } },
{ if let Some(_m) = msg { " - " } else { "" } },
"additional info");
}
在 rustfmt 之后看起来像这样:
fn foo(msg: Option<&str>) {
panic!(
"{}{}Something went wrong: {}",
{
if let Some(m) = msg {
m
} else {
""
}
},
{
if let Some(_m) = msg {
" - "
} else {
""
}
},
"additional info"
);
}
我经常使用这样的小包装纸:
struct OrEmptyS<T>(Option<T>);
impl<'a, T: std::fmt::Display> std::fmt::Display for OrEmptyS<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
if let Some(v) = &self.0 {
v.fmt(f)
} else {
Ok(())
}
}
}
// Extension trait to add methods on `Option`
trait OrEmpty<T> {
fn or_empty(&self) -> OrEmptyS<&T>;
fn empty_or<'a, U: ?Sized>(&'a self, alt: &'a U) -> OrEmptyS<&'a U>;
}
impl<T> OrEmpty<T> for Option<T> {
fn or_empty(&self) -> OrEmptyS<&T> {
OrEmptyS(self.as_ref())
}
fn empty_or<'a, U: ?Sized>(&'a self, alt: &'a U) -> OrEmptyS<&'a U> {
OrEmptyS(self.as_ref().map(|_| alt))
}
}
您可以将其用作
fn foo(msg: Option<&str>) {
panic!(
"{}{}Something went wrong: {}",
msg.or_empty(),
msg.empty_or(" - "),
"additional info"
);
}
我想编写自己的断言函数,它可以有选择地包含一条消息:
fn foo(msg: Option<&str>) {
if let Some(m) = msg {
panic!("{} - Something went wrong: {}", m, "additional info");
} else {
panic!("Something went wrong: {}", "additional info")
}
}
如何避免这样的重复代码?如何避免对消息字符串进行多次(重新)分配?
不打印时使用空字符串。
fn foo(msg: Option<&str>) {
panic!("{}{}Something went wrong: {}",
{ if let Some(m) = msg { m } else { "" } },
{ if let Some(_m) = msg { " - " } else { "" } },
"additional info");
}
在 rustfmt 之后看起来像这样:
fn foo(msg: Option<&str>) {
panic!(
"{}{}Something went wrong: {}",
{
if let Some(m) = msg {
m
} else {
""
}
},
{
if let Some(_m) = msg {
" - "
} else {
""
}
},
"additional info"
);
}
我经常使用这样的小包装纸:
struct OrEmptyS<T>(Option<T>);
impl<'a, T: std::fmt::Display> std::fmt::Display for OrEmptyS<T> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
if let Some(v) = &self.0 {
v.fmt(f)
} else {
Ok(())
}
}
}
// Extension trait to add methods on `Option`
trait OrEmpty<T> {
fn or_empty(&self) -> OrEmptyS<&T>;
fn empty_or<'a, U: ?Sized>(&'a self, alt: &'a U) -> OrEmptyS<&'a U>;
}
impl<T> OrEmpty<T> for Option<T> {
fn or_empty(&self) -> OrEmptyS<&T> {
OrEmptyS(self.as_ref())
}
fn empty_or<'a, U: ?Sized>(&'a self, alt: &'a U) -> OrEmptyS<&'a U> {
OrEmptyS(self.as_ref().map(|_| alt))
}
}
您可以将其用作
fn foo(msg: Option<&str>) {
panic!(
"{}{}Something went wrong: {}",
msg.or_empty(),
msg.empty_or(" - "),
"additional info"
);
}