Cloning a std::iter::Map with inferred (?) type

最后都变了- 提交于 2019-12-10 20:59:33

问题


I'm having trouble cloning a Map in a compact way:

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

The error I get with this code is

`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

which is understandable, but if I try to use time_1s.clone() instead, I get

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

which is also understandable, but storing (freq * time_sample).sin() in a let foo: f64 inside the closure before returning it doesn't have any effect.

What am I supposed to do in a situation like this? All I wanted to do was use the time vector more than once.


回答1:


One way to use time_1s twice is to do both together and unzip at the end:

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



回答2:


My original answer caused 3 enumerations of the iterator. Ideally you were looking for 2 iterations.

Since map consumes the iterator, it seems like the easier and more efficient way to do this without causing more iterations or clones than necessary is to just loop over it yourself only once:

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


来源:https://stackoverflow.com/questions/39951381/cloning-a-stditermap-with-inferred-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!