When I'm writing debug impls, I sometimes want to simulate some structure that is different from the structure of the actual contents of the struct/enum. For example, say I have a 2D path representation like the SVG path (details not important), but I use a custom encoding to save space. In the debug impl I want to show something like SVGPath { elements: [<elements here>] }. Currently the way I would do this would to be to create a wrapper struct for the inner data, implement Debug on that, and then do f.debug_struct("SVGPath").field("elements", &MyCustomStruct(&self.data)).finish(), which is all very verbose.
I'd like to be able to solve the above problem using a closure, so I can do f.debug_struct("SVGPath").field("elements", |f| f.debug_list().entries(&self.data).finish()).finish(), but currently Debug isn't implemented for Fn(&mut fmt::Formatter) -> fmt::Result.
Proposal
impl<F> Debug for F where F: Fn(&mut fmt::Formatter) -> fmt::Result {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(*self)(f)
}
}
// Or if you'd prefer not to do a blanket fn implementation, we could provide a wrapper at a
// small cost to ergonomics.
struct DebugFn<'a, F>(pub &'a F);
impl<'a, F> Debug for DebugFn<'a, F>
where F: Fn(&mut fmt::Formatter) -> fmt::Result
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(self.0)(f)
}
}
[The display version can be useful for functions that want to return some form of impl Display value (which some API may prefer over generating a String).]
(click here to read the rest; I don’t want to distract from this thread too much with long off-topics deliberations)
In this world, you could also write
let mut n = 0;
let iterator1 = move Iterator<Item = i32> {
next: || {
n += 1;
Some(n)
},
};
return iterator1;
or
let mut n = 0;
let iterator2 = Iterator<Item = i32> {
next: || {
n += 1;
Some(n)
},
size_hint: || (usize::MAX, None),
};
for n in iterator2 {
if random() {
break;
}
}
Such ad-hoc anonymous trait implementations would be a lot like closures (but not actually the same, just the syntax I came up with is inspired by closures) – but the killer feature of this would be that multiple methods can have mutable access to captured variables, see e.g. the range function above, (which means this is more capable than simple helper functions taking multiple closures, on for each method). Another great feature would be that this could support convenient variable capture despite implementing generic methods. (As given that generic closures do not exist in Rust.)
How to handle super traits? How to name parameter of a generic method? I don’t know… but a MVP probably doesn’t necessarily need to address all this, anyways.
Sorry if this is taking it somewhat off-topic as it’s more of a language feature proposal, going far beyond (both in scope and time-frame) a simple library addition. (Also I haven’t cross-checked at all against potential existing proposals.)