.next()之后的... .zip():防止迭代器被移动

时间:2016-05-30 02:16:51

标签: rust

我是Rust的新手,并且还没有完全了解所有这些。我一直在做很多Rust阅读,也在玩数学问题。我用这个签名写了一个函数:

pub fn prime_factors(n: u64) -> Vec<u64> {

因此,给定n为30,它应返回值为2,3和5的向量。我构建了一个测试:

#[test]
fn prime_factors_test() {
    assert_list_eq([2,3,5].iter(), prime_factors(30).iter());
}

一个亮点是我将静态数组与向量进行比较(出于学习目的,目前这是可取的,因为我喜欢练习泛型)。

我的测试功能是我实际遇到的问题。要进行测试,函数必须遍历两个集合,检查每个索引的相等性。我用.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());
}

我认为循环(或者循环的设置)移动/消耗迭代器,并且它们不能在循环之后使用。但我想要来检查循环后那些迭代器的状态。我想我知道错误是什么,我只是不知道怎么做正确。我几乎肯定有一个概念问题。

作为一种解决方法,我做到了这一点,但我觉得我通过使用.clone()只是为了让事情发挥作用而拥抱反模式。

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);
    }
}
BTW(承认XY问题):我很乐意了解比较两个有序集合的内置断言,但这并不是我真正感到困惑的。

1 个答案:

答案 0 :(得分:3)

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()); } 应用于两个迭代器:

Vec

也就是说,标准库已经提供了所有必要的工具来比较固定大小的数组和PartialEq。虽然它有点棘手,因为#[test] fn prime_factors_test() { assert_eq!([2,3,5][..], prime_factors(30)[..]); } 在其右侧参数上是通用的,并且没有足够的实现它以“明显”的方式工作。这是一种方法:

[..]

..使用Index<RangeFull>特征强制将表达式转换为切片(RangeFull[..]的简写)。

另一种方法是只交换操作数,然后你不需要#[test] fn prime_factors_test() { assert_eq!(prime_factors(30), [2,3,5]); }

impl PartialEq<[T; 3]> for Vec<T>

这是因为标准库提供impl PartialEq<Vec<T>> for [T; 3],但不提供 @IBOutlet weak var originalImage: UIImageView! var userImage?:UIImage @IBAction func SepiaToneFilter(sender: AnyObject) { let mySepiaFilter = CIFilter(name: "CISepiaTone") if let image = self.userImage { mySepiaFilter!.setValue(CIImage(image: image), forKey: kCIInputImageKey) let myOutputImage : CIImage = mySepiaFilter!.outputImage! originalImage.image = UIImage(CIImage: myOutputImage) } } @IBAction func ResetFilter(sender: AnyObject) { if let image = self.userImage { self.originalImage.image = image } } func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) { self.userImage = image originalImage.image = image self.dismissViewControllerAnimated(true, completion: nil); }