如何在循环中使用链式生成器模式而不产生编译器错误?

mar*_*hon 2 rust

您如何正确使用期望在循环中链接方法的构建器模式?使用log4rs中的示例。注意self不是中的参考appender

//builder pattern from log4rs

pub struct ConfigBuilder {
    appenders: Vec<Appender>,
    loggers: Vec<Logger>,
}

impl ConfigBuilder {
    pub fn appender(mut self, appender: Appender) -> ConfigBuilder {
        self.appenders.push(appender);
        self
    }
}
Run Code Online (Sandbox Code Playgroud)

在下面执行此操作会导致错误,因为(我认为)cb正在移至所返回的内存中.appender()

let cb = ConfigBuilder::new();
for x in ys {
    cb.appender(x);
}
Run Code Online (Sandbox Code Playgroud)

这似乎在工作。这是唯一的方法吗?

let mut cb = ConfigBuilder::new();
for x in ys {
    cb = cb.appender(x);
}
Run Code Online (Sandbox Code Playgroud)

log*_*yth 5

这是唯一的方法吗?

从语义上讲,这是关键的方法,尽管还有其他编写方法。该appender函数执行此操作,mut self因此它将获取cb变量值的所有权,并在此之后使该变量不可用。它本来可以借用参考,但是链接很好。由于您处于循环中,因此构建器需要在下一次迭代中可用,因此您需要将值分配给新对象。这意味着

let mut cb = ConfigBuilder::new();
for x in ys {
    cb = cb.appender(x);
}
Run Code Online (Sandbox Code Playgroud)

确实是做到这一点的一种方法。另一种方法是使用Iterator.fold

let cb = ys.into_iter()
  .fold(ConfigBuilder::new(), |cb, x| cb.appender(x));
Run Code Online (Sandbox Code Playgroud)

这样可以将所有内容保持在一个作业中,但其他方面几乎相同。