Open kangalio opened 3 years ago
In hindsight, I'm thinking this is way too much effort and too brittle for little benefit.
Dtolnay had discovered a clever trick to emulate specialization using autoref. This trick can be applied here to provide a specialization output format for Iterators.
The final generated code looks like this:
struct Wrap<T>(T);
trait Output {
fn output(self);
}
impl<T: Iterator> Output for Wrap<T> where T::Item: std::fmt::Debug {
fn output(mut self) {
if let Some(item) = self.0.next() {
print!("{:?}", item);
for item in self.0 {
print!(", {:?}", item);
}
println!();
}
}
}
impl<T: std::fmt::Debug> Output for &Wrap<T> {
fn output(self) {
println!("{:?}", &self.0);
}
}
fn main() { Wrap({
// USER CODE HERE
}).output(); }
This code can presumably be minified considerably. The utility structs and traits might also have to be wrapped in a macro for hygiene, so that the user doesn't accidentally use Output or Wrap in their own code and is confused about the result.
Now, I tested this code with a few types and it yielded the correct results each time. It seems robust enough, so the "tricky to implement" concern from above is dealt with I think.
The "magic" concern is definitely still valid though, in two aspects:
Remaining questions:
...
after a certain number of items or a certain number of printed characters?
The situation often comes up that you want to demonstrate some iterator chain using
?eval
. Directly writing the iterator yields bad results:The obvious workaround is to collect into a vector:
However, this workaround is slightly problematic:
::<Vec<_>>
)Perhaps there is a way to special-case the return value formatting for iterators? In the above example, the bot output could look like this:
Advantages:
Potential difficulties: