No Rust, o que é `fn () -> ()`?
Eu tenho uma compreensão dos traços Fn (capital-F): Fn, FnMut, FnOnce. Eu entendo que eles são traços e funcionam como traços.
Mas e quanto a fn(f minúsculo)? Ele ganha uma coloração diferente nos editores, o que me diz que não é uma característica. Também pode ser usado em alguns lugares onde os outros não podem (e vice-versa), embora pareça se comportar da mesma forma em outros casos. Não consegui encontrar nada explicando isso diretamente nos documentos.
Respostas
A resposta de prog-fh é essencialmente correta, mas carece de algumas nuances. Rust possui três tipos de tipos semelhantes a funções:
Itens de função são o que você obtém ao criar uma função usando
fn foo() {...}. É também o tipo de construtor de uma estrutura semelhante a uma tupla ou variante enum. Os itens de função têm tamanho zero (não contêm dados) e cada função não genérica tem um tipo de item de função único e inominável. Em mensagens de erro, o compilador exibe esses "tipos de Voldemort" como algo semelhantefn() -> () {foo}(com o nome da função em{}).Fechamentos são valores semelhantes a itens de função, mas fechamentos podem conter dados: cópias ou referências a quaisquer variáveis que capturem de seu ambiente. Como você já sabe, você cria um encerramento usando a sintaxe de encerramento (
|args| expression). Assim como os itens de função, os encerramentos têm tipos únicos e inomináveis (renderizados pelo compilador de forma semelhante[closure@src/main.rs:4:11: 4:23]).Ponteiros de função são o que você está perguntando: os tipos que se parecem
fn() -> (). Os ponteiros de função não podem conter dados, mas não têm tamanho zero; como o nome sugere, eles são ponteiros. Um ponteiro de função pode apontar para um item de função ou para um fechamento que não captura nada, mas não pode ser nulo.
Itens de função e fechamentos são automaticamente forçados para o tipo de ponteiro de função relevante quando possível, então é por isso que let f: fn(i32) = |_| ();funciona: como o encerramento não captura nada, ele pode ser forçado para um ponteiro de função.
Todas as três funções semelhantes tipos implementar o relevante Fn, FnMute FnOncetraços (exceto que fechamentos pode não implementar Fnou FnMutdependendo do que eles captura). Itens de função e ponteiros de função também implementar Copy, Clone, Sende Sync(fechamentos única implementar essas características, quando todos os seus conteúdos fazem).
Em termos de desempenho, os ponteiros de função são uma espécie de meio-termo entre genéricos e objetos de características. Eles precisam ser desreferenciados para serem chamados, portanto, chamar um ponteiro de função pode ser mais lento do que chamar um item de função ou encerramento diretamente, mas ainda mais rápido do que chamar um dyn Fnobjeto de característica, o que envolve uma pesquisa vtable além da chamada indireta.
Referências
- Qual é a diferença prática entre item fn e ponteiro fn?
- Por que criar uma linguagem com tipos anônimos exclusivos?
- Como faço uma estrutura para FFI que contém um ponteiro de função anulável?
- Por que passar um encerramento para uma função que aceita um ponteiro de função não funciona?
É um tipo de ponteiro de função .
Ele se refere apenas a uma função, não a um encerramento, pois contém apenas o endereço da função, não o ambiente capturado de que um encerramento precisa.
Um Fntraço (F maiúsculo) pode se referir a um fechamento ou a uma função.
fn é o tipo de ponteiro de função. Veja também aqui na documentação:https://doc.rust-lang.org/std/primitive.fn.html