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

4
我想知道是否可能使其编译。
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()
}
1个回答

5

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()
    }
}

看起来我的 Rust 有点生疏了。我原本以为一个 &Trait 只能通过显式转换来构造。 - A.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接