5

Mam ogólne pytanie o tłumaczy języków funkcyjnych:Czy Runtime zazwyczaj używają interpretację imperatyw podobnego kodu językowego funkcjonalny

istnieją właściwie żadnych korzyści z używania języka funkcjonalnego kontra języku bezwzględnej w czasie wykonywania (lub dotrzeć do tłumacza)?

Żadne z pytań, które zobaczyłem (np. this) nie jest tak naprawdę prawdziwe, a wyszukiwania są zalewane argumentami dotyczącymi definicji różnych języków.

EDYCJA: Rozebrałem się na jedyne pytanie, na które skończyło się wymagające odpowiedzi.

+2

Co rozumiesz przez zalety, które trafiają do tłumacza? – sepp2k

+1

@ 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? –

+0

Zmieniłem tytuł i odrobinę pytania, mam nadzieję, że teraz jest to bardziej przejrzyste. –

Odpowiedz

29

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.

+0

To jest idealne, dziękuję. –

0

Czy rzeczywiście istnieją jakieś korzyści z używania języka funkcjonalnego w porównaniu z imperatywnym językiem w środowisku uruchomieniowym (lub które trafiają do interpretera)?

Tak. Jeśli używasz języka funkcjonalnego, zaletą jest to, że pisarz tłumacza jest prawdopodobnie wykonywany szybciej. Jeśli użyjesz imperatywnego, możesz użyć nieco mniej pamięci i procesora.

Tak więc, bez względu na to, jak to robisz, są zalety.

Ale, biorąc pod uwagę dwóch tłumaczy, jeden napisany w języku imperatywnym, a drugi w języku funkcjonalnym, i biorąc pod uwagę, że oba są poprawne, nie można było stwierdzić na podstawie wyników programu, którego tłumacza użyto.

Powiązane problemy