Альтернативный функциональный стиль написан в ржавчине - PullRequest
0 голосов
/ 21 мая 2018

Как исправить синтаксическую ошибку в разделе 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]);
}

Ответы [ 2 ]

0 голосов
/ 21 мая 2018

Существует окончательная версия для справки.

distance = iter::repeat(())
        .enumerate()
        .map(|(i, _)| (x[i].powi(2) + y[i].powi(2)).sqrt())
        .take(numIteration)
        .collect::<Vec<f64>>();
0 голосов
/ 21 мая 2018

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 материал бесполезен.


Обратите внимание, что вы делаете ненужные выделения, если вам не нужно сохранять x s и y s.Этот код может быть просто написан как:

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, только если вы действительно хотите Vec, HashSet или что-то еще.Если ваша цель состоит в том, чтобы перебрать некоторые данные, оставьте итератор без изменений.

...