itertools
itertools copied to clipboard
Format should not panic if you try to format it more than once
Some logging frameworks will format things sent to the error! macro twice.
Some possible solutions:
- Print a "iterator exhausted" message instead of panicking
- Impose a
Clonebound on the iterator being formatted so that we can format it multiple times - Doesn't
fmtreturn aResultanyway? Why not just returnErr?
(3) From previous discussion I have understood that fmt's error return should not be used by the thing that is being formatted. It's used to relay the information that an I/O error happened through the formatting chain.
I don't know how to solve it, I think this is a drawback that comes from our skirting the rules a bit for formatting.
As an alternative to changing the behavior of the existing format, how about a separate extension-trait on copyable sources of iterators providing a "safe format" type, so that into_iter() is called every time fmt is called?
trait IterSafeFormatExt {
type I;
fn safe_format(&self, separator: &'static str) -> SafeFormat<Self::I>;
}
struct SafeFormat<I>{
iterable: I,
separator: &'static str,
}
impl<I: IntoIterator<Item = E> + Copy, E: fmt::Display> fmt::Display for SafeFormat<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.iterable.into_iter().format(self.separator).fmt(f)
}
}
impl<I: IntoIterator<Item = E> + Copy, E: fmt::Display> IterSafeFormatExt for I {
type I = I;
fn safe_format(&self, separator: &'static str) -> SafeFormat<I> {
SafeFormat { iterable: *self, separator }
}
}
The common case would be to call safe_format on a shared reference to a container:
fn main() {
let mut v = Vec::new();
v.push("foo");
let formatter = (&v).safe_format(", ");
println!(
"{}{}",
formatter, formatter,
);
}
Edit: I'd like to have some way to accept an arbitrary callback that generates the appropriate iterator on-demand, but I can't figure out how to make the types work out for that.