我是 Rust 新手,还没有完全理解它的全部内容。我做了很多 Rust 阅读,也解决了数学问题。我用这个签名编写了一个函数:
pub fn prime_factors(n: u64) -> Vec<u64> {
Run Code Online (Sandbox Code Playgroud)
因此,给定n30,它应该返回一个值为 2、3 和 5 的向量。我构建了一个测试,内容如下:
#[test]
fn prime_factors_test() {
assert_list_eq([2,3,5].iter(), prime_factors(30).iter());
}
Run Code Online (Sandbox Code Playgroud)
一个亮点是我正在将静态数组与向量进行比较(出于学习目的,这目前是可取的,因为我想练习泛型)。
我的测试功能是我实际上遇到问题的功能。要进行测试,该函数必须迭代两个集合,检查每个索引是否相等。我曾经.zip()这样做过,但如果集合不均匀,迭代器只会通过较短集合的索引进行耗尽。所以之后zip,我想检查两个迭代器是否有额外的元素。
以下内容无法编译:
fn assert_list_eq<I, T>(mut expected: I, mut actual: I)
where I: Iterator<Item=T> + Clone,
T: PartialEq + Debug {
for (e, a) in expected.zip(actual) {
assert_eq!(e, a);
}
// fail if there are any "leftovers"
assert_eq!(None, expected.next());
assert_eq!(None, actual.next());
}
Run Code Online (Sandbox Code Playgroud)
我认为循环(或者可能是循环的设置)移动/消耗迭代器,并且它们在循环之后不能使用。但我想检查循环后这些迭代器的状态。我想我知道出了什么问题,只是不知道如何改正。我几乎肯定遇到了概念问题。
作为一种解决方法,我这样做了,但我觉得我正在拥抱一种反模式,通过使用.clone()just 让事情正常进行。
fn assert_list_eq<I, T>(expected: I, actual: I)
where I: Iterator<Item=T> + Clone,
T: PartialEq + Debug {
assert!(expected.clone().count() == actual.clone().count()); // desperation
for (e, a) in expected.zip(actual) {
assert_eq!(e, a);
}
}
Run Code Online (Sandbox Code Playgroud)
BTW(承认 XY 问题):我很高兴了解一个内置断言来比较两个有序集合,但这并不是我真正感到困惑的地方。
zip按值获取其参数,因此这就是它们被移动并且之后不能使用它们的原因。
然而,有一个解决方法:有一个by_ref方法返回对迭代器的可变引用,技巧是&mut I where I: Iterator它还实现了Iterator. 因此,您可以在.by_ref()将两个迭代器传递给之前应用它们zip():
fn assert_list_eq<I, T>(mut expected: I, mut actual: I)
where I: Iterator<Item=T> + Clone,
T: PartialEq + Debug {
for (e, a) in expected.by_ref().zip(actual.by_ref()) {
assert_eq!(e, a);
}
// fail if there are any "leftovers"
assert_eq!(None, expected.next());
assert_eq!(None, actual.next());
}
Run Code Online (Sandbox Code Playgroud)
也就是说,标准库已经提供了将固定大小数组与Vec. 但这有点棘手,因为PartialEq它的右侧参数是通用的,并且没有足够的实现来使其以“明显”的方式工作。这是一种方法:
#[test]
fn prime_factors_test() {
assert_eq!([2,3,5][..], prime_factors(30)[..]);
}
Run Code Online (Sandbox Code Playgroud)
[..]Index<RangeFull>使用特征 (..是 的简写)强制将表达式转换为切片RangeFull。
另一种方法是仅交换操作数,然后就不需要[..].
#[test]
fn prime_factors_test() {
assert_eq!(prime_factors(30), [2,3,5]);
}
Run Code Online (Sandbox Code Playgroud)
那是因为标准库提供了impl PartialEq<[T; 3]> for Vec<T>,但没有提供impl PartialEq<Vec<T>> for [T; 3]。
| 归档时间: |
|
| 查看次数: |
911 次 |
| 最近记录: |