Czy nauka funkcjonalnego języka jest lepszym programistą OOP? [Zamknięte]

28

Jako programista Java / C # / C ++ dużo słyszę o językach funkcjonalnych, ale nigdy nie musiałem się ich uczyć. Słyszałem również, że wyższy poziom myślenia wprowadzony w językach funkcjonalnych sprawia, że ​​jesteś lepszym programistą języka OOP / języka proceduralnego.

Czy ktoś może to potwierdzić? W jaki sposób poprawia twoje umiejętności programowania?

Jaki jest dobry wybór języka do nauki w celu poprawy umiejętności w mniej zaawansowanym języku?

GavinH
źródło
3
Jeśli kodujesz w C #, już znasz jeden. LINQ jest dość funkcjonalną rzeczą.
SK-logika
Myślę, że OOP jest lepszy do modelowania rzeczywistych obiektów.
Tulains Córdova
1
@ user61852 Większość wzorców projektowych OO nie modeluje niczego na temat „rzeczywistych” obiektów, ale w rzeczywistości wysoce abstrakcyjne koncepcje.
Andres F.,
Być kimś więcej niż programistą Java / C # (+ C ++). Istnieje różnica między gigantycznym szwajcarskim nożem wojskowym z niezbyt małą broszurą, która wyjaśnia, dlaczego wybrałeś ostrze X z 40, a ostrzem, które możesz wykroić cholernie blisko wszystkiego, co chcesz, ponieważ jest cholernie ostre i tylko zakrzywione tak, że bez większego namysłu można zastosować jego siłę cięcia w różnych okolicznościach. (oczywiście z otwieraczem do butelek w rękojeści)
Erik Reppen

Odpowiedzi:

32

I w zasadzie zgadzają się z odpowiedzią FrustratedWithFormsDesign za , ale poprosił także, jak uczenie się nowego paradygmatu pomaga rozwijać swoich umiejętności. Mogę podać kilka przykładów z własnego doświadczenia.

Od czasu nauki programowania funkcjonalnego jestem znacznie bardziej świadomy, z którymi pojęciami pracuję bardziej naturalnie uważanymi za „obiekty” (ogólnie tam, gdzie mutacja ma sens), a które z natury są uważane za niezmienne „wartości” (myślę, że istnieje ważne rozróżnienie , dotykając, gdzie OO ma sens, a kiedy FP ma sens, ale to tylko moja opinia).

Zauważyłem, gdzie mój kod zawiera efekty uboczne, i staram się izolować te miejsca, czyniąc więcej moich funkcji „czystymi” funkcjami. To znacznie poprawia testowalność mojego kodu OO.

Jestem bardziej świadomy cykli w mojej reprezentacji danych. (Na przykład nie sądzę, że można napisać funkcję konwersji listy połączonej na listę podwójnie połączoną w Haskell, więc zauważasz cykle znacznie więcej w tym języku). Unikanie cykli zmniejsza ilość synchronizacji musisz wykonać, aby struktury danych były wewnętrznie spójne, zmniejszając obciążenie związane z udostępnianiem tych struktur między wątkami.

Bardziej prawdopodobne jest, że będę polegać na rekurencji (rekurencyjne konstrukcje zapętlające schematu to rzeczy piękne). Dijkstra poruszył tę kwestię w uwagach na temat programowania strukturalnego - algorytmy rekurencyjne odwzorowują bardzo bezpośrednio indukcję matematyczną, co, jak sugeruje, jest jedynym sposobem intelektualnego udowodnienia poprawności naszych pętli. (Nie sugeruję, że musimy udowodnić, że nasz kod jest poprawny, ale że im łatwiej nam to zrobić, tym bardziej prawdopodobne jest, że nasz kod jest poprawny.)

Bardziej prawdopodobne jest, że użyję funkcji wyższego rzędu. Artykuł Johna Hughesa, Dlaczego programowanie funkcjonalne ma znaczenie . Podkreśla kompozycyjność uzyskaną dzięki zastosowaniu funkcjonalnych technik programowania, przy czym funkcje wyższego rzędu odgrywają ważną rolę.

Ponadto, jak poruszono w odpowiedzi Jettiego , przekonasz się, że wiele pomysłów na FP jest włączanych do nowszych języków OO. Zarówno Ruby, jak i Python zapewniają wiele funkcji wyższego rzędu, słyszałem LINQ opisany jako próba wprowadzenia obsługi rozumień monadycznych do C #, nawet C ++ ma teraz wyrażenia lambda.

