保持干燥生锈

时间:2014-07-01 20:05:35

标签: reference dry rust

有时我必须采取长序列表达的信息,例如:

f1(f2(f3).f4(x,f5(y,z))).f6().f7()

(不一定是,你不想重复的任何长序列)。我可能需要多次引用它,其他代码介于两者之间。像这样:

fn myfunc(v: &T) -> X {
  match v.func(func(v.func().func())).func() {
    ...
  }
  .. other stuff ..
  match v.func(func(v.func().func())).func() {
    ...
  }
}

该值不可移动,因此我无法将其分配给变量,然后像其他语言一样引用变量两次,所以基本上我发现自己多次编写相同的函数调用序列。我试过这样的事情

let x = &( ... )

然后使用此

*x

但这没有用。我想我可以使用一个宏,但是每次都会重新计算它(因为大多数函数调用只是编译器和类型系统的糖,所以它不会太糟糕),但是那个'到目前为止,我已经解决了这个问题。还有另一种方式吗?

1 个答案:

答案 0 :(得分:1)

如果值不是Copy,那么您需要复制它,或者通过引用传递。例如。假设它正在计算T类型的值。我想你目前遇到的问题是

fn foo(x: T) { ... }
fn bar(x: T) { ... }


let your_thing = f1(f2(f3).f4(x,f5(y,z))).f6().f7();

foo(your_thing);
bar(your_thing); // error: use of moved value

正确的解决方法是将foo行更改为

fn foo(x: &T) { ... }

foo(&your_thing);

foofoo(your_thing.clone())的调用(如果TClone)。您可以通过考虑foo所需的所有权T来决定哪一个是合适的:如果它需要完全所有权(例如将其传递给不同的任务),则应该按值{foo(x: T)来获取它。 1}};另一方面,如果它只需要查看数据(即没有所有权),那么请参考foo(x: &T)

有关移动和复制的一些背景信息,另请参阅"Moves vs Copy in Rust"。它包括对&(...) + *x解决方案不起作用的原因的解释:不能从引用后面移出(尽管在这种情况下它永远不会起作用,因为移出两次无论如何都是非法的。)


同样的推理适用于模式匹配:如果您只需要参考,您可以通过ref参考感兴趣的值。例如。想象你正在计算Option<T>

let x = v.func(func(v.func().func())).func()

match x {
    Some(ref y) => { /* y is a &T */ ... }
    None => { ... }
}

// the last `match` can move `x`
match x {
     Some(y) => { /* y is a T */ ... }
     None => { ... }
}

如果第一个匹配确实需要x某些部分的所有权,您可以clone x本身,也可以只匹配与ref匹配后需要的部分。