首页 > 解决方案 > 用 Rust 编写的替代功能样式

问题描述

如何更正第 2 节中的语法错误?显示错误消息

error[E0277] slice indices are of type `usize` or ranges of `usize`

编译第 2 节时。(第 1 节和第 2 节;两者在不同的编程风格中具有相同的功能。)

extern crate rand;

use std::iter;
use rand::Rng;

fn estimateAreaCircleMonteCarlo() {
    let box_area = 4.0;
    let numIteration = 100000;

    let mut x = Vec::<f64>::with_capacity(numIteration);
    let mut y = Vec::<f64>::with_capacity(numIteration);
    let mut distance = Vec::<f64>::with_capacity(numIteration);
    let mut rng = rand::thread_rng();

    x = iter::repeat(())
        .map(|()| rng.gen_range(-1., 1.))
        .take(numIteration)
        .collect::<Vec<f64>>();

    y = iter::repeat(())
        .map(|()| rng.gen_range(-1., 1.))
        .take(numIteration)
        .collect::<Vec<f64>>();

    // section 1, it is able to be compiled.
    distance = (0..numIteration)
        .map(|i| (x[i].powi(2) + y[i].powi(2)).sqrt())
        .collect::<Vec<f64>>();

    // section 2, same functionality as section 1 but it cannot be compiled.
    // error[E0277]^^^^ slice indices are of type `usize` or ranges of `usize`
    /*
    distance = iter::repeat(())
        .map(|i| (x[i].powi(2) + y[i].powi(2)).sqrt())
        .take(numIteration)
        .collect::<Vec<f64>>();
    */

    println!("x={}", x[numIteration - 1]);
    println!("y={}", y[numIteration - 1]);
    println!("distance={}", distance[numIteration - 1]);
}

标签: lambdafunctional-programmingrust

解决方案


iter::repeat(())创建一个产生()(单元类型)的迭代器。然后你用这个闭包映射那些迭代的项目:

|i| (x[i].powi(2) + y[i].powi(2)).sqrt()

i因此是类型()。你不能()像编译器所说的那样索引一些东西:

the trait `std::slice::SliceIndex<[f64]>` is not implemented for `()`

解决此问题的一种方法可能是枚举:

distance = iter::repeat(()).enumerate()
    .map(|(i, _)| (x[i].powi(2) + y[i].powi(2)).sqrt())
    .take(numIteration)
    .collect();

但是您的第一个解决方案更好,因为这些iter::repeat东西没用。


请注意,如果您不需要保留xs 和ys,则会进行一些不必要的分配。这段代码可以简单地写成:

extern crate rand;

use rand::Rng;

fn estimate_area_circle_monteCarlo() {
    let num_iteration = 100000;
    let mut rng = rand::thread_rng();

    let distances: Vec<_> = (0..num_iteration)
        .map(|_| {
            let x: f32 = rng.gen_range(-1., 1.);
            let y: f32 = rng.gen_range(-1., 1.);
            (x.powi(2) + y.powi(2)).sqrt()
        })
        .collect();

    println!("last distance = {}", distances.last().unwrap());
}

collect仅在您确实需要 a Vec、 anHashSet或其他内容时使用。如果您的目的是迭代某些数据,请保持迭代器不变。


推荐阅读