2016-04-03 8 views
13

Czy mogę przekazać funkcję jako parametr w Rust (prawdopodobnie tak), jeśli jest to możliwe, tak jak ja.W Rust, w jaki sposób przekazujesz funkcję jako parametr?

Jeśli nie możesz, co jest dobrą alternatywą.

Próbowałem trochę składni, ale nie dostał


wiem, że mogę to zrobić

..// 

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

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

ale nie tak przekazując funkcję jako parametr do innej funkcji

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

Odpowiedz

22

Na pewno możesz:

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

Ale to Rust, więc musisz wziąć pod uwagę ownership and lifetime of the closure.

TL; DR; Zasadniczo istnieją 3 rodzaje zamknięć (obiekty do wywołania):

  1. Fn: Najbardziej ogólny, jest to funkcja czysta.
  2. FnMut: Może modyfikować przechwycone obiekty.
  3. FnOnce: Najbardziej ograniczony. Można go wywołać tylko raz, ponieważ gdy się go nazywa, konsumuje się i przechwytuje.

Jeśli używasz prostego wskaźnika do funkcji jak zamknięcie, to zestaw przechwytywania jest pusty i masz smak Fn.

Jeśli chcesz zrobić więcej wymyślnych rzeczy, musisz użyć funkcji lambda.

+0

Istnieje różnica w używaniu lub nie (.., f: & Fn ...) dwóch prac, jakichś szczegółów, które muszę znać? –

+0

@AngelAngel: Cóż, 'Fn *' to cechy, więc stosuje się zwykle '' vs '(t: & T)'. Głównym ograniczeniem nietypowego rozwiązania jest to, że musi być używane z odniesieniami. Więc jeśli chcesz 'FnOnce', który powinien być przekazany jako kopia, musisz użyć ogólnego stylu. – rodrigo

+2

Należy zauważyć, że bardziej idiomatyczne jest używanie generycznych zamiast obiektów cech (np. '' zamiast '(f: & Fn ...)'. A to z jakiegoś powodu - generics spowoduje statyczną wysyłkę, podczas gdy obiekty cech wymagają dynamiczna wysyłka. –

6

Fn, FnMut i FnOnce, przedstawione w drugim odpowiedzi są zamknięcie typów. Rodzaje funkcji, które zamykają swój zakres.

Oprócz zamknięć przechodzącej rdzy obsługuje przechodzącej prostych funkcji (nie-końcowe), na przykład:

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 o to function pointer type.

Jeśli nie potrzebujesz pełnowartościowego zamknięcia niż praca z typami funkcji, często jest to prostsze, ponieważ nie ma do czynienia z tymi trwałościami zamknięcia.

Powiązane problemy