Za pomocą generatorów i lambda możemy programować funkcjonalnie za pomocą Pythona. To samo możesz osiągnąć również dzięki Ruby.
Pytanie zatem brzmi: dlaczego potrzebujemy konkretnych funkcjonalnych języków programowania, takich jak Erlang, Haskell i Scheme? Czy jest coś innego niż te specyficzne funkcjonalne języki programowania? Dlaczego nie możemy po prostu używać Pythona do programowania funkcjonalnego?
programming-languages
python
functional-programming
Joshua Partogi
źródło
źródło
Odpowiedzi:
Doceniam to pytanie, ponieważ osobiście jestem wielkim fanem zarówno języka Python, jak i funkcjonalnego stylu programowania. Mam duże doświadczenie w Pythonie i ostatnio zacząłem uczyć się języka Haskell, więc oto kilka punktów opartych na moich osobistych doświadczeniach na temat różnic między tymi językami, z funkcjonalnego punktu widzenia.
Czystość
Nawet jeśli nie zależy ci na czystości funkcji (tj. Braku efektów ubocznych) jako zasady, ma to praktyczny wpływ na to, jak łatwo można odczytać kod i powód. Nawet jeśli utrzymujesz czystość we własnych funkcjach Pythona, istnieje duża różnica w wymuszaniu czystości przez kompilator, a przede wszystkim w posiadaniu standardowej biblioteki zbudowanej w oparciu o czystość i niezmienne struktury danych.
Wydajność
W zależności od domeny aplikacji możesz, ale nie musi to zależeć od wydajności, ale pisanie statyczne i gwarantowana czystość daje kompilatorowi znacznie więcej możliwości pracy w porównaniu z Pythonem i innymi dynamicznymi językami (chociaż muszę przyznać, że PyPy świetnie sobie radzi inroads, i np. LuaJIT graniczy z cudami).
Optymalizacja ogona
Związane z wydajnością, ale nieco inne. Nawet jeśli nie przejmujesz się zbytnio wydajnością środowiska wykonawczego, brak optymalizacji wywołania ogona (szczególnie w przypadku rekurencji ogona) ogranicza sposoby implementacji algorytmów w Pythonie bez przekraczania limitów stosu.
Składnia
Jest to największy powód, dla którego zacząłem patrzeć na „prawdziwe” języki funkcjonalne zamiast po prostu używać Pythona z funkcjonalnym stylem. Chociaż myślę, że Python ma ogólnie bardzo ekspresyjną składnię, ma jednak pewne słabe punkty specyficzne dla kodowania funkcjonalnego. Na przykład:
f = g . h
Vs.f = lambda *arg: g(h(*arg))
f = map g
Vs.f = functools.partial(map, g)
sum = reduce (+) lst
Vs.sum = reduce(operator.add, lst)
y = func1 $ func2 $ func3 x
łatwiej jest je odczytać niży = func1(func2(func3(x)))
po zapoznaniu się z tą notacją.źródło
Oto najważniejsze różnice:
Haskell
Haskell i Erlang
Erlang
Schemat
Wszystkie języki
Ponadto powinieneś rzucić okiem na języki z rodziny ML, takie jak SML, Ocaml i F # i Scala, które łączą OO i programowanie funkcjonalne w nowy sposób. Wszystkie te języki mają unikalne interesujące funkcje.
źródło
Trudno jest dokładnie zdefiniować, czym jest „język funkcjonalny” - spośród wymienionych języków tylko Haskell jest czysto funkcjonalny (wszystkie inne mają podejście hybrydowe). Istnieją jednak pewne funkcje językowe, które są bardzo pomocne w programowaniu funkcjonalnym, a Ruby i Python nie mają ich wystarczająco dużo, aby były bardzo dobrym środowiskiem dla FP. Oto moja osobista lista kontrolna, w kolejności według ważności:
Konieczność (1) powinna być oczywista - funkcje wyższego rzędu są niezwykle trudne bez funkcji pierwszej klasy. Kiedy ludzie mówią, że Ruby i Python są dobrymi językami dla FP, zwykle mówią o tym. Jednak ta szczególna cecha jest konieczna, ale niewystarczająca, aby język był dobry dla programu ramowego.
(2) jest tradycyjną koniecznością dla FP, odkąd wynaleziono Schemat. Bez TCO niemożliwe jest programowanie z głęboką rekurencją, która jest jednym z kamieni węgielnych FP, ponieważ dostajesz przepełnienia stosu. Jedynym „funkcjonalnym” (według popularnej definicji) językiem, który go nie ma, jest Clojure (z powodu ograniczeń JVM), ale Clojure ma wiele różnych metod symulowania TCO. (FYI, Ruby TCO jest specyficzny dla implementacji , ale Python konkretnie go nie obsługuje ). Powodem, dla którego TCO musi być zagwarantowane, jest to, że jeśli jest specyficzne dla implementacji, głębokie funkcje rekurencyjne zepsują się z niektórymi implementacjami, więc nie można tak naprawdę w ogóle ich używaj.
(3) to kolejna wielka rzecz, którą współczesne języki funkcjonalne (zwłaszcza Haskell, Erlang, Clojure i Scala) mają w przeciwieństwie do Ruby i Pythona. Bez wchodzenia w zbyt wiele szczegółów, gwarantowana niezmienność eliminuje całe klasy błędów, szczególnie w sytuacjach współbieżnych, i pozwala na porządne rzeczy, takie jak trwałe struktury danych . Bardzo trudno jest skorzystać z tych korzyści bez wsparcia na poziomie językowym.
(4) jest dla mnie najbardziej interesującą rzeczą w językach czysto funkcjonalnych (w przeciwieństwie do języków hybrydowych). Rozważ następującą niezwykle prostą funkcję Ruby:
Wygląda to na czystą funkcję, ale z powodu przeciążenia operatora może mutować albo parametr, albo powodować działania niepożądane, takie jak drukowanie na konsoli. Jest mało prawdopodobne, aby ktoś przeciążył
+
operatora, aby wywołać efekt uboczny, ale język nie daje żadnych gwarancji. (To samo dotyczy Pythona, choć może nie w tym konkretnym przykładzie).Z drugiej strony w języku czysto funkcjonalnym istnieją gwarancje na poziomie językowym, że funkcje są względnie przejrzyste. Ma to wiele zalet: proste funkcje można łatwo zapamiętać; można je łatwo przetestować bez polegania na jakimkolwiek stanie globalnym; a wartości w obrębie funkcji można oceniać leniwie lub równolegle bez obawy o problemy z współbieżnością. Haskell w pełni z tego korzysta, ale nie znam wystarczającej liczby języków funkcjonalnych, aby wiedzieć, czy tak.
Mimo to można stosować techniki FP w prawie każdym języku (nawet Java). Na przykład Google MapReduce jest inspirowany funkcjonalnymi pomysłami, ale o ile wiem, nie używają żadnych „funkcjonalnych” języków w swoich dużych projektach (myślę, że głównie używają C ++, Java i Python).
źródło
Wymienione języki są bardzo różne.
Podczas gdy Python i Ruby są dynamicznie pisanymi językami, Haskell jest wpisywany statycznie. Erlang jest językiem współbieżnym i wykorzystuje model aktora i bardzo różni się od wszystkich innych języków, o których wspominasz.
Python i Ruby mają wiele konstrukcji imperatywnych, podczas gdy w bardziej czystym języku funkcjonalnym, takim jak Haskell, wszystko zwraca coś lub innymi słowy wszystko jest funkcją.
źródło
Jak zwykle spóźnia się na przyjęcie, ale i tak coś powie.
Funkcjonalny język programowania nie jest językiem, który umożliwia programowanie funkcjonalne. Gdybyśmy mieli stosować tę definicję, praktycznie każdy język w dowolnym miejscu jest funkcjonalnym językiem programowania. (Nawiasem mówiąc, to samo dotyczy OOP. Możesz pisać w stylu OOP w C. Jeśli chcesz, to zgodnie z logiką C jest językiem OOP.)
To, co sprawia, że funkcjonalny język programowania nie jest tym, na co pozwala ci programować, jest tym, na co pozwala ci programować w prosty sposób . To jest klucz.
Python ma więc lambdy (które są niezwykle anemicznymi sprawami przypominającymi zamknięcie) i oferuje kilka funkcji bibliotecznych, które zobaczysz w bibliotekach funkcjonalnych, a także „map” i „fold”. Jednak to nie wystarczy, aby uczynić go funkcjonalnym językiem programowania, ponieważ trudno jest konsekwentnie programować w nim odpowiedni funkcjonalny styl (a język z pewnością nie wymusza tego stylu!). W jego rdzeniu Python jest imperatywnym językiem związanym z operacjami stanu i manipulowania stanem, co jest po prostu sprzeczne z semantyką wyrażeń i oceny wyrażeń w języku funkcjonalnym.
Dlaczego więc mamy funkcjonalne języki programowania, skoro Python (lub Ruby (lub wstaw wybrany język)) może „robić programowanie funkcjonalne”? Ponieważ Python i inni nie potrafią poprawnie zaprogramować funkcjonalnie. Dlatego.
źródło
Państwo może zrobić programowania funkcyjnego w Javie (patrz np http://functionaljava.org/ ). Można również zrobić programowanie obiektowe w C . To po prostu nie takie idiomatyczne.
Rzeczywiście nie potrzebujemy absolutnie Erlanga, Haskella, Scheme ani żadnego konkretnego języka programowania, ale wszystkie reprezentują różne podejścia i różne kompromisy, dzięki czemu niektóre zadania są łatwiejsze, a niektóre trudniejsze. To, czego powinieneś użyć, zależy od tego, co chcesz osiągnąć.
źródło
To pytanie można zastosować do nieskończonej liczby języków i paradygmatów.
Większość, jeśli nie wszystkie języki istnieją z konkretnego powodu. Istnieją, ponieważ ktoś potrzebował, aby żaden obecny język nie był wypełniony lub źle wypełniony. (To oczywiście nie dotyczy wszystkich języków, ale uważam, że dotyczy większości znanych języków.) Na przykład Python został pierwotnie opracowany do współpracy z systemem operacyjnym Amoeba [ 1 , 2 ], a Erlang został stworzony, aby pomóc w rozwoju aplikacji telefonicznych [ 3 ]. Tak więc jedna odpowiedź na pytanie „Dlaczego potrzebujemy innego języka funkcjonalnego?” może po prostu być, ponieważ [insert-name-of-someone-who-know-how-to-design-languages] nie podobało się to, w jaki sposób Python to zrobił.
To właściwie podsumowuje, jak sądzę, odpowiedź. Chociaż możesz zrobić wszystko za pomocą Pythona, co możesz zrobić za pomocą funkcjonalnego języka, to czy naprawdę chcesz? Wszystko, co możesz zrobić w C, możesz zrobić w asemblerze, ale czy chcesz? Różne języki zawsze będą najlepsze w robieniu różnych rzeczy i tak właśnie powinno być.
źródło
Programowanie funkcjonalne dotyczy zarówno paradygmatu projektowania, jak i konkretnych funkcji językowych. Innymi słowy, lambdas i funkcja mapy nie tworzą funkcjonalnego języka programowania. Python i Ruby mają pewne funkcje inspirowane funkcjonalnymi językami programowania, ale nadal piszesz kod w bardzo imperatywny sposób. (To coś w stylu C: możesz pisać kod podobny do OO w C, ale nikt poważnie nie uważa C za język OO.)
Spójrz: programowanie funkcjonalne to nie tylko lambda lub
map
funkcje wyższego rzędu. Chodzi o projekt . Program napisany w „prawdziwym” funkcjonalnym języku programowania rozwiązuje problemy poprzez kompozycję funkcji. Chociaż programy napisane w Ruby lub Python mogą korzystać z funkcji podobnych do FP, zazwyczaj nie czytają jak zestaw złożonych funkcji.źródło
Każdy język funkcjonalny, o którym wspomniałeś, całkiem dobrze wpasowuje się w pewną niszę, a wzorce idiomatyczne, które każdy zachęca, sprawiają, że bardzo dobrze nadają się do pewnych zadań, których nie można byłoby wykonać w Pythonie, chyba że zbudujesz ogromną bibliotekę modułów pomocniczych. Najbardziej oczywistą z takich niszowych doskonałości jest model współbieżności Erlanga. Pozostałe mają również podobne zalety.
źródło
Każda koncepcja dostępna w rachunku lambda, LISP i schemacie jest dostępna w Pythonie, więc tak, możesz w niej programować funkcjonalnie. To, czy jest to wygodne, czy nie, zależy od kontekstu i smaku.
Możesz łatwo napisać interpreter LISP (lub inny język funkcjonalny) w Pythonie (Ruby, Scala) (co to oznacza?). Możesz napisać interpreter dla Pythona, używając czysto funkcjonalnego, ale zajęłoby to dużo pracy. Nawet języki „funkcjonalne” są obecnie wieloparadygmatyczne.
Ta stara i piękna książka ma większość (choć nie wszystkie) odpowiedzi na temat tego, na czym polega istota programowania funkcjonalnego.
źródło
eval()
funkcję, która jest potrzebna, aby kod zawierał dane , ale idzie dalej: pozwala modyfikować większość środowiska wykonawczego, np. W LISP.eval()
to metaprogramowanie środowiska wykonawczego. Czasami jest przydatny, ale jest niezwykle drogi. Makra Lisp są różne, jest to metaprogramowanie czasu kompilacji. Nie jest dostępny w Pythonie w żadnej użytecznej formie.Ponieważ Python może również programować w niefunkcjonalnym stylu, co nie jest wystarczające dla purystów FP. Jednak bardziej pragmatyczni koderzy mogą cieszyć się zaletami funkcjonalnego stylu, nie będąc do tego dogmatycznym:
- John Hughes, Dlaczego programowanie funkcjonalne ma znaczenie
źródło
goto
jest okropny.call-with-current-continuation
.