Aidan Cully
źródło
@Aidan: wrt lambdas w C ++ 0x, w każdym razie nowe kompilatory C ++ już je wprowadziły.
Matthieu M.
1
„Obiekt” jako „rzecz posiadająca stan zmienny” jest bardzo powszechny, ale wzorzec Obiekt Wartości istnieje już od wielu lat.
Frank Shearar
@ Matthieu, dzięki, zaktualizowałem tekst, aby to odzwierciedlić.
Aidan Cully,
@Frank: dzięki za wskaźnik. Nie umieściłem tego w odpowiedzi, ale główny zarzut, który muszę uczynić, tworząc Wartości na Obiekty, dotyczy rozróżnienia między interfejsami obiektowymi (które są własnością obiektów) i operacjami (w których relacje między obiektami są bardziej pierwotne niż same obiekty). 1 + 2jest matematycznie równoważny 2 + 1, ale 1.+(2)jest implementowany inaczej niż 2.+(1). Istnieje wiele problemów z oprogramowaniem SW, które można zrozumieć bardziej naturalnie przy użyciu operacji niż przy użyciu interfejsów obiektowych.
Aidan Cully,
1
@Aidan Czy czytałeś książkę Williama Cooka „On Understanding Data Abstraction, Revisited”? Zagłębia się w różnice między obiektami i narzędziami ADT, o czym właśnie sugerujesz.
Frank Shearar
32

Nie powiedziałbym, że z pewnością sprawi, że staniesz się lepszym programistą OOP, ale wprowadzi cię w nowy sposób myślenia, a to może sprawić, że będziesz lepiej w rozwiązywaniu problemów w ogóle, nie tylko w zakresie OOP.

FrustratedWithFormsDesigner
źródło
3
Biorąc pod uwagę, że obiekty są w rzeczywistości funkcjami wyższego rzędu, odkryłem, że uczenie się rzeczy FP pomogło bezpośrednio w moim OOP. Jest jednak, jak mówisz, bardziej ogólnie stosowany / pomocny.
Frank Shearar
12

Nauka języka funkcjonalnego - dla mnie Lisp - naprawdę pomaga w budowaniu aplikacji równoległych. Metody funkcjonalne (oparte na stanie, bez skutków ubocznych) są znacznie łatwiejsze do synchronizacji i łatwiej jest zabezpieczyć wątek, ponieważ zależą tylko od ich wkładu. Oznacza to, że jedynymi danymi, które należy obserwować dla danego obszaru kodu, są przekazywane parametry. Ułatwia to także debugowanie.

Michael K.
źródło
Przekonasz się również, że pomaga to w bibliotekach wątków, które zwykle oczekują czystych funkcji jako swoich zadań. Może również pośrednio pomóc, są miejsca, w których napiszę kod OO w rodzaju „stylu funkcjonalnego”, w którym istnieje „parametr będący właścicielem”, który niejawnie blokuje wiązkę obiektów, do których się odwołuje i które są używane przez funkcję . Dopóki dokumentujesz swoje oczekiwania (i testujesz je na jednostce), może to dać lepszy kod wielowątkowy z kilkoma problemami z blokowaniem. I kilka wyraźnych zamków.
Nigdy nie słyszałem o Prologu nazywanym językiem funkcjonalnym. Jeśli wystarczająco zmrużyłem oczy, mogę niejasno zobaczyć, w jaki sposób Prolog może pomóc w FP.
Frank Shearar
1
Prolog nie jest językiem funkcjonalnym. To język logiczny. Jeśli chcesz mieć język logiczny podobny do Prologa, który ma również zintegrowane programowanie funkcjonalne, pamiętaj, że możesz pochwalić się Mercury . Ostrzeżenie: To trochę zrani twój mózg, nawet jeśli znasz już Prologa.
WŁAŚNIE MOJA poprawna OPINIA
@ PO PROSTU MOJA poprawna OPINIA: Tak, myślę, że masz rację. Zgaduję, że muszę dowiedzieć się więcej o językach funkcjonalnych!
Michael K,
1
@moz: Tak, chciałbym, żeby Java miała lambdas. Anonimowe Threadprzedmioty są ... niezdarne.
Michael K,
9

Nauka jakiegokolwiek innego paradygmatu programowania poprawi Twoje umiejętności programistyczne w ogóle. Programowanie, gdy nie jest to materiał naukowy (a nawet często), jest w zasadzie rozwiązywaniem problemów. Jednym słowem myślenie. Różne paradygmaty to różne sposoby myślenia o problemach i ich rozwiązaniach. Nie myśl więc o tym jako o „nauce języka funkcjonalnego”. Pomyśl o tym jako o „uczeniu się innego sposobu myślenia o problemach i ich rozwiązaniach”. Wtedy zobaczysz zalety nauki języka, nawet jeśli nigdy go nie używasz.

