此代码有效:
extern crate num;
use num::{BigInt, FromPrimitive, Zero};
fn sample() {
let mut to_factor = "600851475143".parse::<BigInt>().unwrap();
let mut prime = BigInt::from_i32(2).unwrap();
let zero = BigInt::zero();
//let is_div = |n, p| { n % p == zero};
loop {
if &to_factor % &prime == zero {
to_factor = &to_factor / ′
} else {
break;
}
}
println!("{}", to_factor);
}
但是如果我尝试用闭包替换循环中的条件,它就不再编译了:
fn sample() {
let mut to_factor = "600851475143".parse::<BigInt>().unwrap();
let mut prime = BigInt::from_i32(2).unwrap();
let zero = BigInt::zero();
let is_div = |n, p| { n % p == zero};
loop {
if is_div(&to_factor, &prime) {
to_factor = &to_factor / ′
} else {
break;
}
}
println!("{}", to_factor);
}
错误如下:
error[E0506]: cannot assign to `to_factor` because it is borrowed
--> src/main.rs:16:13
|
15 | if is_div(&to_factor, &prime) {
| --------- borrow of `to_factor` occurs here
16 | to_factor = &to_factor / ′
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ assignment to borrowed `to_factor` occurs here
对我来说似乎很好 - 当我们改变 to_factor
时,借用应该是"over",当然?
为了增加混淆,如果我用实际函数替换 is_div
:
fn is_div(n: &BigInt, p: &BigInt) -> bool {
return to_factor % p == BigInt::zero()
}
它工作正常 .
我是Rust的初学者,但不是一般的编程 . 我很确定这与所有权有关,但它也可能与如何实现闭包有关?
这些示例是我尝试编写的实际代码中的MWE . 它们在这一点上并没有真正意义,但它们表现出相同的编译错误 .
2 回答
您正在遇到Rust类型系统的实现限制,特别是关于闭包参数的类型推断 . 也就是说,当你声明一个与立即使用的闭包相比没有立即使用的闭包时,推断的类型会略有不同 .
这种闭包有效,因为类型推断可以立即将参数连接到参数:
这也有效,因为我们立即定义参数的类型:
这也是您的功能版本工作的原因 .
在问题跟踪器上有很多问题(这是一个非常难以搜索的东西!),但是12679是一个较旧的问题 .
这是您经常看到内联定义的闭包的原因 .
正如你所写的那样,
is_div
闭包不会借用to_factor
,它会永远占用它 . 如果您将闭包签名更改为借用to_factor
则可行 .不能在操场上使用板条箱,但这说明了这一点 .