2016-10-25 11 views
0

私はnew_vecという機能を持っています。 zipされたベクトルから要素のペアに対して要素単位の操作を実行することによって、2つのベクトルを取り、新しいベクトルを作成します。適用される操作で一般的な錆関数を作成するにはどうすればよいですか?

fn main() { 
    let v1s = vec![1, 0, 1]; 
    let v2s = vec![0, 1, 1]; 
    let v3s = new_vec(v1s, v2s); 
    println!("{:?}", v3s) // [1, 1, 2] 
} 

fn new_vec(v1s: Vec<i32>, v2s: Vec<i32>) -> Vec<i32> { 
    let mut v3s = Vec::<i32>::new(); 
    for (v1, v2) in v1s.iter().zip(v2s.iter()) { 
     v3s.push(v1 + v2) // would also like to use - 
    } 
    v3s 
} 

私はそのような+-/*として二つの整数、上で使用することが可能である一般的な二項演算のためのnew_vec機能を持っていると思います。

どうすればよいですか?私は2つの方法を想像することができます:マクロとクロージャー。例えば、+-のように、これを最も良い方法で行う方法の最小の例が認められます。

+0

私はコピー&ペーストしていない理由があるので、私は一般的なようにしたい機能は、やや長いです:) –

答えて

5

Iはクロージャを渡す:

fn new_vec<F>(v1s: &[i32], v2s: &[i32], foo: F) -> Vec<i32> 
    where F: Fn(i32, i32) -> i32 
{ 
    let mut v3s = Vec::<i32>::new(); 
    for (&v1, &v2) in v1s.iter().zip(v2s.iter()) { 
     v3s.push(foo(v1, v2)) 
    } 
    v3s 
} 

fn main() { 
    let v1s = vec![1, 0, 1]; 
    let v2s = vec![0, 1, 1]; 
    let v3s = new_vec(&v1s, &v2s, |x, y| x - y); 
    let v4s = new_vec(&v1s, &v2s, |x, y| x + y); 
    println!("{:?}", v3s); // [1, -1, 0] 
    println!("{:?}", v4s); // [1, 1, 2] 
} 

は、最初の2つのパラメータの変化に注意してください。関数が引数を消費する必要がない場合はreferences are preferable to Vectors - この場合は&[i32]です。

この実装は、結果として得られるVectorが段階的に拡張されるため効率的ではありません。次のように割り当ての数を減らすために、それを変更した場合、それは良いでしょう:

fn new_vec<F>(v1s: &[i32], v2s: &[i32], foo: F) -> Vec<i32> 
    where F: Fn(i32, i32) -> i32 
{ 
    v1s.iter().zip(v2s.iter()).map(|(&x, &y)| foo(x, y)).collect() 
} 
+0

はどこhaskellishを愛し!閉鎖が遅くないことは、私には直感に反する。あたかも私が各操作(add_vec、minus_vec)ごとに異なる関数を作成したかのように、クロージャを処理するコンパイラを入手できるかどうか知っていますか? (受け入れる前に明日の答えを見る必要があります。) –

+0

@TheUnfunCat私はこれがあなたの後ろであるかどうかはわかりませんが、letバインディングでクロージャを定義することができます。 'let add = | x、y | x + y; 'それを正規関数の引数のように渡す:' new_vec(&v1s、&v2s、add) '。 – ljedrz

+0

私が達成しようとしていたのは、関数を完全に書き出してファイルをコンパイルしたのと同じ速度でした:) –

関連する問題