Krótka odpowiedź brzmi: wszystko zostanie skompilowane do jakiegoś niskiego poziomu języka na końcu (język zespołu lub maszyny wirtualnej). Języki funkcjonalne i imperatywne są na równej stopie: muszą skompilować mechanizmy abstrakcji, aby dopasować to, co jest dostępne na maszynie.
Tam, gdzie językiem jest różnica, to jak blisko pasują do kodu niskiego poziomu (zapewniając funkcje niskopoziomowe w celu zoptymalizowania kodu ręcznie, gdy jest to pożądane) i które optymalizacje umożliwiają lub ułatwiają dzięki czystej semantyki zapewniającej silne uzasadnienie gwarancji .
Na przykład podczas kompilacji na kod natywny rekurencja nie jest (ogólnie) kompilowana w pętle, ale w skoki do etykiet, tak jak pętle: większość języków złożeniowych nie ma ani pętli, ani rekursji. Oczywiście, jeśli kompilujesz na maszynie wirtualnej, która ma pętle, ale nie ma skoków, musisz utworzyć pętle; jest to problem na przykład na maszynie wirtualnej Java, ponieważ ogólne wywołania ogona są bardziej ekspresyjne niż same pętle i trzeba obejść to ograniczenie, rezygnując z pewnej wydajności.
"Zaletą" programów funkcjonalnych może być to, że semantyka jest lepiej zachowana, można łatwiej rozumować o programie, a na przykład wyrażać optymalizacje w prostszy sposób. Obecnie wiele kompilatorów korzysta z pośredniej formy Single Static Assignment (SSA), która w zasadzie jest językiem funkcjonalnym niskiego poziomu¹ - choć została odkryta niezależnie przez ludzi ze społeczności kompilatorów. Większość optymalizacji jest łatwiejsza do zrobienia po wyeliminowaniu mutacji zmiennych, a zmienna zachowuje tę samą wartość we wszystkich jej zakresach. Istnieją pewne techniki dokonywania rejestracji rejestru w more efficient ways na takich funkcjonalnych formach pośrednich.
¹: Zobacz krótki artykuł Andrew Appel z 1998 roku: SSA is Functional Programming; Jeśli jesteś zainteresowany szczegółami na temat formularza SSA, tutaj są some reading notes o związku między SSA i innymi funkcjonalnymi pośrednimi formularzami, takimi jak CPS.
Można również uzyskać zalety optymalizacji od czystości (brak efektów ubocznych lub co najmniej dobrej kontroli, dla której obliczenia będą wolne od skutków ubocznych) i pisanie statyczne. Z czystości można czerpać potężne optymalizacje, takie jak deforestation lub fusion (eliminując pośrednie struktury danych), a od pisania można uzyskać silne gwarancje dotyczące kształtu wartości (dlatego niektóre języki dynamiczne próbują dopuszczać pewne ograniczone adnotacje typu do optymalizacji celów), które umożliwiają generowanie lepszego kodu.
Jeśli chodzi o dostęp do funkcji niskopoziomowych: Fortran, C i C++ są prawdopodobnie najlepszymi i najpowszechniej dostępnymi językami "mogą przejść na bardzo niski poziom".Niektóre języki starają się zapewnić niektóre z tych możliwości: na przykład ATS (początkowo funkcjonalny język programowania, choć jest tak goły metal, że jest raczej trudny do zobaczenia) zapewnia dobrą kontrolę przy alokacji sterty w alokacji stosu, zarówno Haskell, jak i the CLR (C#,etc.) zapewniają bez opakowania typy złożone, jako szczególny przypadek takiego rozumowania niskiego poziomu, i podobnie Rust próbuje dostarczyć ci sposobów podejmowania niskonakładowych decyzji dotyczących zużycia pamięci.
Jednak jest to przydatne, gdy wyizolowałeś mały fragment kodu, który jest krytyczny dla twoich osiągnięć, i chcesz go zoptymalizować (rezygnując z pewnej elastyczności/prostoty/łatwości konserwacji), to się nie zmieni twoje życie w codziennych sytuacjach, chyba że jesteś programistą wbudowanym/jądra. Prawdopodobnie uzyskasz większy ogólny wzrost wydajności dzięki produktywnemu językowi, który pozwoli Ci na użycie odpowiedniego poziomu abstrakcji i poświęci więcej czasu na wybór właściwego projektu i algorytmów Twojego problemu. Oczywiście, można chcieć mieć jedno i drugie, i jest to możliwe, ale trudne.
Co rozumiesz przez zalety, które trafiają do tłumacza? – sepp2k
@ sepp2k Podobnie jak w przypadku konkretnych przykładów, które wymieniłem: wydaje się, że istnieją różne wspólne cechy funkcjonalnych języków programowania. Chciałbym wiedzieć, czy te funkcje, które wydają się różnicować funkcjonalne programowanie od imperatywnego stylu, faktycznie będą miały jakąkolwiek różnicę w czasie wykonywania, lub jest to po prostu bardziej powierzchowna różnica w stylu kodowania, który różnicuje te dwa. Ma sens? –
Zmieniłem tytuł i odrobinę pytania, mam nadzieję, że teraz jest to bardziej przejrzyste. –