Czym jest `fn () -> ()` w Rust?

Oct 10 2020

Mam zrozumienie Fn (kapitał-F) Cechy: Fn, FnMut, FnOnce. Rozumiem, że są to cechy i działają jak cechy.

Ale co z fn(małe-f)? W edytorach ma inny kolor, co mówi mi, że to nie jest cecha. Może być również używany w niektórych miejscach, w których inne nie mogą (i odwrotnie), chociaż wydaje się, że zachowuje się podobnie w innych przypadkach. Nie mogłem znaleźć niczego wyjaśniającego to bezpośrednio w dokumentach.

Odpowiedzi

8 trentcl Oct 10 2020 at 22:09

Odpowiedź prog-fh jest zasadniczo poprawna, ale brakuje jej pewnych niuansów. Rust ma trzy rodzaje typów funkcjonalnych:

  1. Elementy funkcji są tym, co otrzymujesz, tworząc funkcję za pomocąfn foo() {...}. Jest to również typ konstruktora struktury podobnej do krotki lub wariantu wyliczeniowego. Elementy funkcji mają rozmiar zerowy (nie zawierają danych), a każda funkcja nieogólna ma unikalny typ elementu funkcji, którego nie można nazwać. W komunikatach o błędach kompilator wyświetla te „typy Voldemorta” jako coś podobnegofn() -> () {foo}(z nazwą funkcji w{}).

  2. Zamknięcia są wartościami podobnymi do elementów funkcyjnych, ale domknięcia mogą zawierać dane: kopie lub odniesienia do dowolnych zmiennych, które przechwytują ze swojego środowiska. Jak już wiesz, zamknięcie tworzy się za pomocą składni zamknięcia (|args| expression). Podobnie jak elementy funkcji, zamknięcia mają unikalne typy, których nie można nazwać (renderowane przez kompilator w podobny sposób[closure@src/main.rs:4:11: 4:23]).

  3. Wskaźniki funkcji są tym, o co pytasz: typy, które wyglądająfn() -> (). Wskaźniki funkcji nie mogą zawierać danych, ale nie mają rozmiaru zerowego; jak sugeruje ich nazwa, są wskazówkami. Wskaźnik funkcji może wskazywać na element funkcji lub na zamknięcie, które nic nie przechwytuje, ale nie może mieć wartości null.

Elementy funkcji i zamknięcia są automatycznie przekształcane do odpowiedniego typu wskaźnika funkcji, gdy jest to możliwe, dlatego właśnie let f: fn(i32) = |_| ();działa: ponieważ zamknięcie niczego nie przechwytuje, może zostać przekształcone we wskaźnik funkcji.

Wszystkie trzy rodzaje funkcji, jak wdrożyć odpowiednie Fn, FnMuti FnOncecechy (z wyjątkiem zamknięć nie może realizować Fnlub FnMutw zależności od tego, co przechwytywania). Elementy funkcyjne i wskaźniki funkcyjne również wdrożyć Copy, Clone, Sendi Sync(zamknięcia realizować tylko te cechy, gdy wszystkie ich zawartość zrobić).

Pod względem wydajności wskaźniki funkcji są czymś w rodzaju kompromisu między rodzajami a obiektami cech. Aby można było je wywołać, należy je wyreferencjonować, więc wywołanie wskaźnika funkcji może być wolniejsze niż bezpośrednie wywołanie elementu funkcji lub zamknięcia, ale nadal szybsze niż wywołanie dyn Fnobiektu cechy, które obejmuje wyszukiwanie w tabeli vtable oprócz wywołania pośredniego.

Bibliografia

  • Jaka jest praktyczna różnica między elementem fn a wskaźnikiem fn?
  • Po co projektować język z unikalnymi anonimowymi typami?
  • Jak utworzyć strukturę dla FFI, która zawiera wskaźnik funkcji dopuszczającej wartość null?
  • Dlaczego nie działa przekazanie zamknięcia do funkcji, która akceptuje wskaźnik funkcji?
3 prog-fh Oct 10 2020 at 21:07

Jest to wskaźnik funkcji .

Odnosi się tylko do funkcji, a nie do zamknięcia, ponieważ zawiera tylko adres funkcji, a nie przechwycone środowisko, którego potrzebuje zamknięcie.

FnCecha (kapitał F) może odnosić się zarówno do zamknięcia lub funkcji.

NickDecroos Oct 10 2020 at 21:07

fn jest typem wskaźnika funkcji. Zobacz także w dokumentacji:https://doc.rust-lang.org/std/primitive.fn.html