Aby odpowiedzieć na twoje konkretne pytanie, byłem programistą C ++ w dawnych czasach (wcześniej był standard dla C ++). Śledziłem wszystkie zwykłe rzeczy z obiektami utrzymującymi stan zmanipulowanymi metodami itp. Itd. Potem natknąłem się na Haskella i nauczyłem się (wiele) tego. (Nie sądzę, żeby ktokolwiek naprawdę się uczył Haskella.) Ćwiczenie wydawało się wtedy trochę zmarnowane, dopóki jeden z moich kolegów, tester przydzielony do mojej grupy, nie skomentował, że mój kod staje się łatwiejszy do przetestowania.

Stało się tak, że zacząłem sprawiać, by moje przedmioty stawały się coraz bardziej niezmienne. Klasy ze złożonym stanem zmiennym zaczęły być zastępowane klasami, które klonowały się ze zmianami, zwracając nowe obiekty. Obiekty współdzielone zaczęły być zastępowane obiektami, które miały semantykę kopiowania przy zapisie (dając iluzję wielu klonów obiektów bez narzutu pamięci). Funkcje nie wywoływały żadnych skutków ubocznych, chyba że absolutnie konieczne; czysta, matematyczna definicja „funkcji” była coraz bardziej normą. Wszystko to zaczęło się dziać naturalnie w moim kodzie - bez udziału świadomej myśli - gdy badałem coraz więcej funkcjonalnej przestrzeni programistycznej.

Teraz moim celem jest nauczenie się co najmniej jednego nowego paradygmatu programistycznego co dwa lata (nawet jeśli jest to tylko niewielki paradygmat rozszerzenia, taki jak AOP) i co najmniej dwóch nowych języków w ramach każdego paradygmatu (jeden tak czysty, jak to możliwe, jeszcze jeden hybrydowy / praktyczny ). Każdy z nich dał mi nowe narzędzia intelektualne do zastosowania w całym moim programowaniu w dowolnym języku, więc moim zdaniem czas poświęcony na ich naukę nie został nawet trochę zmarnowany.

WŁAŚNIE MOJA poprawna OPINIA
źródło
3

Powiedziałem to wcześniej i powiem to jeszcze raz, nauka języków funkcjonalnych zdecydowanie poprawiła mój C #. Pomogło mi zrozumieć lambdas (i pomogło mi je pokochać). Uświadomiłem sobie również, jak bardzo wolę programowanie funkcjonalne (F #) podczas pracy z operacjami asynchronicznymi!

Jetti
źródło
3

Kod maszynowy to nic innego jak lista efektów ubocznych - poleceń wykonywanych bezpośrednio przez procesor. Efekty uboczne w C są różne, zamiast obsługi rejestrów i fizycznego sprzętu, zajmujesz się zestawem abstrakcji i pozwalasz kompilatorowi wykonać całą brudną robotę. C pozwala również uporządkować efekty uboczne w pętlach, a jeśli tak, to w instrukcjach. C ++ poprawia C, dodając OOP i niektóre bardzo potrzebne funkcje do języka. Java i C # dodają odśmiecanie, a Python dodaje dynamiczne pisanie.

Nawet z tymi wszystkimi funkcjami - dynamiczne pisanie, wyrzucanie elementów bezużytecznych itp. Programy w tych językach są nadal całkowicie oparte na efektach ubocznych. Funkcjonalne języki programowania, takie jak Scheme, Clojure, Haskell i ML, są czymś zupełnie innym, języki te są bliżej matematyki niż kodu maszynowego. Zamiast efektów ubocznych przekazujesz wartości wokół funkcji.

Jaki jest dobry wybór języka do nauki w celu poprawy umiejętności w mniej zaawansowanym języku?

Polecam Schemat , jest minimalny i był używany w starych klasach wprowadzających MIT. Inne funkcjonalne języki programowania są znacznie trudniejsze do nauczenia. Clojure przynosi ze sobą wszystkie zawiłości Javy, ML ma skomplikowany system statyczny, Haskell jest czasem określany jako język akademicki - nie jest idealny dla początkujących i tak dalej. Z drugiej strony schemat jest łatwy do nauczenia się i zrozumienia.

W jaki sposób poprawia twoje umiejętności programowania?

Prawie wszystkie języki programowania wysokiego poziomu mają funkcje i rekurencję - pojęcia, na których opiera się programowanie funkcjonalne. Jako taka, twoja wiedza na temat FP powinna być pomocna prawie wszędzie, jednak jeśli naprawdę chcesz programować funkcjonalnie, powinieneś używać języka, w którym jest on naturalny i skuteczny, a nie próbować dopasować projekt innej osoby do twoich upodobań, to znaczy powinieneś używać funkcjonalnego języka programowania do programowania funkcjonalnego.

jhuni
źródło