使用Formatter::debug_list实现二维数组的Debug

Using Formatter::debug_list to implement Debug for a two-dimensional array

我想知道是否可以编译它。

impl<T: fmt::Debug> fmt::Debug for Array2<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ref mut builder = f.debug_list();
        self.rows().fold(builder, |b, e| b.entry(e)).finish()
    }
}

self.rows 是一个产生 &[T].

的迭代器

这里的错误是在 b.entry(e) 的上下文中未为 [T] 实现 Sized,这很奇怪,因为迭代器如前所述产生 &[T]

我无法弄清楚这一点,部分原因是我无法理解此处涉及的函数签名。

fn entry(self, entry: &Debug) -> DebugList<'a, 'b>

注意 &Debug

然而,相关文档示例正在将引用 &i32 传递给构建器。

struct Foo(Vec<i32>);

impl fmt::Debug for Foo {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.0.iter().fold(fmt.debug_list(), |b, e| b.entry(e)).finish()
    }
}

有这么多的困惑,一定有一些有趣的东西要学。

所需的输出类似于 [[1, 2], [3, 4]]

任何人都可以编译的类似示例:

use std::fmt;

fn fmt<T: fmt::Debug>(vec: &Vec<T>, f: &mut fmt::Formatter) -> fmt::Result {
    let ref mut builder = f.debug_list();
    vec.chunks(4).fold(builder, |b, e| b.entry(e)).finish()
}

entry() 定义如下:

pub fn entry(&mut self, entry: &fmt::Debug) -> &mut DebugList<'a, 'b>;

它需要一个fmt::Debug 特征对象。因此,当您将 &[T] 传递给它时,它希望将其隐式转换为 &fmt::Debug。然而,这是不可能做到的,因为特征对象只能由大小对象构成。解决方案是制作一个大小切片的特征对象;也就是说,传递 &&[T] 类型的东西,然后可以将其隐式转换为 &fmt::Debug,包含 &[T] 类型。即 b.entry(&e) 而不是 b.entry(e).

您的 builder 行也是不必要的,实际上引入了生命周期问题;为方便起见,您应该将其声明为 fold 调用的一部分。

最后的结果是:

impl<T: fmt::Debug> fmt::Debug for Array2<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.rows().fold(&mut f.debug_list(), |b, e| b.entry(&e)).finish()
    }
}