2016-04-03 10 views
13

できるだけ可能な場合は、関数をRust(おそらくはい)のパラメータとして渡すことができます。錆にはどのように関数をパラメータとして渡しますか?

できない場合は、これが良い方法です。

私はいくつかの構文を試みたが、私はこの

..// 

let fun: fn(value: i32) -> i32; 
fun = funTest; 
fun(5i32); 

..// 
fn funTest(value: i32) -> i32 { 
    println!("{}", value); 
    value 
} 

ではなく、別の関数にパラメータとして

..// 
fn funTest(value: i32, (some_function_prototype)) -> i32 { 
    println!("{}", value); 
    value 
} 
を機能を渡すように行うことができます知っている


をもらっていない

答えて

22

できること:

fn funTest(value: i32, f: &Fn(i32) -> i32) -> i32 { 
    println!("{}", f(value)); 
    value 
} 

fn times2(value: i32) -> i32 { 
    2 * value 
} 

fn main() { 
    funTest(5, &times2); 
} 

これは錆ですので、ownership and lifetime of the closureを考慮する必要があります。

TL; DR;

  1. Fn:最も一般的なそれは純粋関数であり、基本的に閉鎖の3種類(呼び出し可能オブジェクト)があります。
  2. FnMut:キャプチャするオブジェクトを変更することができます。
  3. FnOnce:最も制限されています。呼び出されたときにそれ自身とそのキャプチャを消費するため、一度だけ呼び出すことができます。

クロージャのような単純な関数へのポインタを使用している場合、キャプチャセットは空で、Fnフレーバがあります。

あなたはより多くの工夫をしたい場合は、ラムダ関数を使用する必要があります。他の回答で概説

+0

の使用に違いがあります(..、f:&Fn ...)2つの作品は、私が知る必要があるいくつかの詳細は? –

+0

@AngelAngel:まあ、 'Fn *'は形質なので、普通の ''と '(t:&T)'が適用されます。非ジェネリックなソリューションの主な制限は、参照と一緒に使用する必要があることです。だからコピーとして渡すべき 'FnOnce'が必要な場合は、汎用スタイルを使わなければなりません。 – rodrigo

+2

特徴オブジェクトの代わりにジェネリックを使用する方が慣れていることに注意してください( 'f:&Fn ...)の代わりに' ')。これは理由のためです。ジェネリックスは静的なディスパッチを引き起こします。ダイナミックディスパッチ。 –

6

FnFnMutFnOnceは、閉鎖タイプです。スコープを超えて機能する関数の種類。ここfunction pointer typeがある

fn times2(value: i32) -> i32 { 
    2 * value 
} 

fn fun_test(value: i32, f: fn(i32) -> i32) -> i32 { 
    println!("{}", f (value)); 
    value 
} 

fn main() { 
    fun_test (2, times2); 
} 

fn(i32) -> i32

別に渡す閉鎖から錆にも、このように、簡単な(非閉鎖)関数を渡すことをサポートしています。

関数型で作業するよりも本格的なクロージャを必要としない場合は、クロージャの生存時間を処理する必要がないため、しばしば簡単です。

関連する問題