【问题标题】:Cloning a std::iter::Map with inferred (?) type使用推断的 (?) 类型克隆 std::iter::Map
【发布时间】:2017-02-18 11:14:11
【问题描述】:

我无法以紧凑的方式克隆地图:

extern crate itertools_num;

use itertools_num::linspace;

fn main() {
    // 440Hz as wave frequency (middle A)
    let freq: f64 = 440.0;
    // Time vector sampled at 880 times/s (~Nyquist), over 1s
    let delta: f64 = 1.0 / freq / 2.0;
    let time_1s = linspace(0.0, 1.0, (freq / 2.0) as usize)
        .map(|sample| { sample * delta});

    let sine_440: Vec<f64> = time_1s.map(|time_sample| {
        (freq * time_sample).sin()
    }).collect();

    let sine_100: Vec<f64> = time_1s.map(|time_sample| {
        (100.0 * time_sample).sin()
    }).collect();
}

我用这段代码得到的错误是

`time_1s` moved here because it has type `std::iter::Map<itertools_num::Linspace<f64>, [closure@examples/linear_dft.rs:12:14: 12:40 delta:&f64]>`, which is non-copyable

这是可以理解的,但如果我尝试改用time_1s.clone(),我会得到

note: the method `clone` exists but the following trait bounds were not satisfied: `[closure@examples/linear_dft.rs:12:14: 12:40 delta:_] : std::clone::Clone`
error: the type of this value must be known in this context
     (freq * time_sample).sin()

这也是可以理解的,但是在返回之前将 (freq * time_sample).sin() 存储在闭包内的 let foo: f64 中没有任何效果。

在这种情况下我该怎么办?我只想多次使用时间向量。

【问题讨论】:

标签: iterator rust clone type-inference


【解决方案1】:

使用time_1s 两次的一种方法是一起做,最后解压:

extern crate itertools_num;

use itertools_num::linspace;

fn main() {
    // 440Hz as wave frequency (middle A)
    let freq: f64 = 440.0;
    // Time vector sampled at 880 times/s (~Nyquist), over 1s
    let delta: f64 = 1.0 / freq / 2.0;
    let time_1s = linspace(0.0, 1.0, (freq / 2.0) as usize)
            .map(|sample| { sample * delta});

    let (sine_440, sine_100): (Vec<f64>, Vec<f64>) = time_1s.map(|time_sample| {
        ((freq * time_sample).sin(),
         (100.0 * time_sample).sin())
    }).unzip();
}

【讨论】:

  • 这很好,我根本没有考虑过unzip。我想知道这个设置会发生什么分配?我想它根本不会产生很大的影响,但我仍然很好奇 - 我并不精通 Rust 迭代器/可枚举的内部结构。
  • 接受这个答案,因为它具有我正在寻找的功能配方。 (也有更多的点。)
【解决方案2】:

我原来的答案导致了迭代器的 3 次枚举。理想情况下,您正在寻找 2 次迭代。

由于map 使用了迭代器,似乎更简单、更有效的方法是在不导致不必要的迭代或克隆的情况下执行此操作,即只自己循环一次:

let time_1s = linspace(0.0, 1.0, (freq / 2.0) as usize)
    .map(|sample| { sample * delta});

let mut sine_100 = Vec::new();
let mut sine_440 = Vec::new();

for time_sample in time_1s {
    sine_100.push((100.0 * time_sample).sin());
    sine_440.push((freq * time_sample).sin());
}

println!("{:?}", sine_100);
println!("{:?}", sine_440);

【讨论】:

    猜你喜欢
    • 2017-03-18
    • 2014-05-08
    • 2021-09-20
    • 1970-01-01
    • 2022-01-02
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    • 2018-03-26
    相关资源
    最近更新 更多