这是一个绝对的初学者问题,但在搜索半小时后我找不到任何有用的东西。我有Rust 1.7.0和这段代码:
type coord = [i64; 3];
// add two coordinates ("vectors") pointwise, that is
// if z = add(a, b) then z[i] = a[i] + b[i] for i=0..2
fn add(a: coord, b: coord) -> coord {
//???
}
我首先尝试的显而易见的事情是a.zip(b).map(|(u,v)| u+v)
,但这不起作用(不能压缩数组),a.iter().zip(b.iter()).map(|(u,v)| u+v)
也不行,因为它无法转换迭代器回到阵列。我可以看出为什么这一般不起作用,但在这种情况下我们知道两者的长度都是一样的。
现在我正在做
fn add(a: coord, b: coord) -> coord {
let mut z: coord = [0, 0, 0];
for i in 0..2 {
z[i] = a[i] + b[i];
}
z
}
但相比之下它看起来很难看。我错过了什么?
答案 0 :(得分:4)
一种简单的方法是使用enumerate
迭代器方法生成索引,并填充z
"显而易见的"方式,通过分配到获得的指数:
type Coord = [i64; 3];
fn add(a: Coord, b: Coord) -> Coord {
let mut z: Coord = [0, 0, 0];
for (i, (aval, bval)) in a.iter().zip(&b).enumerate() {
z[i] = aval + bval;
}
z
}
fn main() {
let x: Coord = [1, 2, 3];
let y: Coord = [1, 1, 1];
assert!(add(x, y) == [2, 3, 4]);
}
在Rust中,我们可以通过注意iter()
将引用生成到数组中来做得更好,并且iter_mut()
可用于生成可变引用。这导致代码与您尝试编写的代码非常相似:
fn add(a: Coord, b: Coord) -> Coord {
let mut z: Coord = [0, 0, 0];
for ((zref, aval), bval) in z.iter_mut().zip(&a).zip(&b) {
*zval = aval + bval;
}
z
}
如果这种写入z
的模式与不同的操作一致,你可以抽象创建新的Coord
并将数据填充到通用函数中:
fn new_coord_from<F: Iterator<Item=i64>>(src: F) -> Coord {
let mut result = [0; 3];
for (rref, val) in result.iter_mut().zip(src) {
*rref = val;
}
result
}
add
然后看起来就像我们喜欢它:
fn add(a: Coord, b: Coord) -> Coord {
new_coord_from(a.iter().zip(&b).map(|(a, b)| a + b))
}