En Rust, ¿qué es `fn () -> ()`?
Tengo una comprensión de los rasgos Fn (capital-F): Fn, FnMut, FnOnce. Entiendo que son rasgos y funcionan como rasgos.
Pero ¿qué pasa con fn(minúscula-f)? Obtiene un color diferente en los editores, lo que me dice que no es un rasgo. También se puede usar en algunos lugares donde otros no pueden (y viceversa), aunque parece comportarse de manera similar en otros casos. No pude encontrar nada que lo explique directamente en los documentos.
Respuestas
La respuesta de prog-fh es esencialmente correcta, pero carece de matices. Rust tiene tres tipos de tipos de funciones:
Los elementos de función son lo que obtiene cuando crea una función usando
fn foo() {...}. También es el tipo de constructor de una estructura similar a una tupla o una variante de enumeración. Los elementos de función son de tamaño cero (no contienen datos), y cada función no genérica tiene un tipo de elemento de función único e innombrable. En los mensajes de error, el compilador muestra estos "tipos de Voldemort" como algo así comofn() -> () {foo}(con el nombre de la función en{}).Los cierres son valores similares a los elementos de función, pero los cierres pueden contener datos: copias o referencias a las variables que capturan de su entorno. Como ya sabe, crea un cierre utilizando la sintaxis de cierre (
|args| expression). Al igual que los elementos de función, los cierres tienen tipos únicos y sin nombre (representados por el compilador de forma similar[closure@src/main.rs:4:11: 4:23]).Los punteros de función son lo que está preguntando: los tipos que parecen
fn() -> (). Los punteros de función no pueden contener datos, pero no tienen tamaño cero; como sugiere su nombre, son indicadores. Un puntero de función puede apuntar a un elemento de función oa un cierre que no captura nada, pero no puede ser nulo.
Los elementos de función y los cierres se coaccionan automáticamente al tipo de puntero de función relevante cuando es posible, por eso let f: fn(i32) = |_| ();funciona: dado que el cierre no captura nada, se puede coaccionar a un puntero de función.
Los tres tipos de función como implementar el correspondiente Fn, FnMuty FnOncerasgos (excepto que los cierres podrían no aplicar Fno FnMutdependiendo de lo que captura). Elementos de función y los punteros de función también implementan Copy, Clone, Sendy Sync(cierres sólo se implementan estas características cuando todos sus contenidos hacen).
Los punteros de función en cuanto al rendimiento son una especie de compromiso entre genéricos y objetos de rasgo. Deben desreferenciarse para ser llamados, por lo que llamar a un puntero de función puede ser más lento que llamar a un elemento de función o cierre directamente, pero aún más rápido que llamar a un dyn Fnobjeto de rasgo, lo que implica una búsqueda de vtable además de la llamada indirecta.
Referencias
- ¿Cuál es la diferencia práctica entre el elemento fn y el puntero fn?
- ¿Por qué diseñar un lenguaje con tipos anónimos únicos?
- ¿Cómo hago una estructura para FFI que contiene un puntero de función anulable?
- ¿Por qué no funciona pasar un cierre a una función que acepta un puntero de función?
Es un tipo de puntero de función .
Se refiere solo a una función, no a un cierre, ya que contiene solo la dirección de la función, no el entorno capturado que necesita un cierre.
Un Fnrasgo (F mayúscula) puede referirse a un cierre o una función.
fn es el tipo de puntero de función. Consulte también aquí en la documentación:https://doc.rust-lang.org/std/primitive.fn.html