longitud keywords etiqueta descripcion cual rust

keywords - En Rust, ¿cómo se pasa una función como parámetro?



meta title y meta descripcion (2)

¿Puedo pasar una función como parámetro en Rust (probablemente sí), si esto es posible como puedo hacerlo?

Si no puedes, que es una buena alternativa.

He intentado alguna sintaxis pero no he conseguido

sé que puedo hacerlo

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

pero no como pasar la función como un parámetro a otra función

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


Seguro que puede:

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

Pero esto es Rust, por lo que debe tener en cuenta la propiedad y la vida útil del cierre .

TL; DR; Básicamente hay 3 tipos de cierres (objetos que se pueden llamar):

  1. Fn : El más genérico, es una función pura.
  2. FnMut : Puede modificar los objetos que captura.
  3. FnOnce : El más restringido. Solo se puede llamar una vez porque cuando se llama se consume a sí mismo y sus capturas.

Si está utilizando un simple cierre de puntero a función, entonces el conjunto de captura está vacío y tiene el sabor Fn .

Si quieres hacer cosas más sofisticadas, tendrás que usar las funciones lambda.

ACTUALIZACIÓN : Después de un tiempo más de aprendizaje de Rust, necesito la necesidad de corregir un poco esta respuesta.

En Rust hay punteros a funciones adecuados, que funcionan como los de C. Su tipo es, por ejemplo, fn(i32) -> i32 . El Fn(i32) -> i32 FnMut(i32) -> i32 , FnMut(i32) -> i32 FnOnce(i32) -> i32 y FnOnce(i32) -> i32 son realmente rasgos. Obviamente, un puntero a función siempre implementa los tres, pero Rust también tiene cierres, que pueden o no convertirse a punteros (dependiendo de si el conjunto de captura está vacío) a las funciones, pero implementan algunos de estos rasgos.

Así, por ejemplo, el ejemplo anterior se puede expandir (y corregir el estilo un poco):

fn fun_test_impl(value: i32, f: impl Fn(i32) -> i32) -> i32 { println!("{}", f(value)); value } fn fun_test_dyn(value: i32, f: &dyn Fn(i32) -> i32) -> i32 { println!("{}", f(value)); value } fn fun_test_ptr(value: i32, f: fn(i32) -> i32) -> i32 { println!("{}", f(value)); value } fn times2(value: i32) -> i32 { 2 * value } fn main() { let y = 2; //static dispatch fun_test_impl(5, times2); fun_test_impl(5, |x| 2*x); fun_test_impl(5, |x| y*x); //dynamic dispatch fun_test_dyn(5, &times2); fun_test_dyn(5, &|x| 2*x); fun_test_dyn(5, &|x| y*x); //C-like pointer to function fun_test_ptr(5, times2); fun_test_ptr(5, |x| 2*x); //ok: empty capture set fun_test_ptr(5, |x| y*x); //error: expected fn pointer, found closure }


Fn , FnMut y FnOnce , que se describen en la otra respuesta, son tipos de cierre . Los tipos de funciones que cierran sobre su alcance.

Además de pasar cierres, Rust también admite el paso de funciones simples (sin cierre), como esto:

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 aquí es un tipo de puntero de función .

Si no necesita un cierre completo, trabajar con tipos de funciones a menudo es más simple, ya que no tiene que lidiar con esas sutilezas de por vida.