lambda - 用 rust 编写的替代功能样式

标签 lambda functional-programming 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]);
}

最佳答案

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 东西没用。


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

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());
}

仅当您确实需要 VecHashSet 或其他任何内容时才使用 collect。如果您的目的是迭代某些数据,请保持迭代器不变。

关于lambda - 用 rust 编写的替代功能样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50443267/

相关文章:

.net - F# 有类似 Haskell 的 where 子句的东西吗?

javascript - 函数式 js - 无法递归调用自己的函数

rust - 为什么可变借用的生命周期不会在函数调用完成时结束?

rust - 如何将可见性 token 传递给位标志!宏?

c++ - clang vs gcc - 空通用 lambda 可变参数包

arrays - 使用 lambda 捕获的 constexpr 值作为数组维度

c# - 如何在 C# 中组合两个类型为 "delegate"的 lambda

Scalaz 实例化类型类和案例类

utf-8 - 如何仅使用 Rust 标准库解码单个 UTF-8 字符并进入下一个字符?

c# - Linq Lambda 表达式 == 和等于运算符