我想编写一个生成一些文本的函数,如下所示:
fn produce_stuff(/* ??? */) -> Result<()> {
write!(...);
write!(...);
write!(...);
...
}
Run Code Online (Sandbox Code Playgroud)
我希望能够在两种情况下使用此功能:
produce_text(io.stdout())。Display如下所示:struct Foo { ... }
impl Display for Foo {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
...
produce_text(f);
...
}
}
Run Code Online (Sandbox Code Playgroud)
似乎这些用例中的每个用例都需要为签名不同produce_text。对于#1,该函数将需要采用一些已实现的东西,对于#2,该函数将需要std::io::Write采用一个std::fmt::Formatter。
我想我可以将它写为一个宏而不是一个函数(类似于write!在两种情况下都可以工作的宏),但是为此使用宏有些不妥。
You just have to implement Display.
When your Foo implements Display, you can use it with any implementation of Write, including io::Stdout:
use std::{
io::{self, Write},
fmt,
};
struct Foo {
field: u16,
}
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Foo({})", self.field)
}
}
fn main() {
write!(io::stdout(), "{}", Foo{field: 3}).unwrap();
}
Run Code Online (Sandbox Code Playgroud)
You don't have to write your own macro; just use write!. This should not feel wrong, it's the normal way.
There's no runtime cost related to the "{}" argument: it's parsed at compile time (in a compiler built-in), which makes the write!(w, "{}", displayable) call efficient.