共计 1505 个字符,预计需要花费 4 分钟才能阅读完成。
基于 Rust 的 Vec
容器,能够表白数学里的 n 维点。上面的 foo
函数能够依据两个 n 维点 a 和 b,结构一个点集 {a, b, c},其中 c 是 a 和 b 的中点。
fn foo(a: &Vec<f64>, b: &Vec<f64>) -> Vec<Vec<f64>> {assert_eq!(a.len(), b.len());
let mut c: Vec<f64> = Vec::new();
for i in 0 .. a.len() {c.push(0.5 * (a[i] + b[i]));
}
let mut points: Vec<Vec<f64>> = Vec::new();
points.push(a.clone());
points.push(b.clone());
points.push(c);
return points;
}
留神,points
存储的是 a
和 b
的正本,并非 a
和 b
自身。假使我心愿 points
里存储的是 a
和 b
自身,该如何做呢?我能想到的计划是
fn foo(a: &Vec<f64>, b: &Vec<f64>) -> Vec<&Vec<f64>> {assert_eq!(a.len(), b.len());
let mut c: Vec<f64> = Vec::new();
for i in 0 .. a.len() {c.push(0.5 * (a[i] + b[i]));
}
let mut points: Vec<&Vec<f64>> = Vec::new();
points.push(a);
points.push(b);
points.push(&c);
return points;
}
当初,points
存储的是 a
,b
和 c
的援用,然而 rustc 在编译这段代码时,会报错并指出,这个函数的返回值蕴含了一个借用值,然而函数签名却未能指明借用的是 a
还是 b
。尽管代码写的很明确,a
和 b
都被借用了,但即便如此,rustc 仍然无奈确定在 points
生命周期之内 a
和 b
是否依然健在,因而须要通过生命周期标记通知 rustc,a
以及 b
的生命周期至多与 points
一样长,亦即
fn foo<'a>(a: &'a Vec<f64>, b: &'a Vec<f64>) -> Vec<&'a Vec<f64>> {... ... ...}
真正致命的问题在于 c
,即
points.push(&c);
rustc 在编译这行代码时,会报错:
error[E0515]: cannot return value referencing local variable `c`
意思是,不能将一个局部变量的援用放在 points
里并将其返回。因为 foo
函数完结时,c
便寿终正寢,从而导致 points
对它的援用生效。我当初无奈解决这个问题,只好乖乖地回到了最后的计划,用 points
存 a
和 b
所援用的点的正本,再存 c
。
当初,再来写一个函数 bar
,用它批改 points
,将 c
放在 a
和 b
的两头:
fn bar(points: &mut Vec<Vec<f64>>) {let b = points[1];
points[1] = points[2];
points[2] = b;
}
逻辑上没问题,然而 rustc 认为,
move occurs because value has type `Vec<f64>`, which does not implement the `Copy` trait
意思就是 bar
外面的三条赋值语句,都是错的,起因是,Vec<f64>
没实现 Copy
Trait。要 Copy
什么呢?我只是心愿 points
的第 2 个和第 3 个元素替换一下地位,并不想 Copy
什么啊。然而,我却不晓得该怎么写这个函数了,假使 points
存储的是援用,而不是理论的值,上述赋值语句应该是成立的,然而这又会导致 foo
函数难以定义。
感觉对 rust 快没有爱了……好在一开始就没有。