【问题标题】:Passing a variable to a function (which alters said variable) repeatedly反复将变量传递给函数(改变所述变量)
【发布时间】:2017-12-07 20:24:21
【问题描述】:

我正在玩 Rust,并且可能咬得比我能咀嚼的多得多,我正在尝试编写一个模块来封装我的数据库流量以供应用程序的其余部分使用。我正在努力的代码如下:

pub fn create_statement(cypher: &str, params: &HashMap<&str, &str>) -> rusted_cypher::Statement {
    let mut statement = rusted_cypher::Statement::new(cypher);
    for (field, value) in params.iter() {
        statement.with_param(field.to_owned(), value.to_owned());
    }
    return statement;
}

这会产生以下错误:error[E0382]: use of moved value: statement。我认为,我的搜索让我明白了这意味着什么(Statement 结构不可复制,因此被移动,然后......实际上不再可访问,我猜?),但我不知道如何绕过它。任何人都可以指出解决方案的方向吗?

【问题讨论】:

  • 据我快速浏览docs 可以看出,with_param 消耗了它的论点;你需要选择一个对statement 进行可变引用的函数。
  • 小提示:由于 Rust 是一种基于表达式的语言,因此您无需输入 return statement;,只需输入 statement

标签: rust move-semantics ownership


【解决方案1】:

我之前没用过这个API,但是,根据its documentation

此方法消耗self并返回它并添加参数,因此绑定不需要是可变的。

正如你所说,结构不是“不可复制的”,而是 with_param 方法是有意编写的,它移动值并获得所有权- 我们也可以说它消耗它。在构建器风格的 API 中,使用该值是一件很常见的事情,因为它可以防止您意外放置半成品对象。每个构建器方法都会使用该对象,在此期间没有其他人可以访问它,然后在完成后返回它,以便您可以继续使用它。来自文档:

let statement = Statement::new("MATCH n RETURN n")
    .with_param("param1", "value1")?
    .with_param("param2", 2)?
    .with_param("param3", 3.0)?;

with_param 的每次调用都会消耗statement,然后将其返回,以便您可以再次调用with_param

这有点棘手的是with_param 的结果不是Statement,而是Result&lt;Statement, JsonError&gt;。显然添加参数可能会导致错误,因此将结果包装起来以适应这种可能性。这就是 ?s 的用途 - 它们将结果解包到基础值中,或者如果无法完成则传播错误。

正如已经建议的其他答案之一,更好的解决方法是仅使用 set_parameters 方法,这将一次性设置它们。

另一种方法是使用每次调用with_param的返回值:

pub fn create_statement(cypher: &str, params: &HashMap<&str, &str>) -> rusted_cypher::Statement {
  let mut statement = rusted_cypher::Statement::new(cypher);
  for (field, value) in params.iter() {
      statement = statement.with_param(field.to_owned(), value.to_owned()).unwrap();
  }
  statement
}

当您使用返回值时,您可以再次访问该值,因此您可以继续使用它。

请注意,我使用unwrap()Result 获取值。这是不是好的做法,因为如果结果是错误会导致恐慌。我在这里这样做是为了专注于解释移动语义,而不涉及错误处理,这本身就是一个主题。

【讨论】:

    【解决方案2】:

    虽然这并不能回答您关于以与当前代码相同的方式传递可变值的基本问题。

    rusted-cypher::Statement 有一个 set_parameters 方法,该方法将 &amp;BTreeMap&lt;String, T&gt; 作为其唯一参数。

    你可以在rusted-cypher's source code看到这个函数。

    一个可能的实现:

    pub fn create_statement(cypher: &str, params: &BTreeMap<&str, &str>) -> rusted_cypher::Statement {
       let mut statement = rusted_cypher::Statement::new(cypher);
       statement.set_parameters(params);
       statement
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-13
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      相关资源
      最近更新 更多