Kiedy używać funkcjonalnego języka programowania?


90

W jakich sytuacjach powinienem wybrać funkcjonalny język programowania zamiast bardziej rozwlekłego języka zorientowanego obiektowo, takiego jak C ++, C # czy Java?

Rozumiem, co to jest programowanie funkcjonalne, czego tak naprawdę nie rozumiem, dla jakiego rodzaju problemów jest to idealne rozwiązanie?


Odpowiedź na to pytanie znajduje się tutaj stackoverflow.com/questions/381685/…
krosenvold

2
Zawsze. A przynajmniej nigdy nigdy.
Shelby Moore III

1
W przypadku lambd C # działa na granicy funkcjonalności.
JD

Odpowiedzi:


50

Moim zdaniem języki funkcjonalne są dobre głównie do dwóch rzeczy: sztucznej inteligencji w grach i obliczeń matematycznych. Jest dobry w grach AI ze względu na przyjemne manipulowanie listami (przynajmniej w Lisp i Scheme) oraz w obliczeniach matematycznych ze względu na składnię. Scheme, Lisp i Haskell mają składnię, która sprawia, że ​​obliczenia matematyczne są łatwe do odczytania. Ostatnią rzeczą, którą muszę dodać, jest to, że języki funkcjonalne to naprawdę zabawne języki. Mój kurs w programie Scheme był jednym z kursów, z których bawiłem się najlepiej.


2
Po tym, jak pogodziłem się z faktem, że mój mózg chciał eksplodować w moim pierwszym tygodniu zajęć kompilatora, które wziąłem w Scheme, również okazało się, że to świetna zabawa (i jestem w tym znacznie lepszy hehe)
Alex Baranosky

1
Jakich języków funkcyjnych używałeś do obliczeń matematycznych?
Jules

8
Również kompilatory! Słyszałem ludzi, którzy pisali kompilatory w Haskell, mówiąc, że „nigdy więcej nie napiszą kompilatora w języku imperatywnym”.
ShreevatsaR

1
julesjacobs: Użyłem trochę zarówno haskell, jak i Scheme, aby rozwiązać proste obliczenia matematyczne. Nie jestem dobry w tych językach, więc mam sposób, aby rozwiązać bardziej złożone problemy. Po prostu nie mogę ich teraz zrobić wystarczająco szybko.
martiert

95

Sam przeprowadziłem kilka badań w tej sprawie i pomyślałem, że mogę dodać CONCURRENCY do listy powodów, dla których warto używać języka funkcjonalnego. Zobacz w pewnym momencie w najbliższej przyszłości prędkość procesora nie będzie mogła wzrosnąć przy użyciu tej samej technologii procesora. Fizyka architektury na to nie pozwala.

I tu właśnie pojawia się współbieżne przetwarzanie.

Niestety większość języków OOP nie może jednocześnie korzystać z wielu procesorów ze względu na współzależności między danymi.

W czysto funkcjonalnych językach programowania komputer może uruchamiać dwie (lub wiele więcej) funkcji jednocześnie, ponieważ funkcje te nie zmieniają zewnętrznych informacji o stanie.

Oto doskonały artykuł na temat programowania funkcjonalnego, który może Ci się spodobać.


38
Nie powiedziałbym, że większość języków OO nie może korzystać z arbitralnie dużej liczby procesorów. Powiedziałbym, że aby program korzystał z wielu procesorów jednocześnie w sposób wydajny i niezawodny, program ten musi być tak zorganizowany, aby większość jednostek kodu wymagających dużej mocy obliczeniowej zachowywała się jak czyste funkcje. W większości języków można w ten sposób zorganizować program. Jest to łatwiejsze do zrobienia w językach funkcjonalnych niż w językach imperatywnych (w tym zorientowanych obiektowo).
Zak

2
Dziękuję za połączenie tego artykułu. Naprawdę pomogło mi to wyjaśnić.
guptron Kwietnia

13

Mój przyjaciel zacytował jednego z jego profesorów z college'u, mówiąc coś takiego:

Narysuj siatkę z typami danych u góry i operacjami na tych typach danych po lewej stronie. Jeśli tniesz siatkę pionowo, robisz OO; jeśli tniesz siatkę poziomo, robisz FP.

Moja odpowiedź jest taka, że ​​FP to całkowicie realne podejście do programowania z tak szerokim zakresem zastosowań, jak OO. Podobnie jak w przypadku każdej dyskusji dotyczącej wyboru języka programowania, myślę, że ważniejsze pytania to:

  1. Czy masz czas, aby zainwestować w naukę nowego zapisu i nowego sposobu myślenia?
  2. Który z rozważanych języków ma wystarczająco bogate biblioteki, aby nie utknąć przy wymyślaniu na nowo jakiegoś koła?

Jeśli chodzi o pierwsze pytanie, jeśli robisz to przede wszystkim ze względu na wartość edukacyjną, sugerowałbym przyjrzenie się Haskellowi , ze względu na szeroki zakres materiałów pomocniczych (książki, artykuły, aktywna społeczność itp.)

Jeśli chodzi o drugie pytanie, Haskell ma niezłą gamę bibliotek (chociaż niektóre są bardziej dojrzałe niż inne), ale Scala (hybrydowy język OO-funkcjonalny działający na JVM) ma zalety polegające na tym, że można bardziej stopniowo przechodzić do stylu funkcjonalnego , i masz dostęp do pełnego zakresu bibliotek dostępnych w języku Java.


Nauczyłem się Scheme na studiach, więc nie chcę uczyć się programowania funkcjonalnego tylko dla doświadczenia. Ze względów praktycznych wolałbym raczej nauczyć się języka funkcjonalnego.
Alex Baranosky

9

Praktycznie wszystko, co możesz zrobić w PP, można zrobić w FP i to samo na odwrót. To po prostu inny sposób kodowania czegoś - inna perspektywa na problem i inny sposób jego rozwiązania.

Jednakże, ponieważ niewiele osób używa FP, problem polega bardziej na braku dobrych bibliotek, przenośności / łatwości utrzymania (ponieważ opiekun ma większą szansę na zrozumienie czegoś napisanego w C ++ niż Scheme) oraz braku dokumentacji i społeczności. Wiem, że jest kilka dokumentów, jednak porównaj je z C ++, C # lub Javą, a zrozumiesz, o co mi chodzi.

Jeśli jednak naprawdę chcesz robić FP, możesz użyć tego stylu nawet w C ++ i C #. Oczywiście nie będzie to 100% FP, jeśli używasz standardowej biblioteki. Niestety, nie sądzę, aby C # był zoptymalizowany do użytku z programowaniem funkcjonalnym i prawdopodobnie spowoduje wiele problemów z wydajnością.

To bardziej subiektywny post, co myślę o FP. Nie jest to rygorystyczna deklaracja.


8
„Praktycznie wszystko, co możesz zrobić w PP, można zrobić w FP” - Właściwie to jest dokładnie wszystko.
BlueRaja - Danny Pflughoeft

2
@BlueRaja - czy masz na myśli kompletność Turinga? Jeśli tak, to, co mówisz, nie następuje. Na przykład gra Conway's Game of Life is Turing Complete, ale nie można jej użyć do napisania sterownika karty graficznej, tak jak w C. Podobnie nie widzę żadnej z najnowszych gier napisanych w Haskell. Can to in FP! = Teoretycznie mógłby to zrobić w teoretycznym FP.
Luigi Plinge

@Luigi Plinge Musiałbym zgodzić się z BlueRaja. Haskellers omawiający niektóre sterowniki Linuksa napisane w Haskell. Nie mam linku, ale słyszałem również, że system operacyjny został napisany w Haskell (możliwe, że inne języki funkcjonalne również). Jeśli chodzi o gry, nie widzę najnowszych gier napisanych w języku C # lub Javie, czy sugerujesz, że nie można ich do tego używać? W każdym razie przykład gry napisanej w FP. Pamiętaj też, że większość moich linków to Haskell, PRAWDZIWY język funkcjonalny.
austinprete

@PardonMyRhetoric Oczywiście możesz pisać gry w Haskell i wykonywać dowolne obliczenia, ale prędkość będzie kilkakrotnie wolniejsza, a zużycie pamięci większe. Zatem kontrprzykładem do stwierdzenia BlueRaja byłoby to, że nie można napisać „gry, która jest tak szybka i zużywa tyle pamięci, ile jest w C” w FP. To prawdziwa praktyczna kwestia, a nie pedantyczna sztuczka (a ja w ogóle nie mam ochoty walić w FP - koduję Scalę!).
Luigi Plinge

1
@PardonMyRhetoric To również musi być idiomatyczne FP. Wzorce, które widzisz, które dają Haskellowi wydajność zbliżoną do C, są napisane w jednostajnym stylu „niskiego poziomu”, którego większość programistów Haskell nie potrafiła napisać. Na przykład możesz osiągnąć podobną wydajność, po prostu tworząc kod wyjściowy Haskella i kompilując kod C. Jednak bezcelowe. Powiązana kwestia praktyczna dotyczy tego, co „można zrobić”, a co „można / można zrobić”. Jeśli coś jest po prostu zbyt trudne, nie ma większego znaczenia, jeśli jest to możliwe w teorii (i „możliwe” dla kogo?).
Luigi Plinge

4

Języki funkcjonalne sprawdzają się w wielu sytuacjach. To zależy od bibliotek konkretnego języka funkcjonalnego.

Jak odpowiedziałbyś na pytanie „Kiedy używać języka programowania obiektowego?”?


1
„Kiedy używać języka programowania zorientowanego obiektowo?” Jeśli chcesz coś wymodelować obliczeniowo, to z drugiej strony szukałem problemu, że fp będzie odpowiedzią intuicyjną, wciąż szukam, tak znalazłem ten post.
jimjim

@Arjang Myślę, że programowanie funkcjonalne znalazłoby ogromne zastosowanie w aplikacjach obliczeniowych, które potrzebują jedynie danych wejściowych do wygenerowania danych wyjściowych. Brak zmienności i iteracji
EdgeDev

3

Chociaż jest to dość subiektywne pytanie, chciałbym tylko dodać, że języki funkcjonalne są często używane do analizowania języków specyficznych dla domeny ; charakter funkcjonalny dobrze nadaje się do analizowania gramatyki.


2
Parsowanie DSL? Myślałem, że w przypadku makr Lispa i tym podobnych, DSL są implementowane jako makra, a nie coś, co ma być analizowane przez programy Lispa. YMMV z językami innymi niż Lisp. :-P
Chris Jester-Young

1

Z tego, co widziałem, jest to bardziej kwestia gustu niż funkcjonalności (gra słów nie jest zamierzona). Tak naprawdę nie ma nic w żadnym stylu języka, który z natury czyni go lepszym lub gorszym w określonych zadaniach.


2
@JonHarrop - Chcesz to rozwinąć? Nie wydaje mi się to takie oczywiste i byłoby szkoda, gdybyś zostawił wrażenie, że głosujesz na ludzi z meer boosterisim.
TED

1
Rodzina języków ML została specjalnie wyhodowana do metaprogramowania z dodatkiem zaawansowanych funkcji językowych, takich jak dopasowywanie wzorców do manipulowania drzewami (np. Drzewami wyrażeń). W konsekwencji ta rodzina języków jest z natury dużo lepsza w tym konkretnym zadaniu.
JD

1
@JonHarrop - zaakceptuję to. Jednak mówisz o ML, a nie ogólnie o językach funkcjonalnych. Jestem wielkim zwolennikiem DSL, więc z pewnością nie będę się spierał przeciwko używaniu konkretnego języka do konkretnego zadania, do którego został zaprojektowany.
TED

Obecnie dopasowanie wzorców można znaleźć w prawie wszystkich językach funkcjonalnych, w tym w OCaml, F #, Scala, Haskell, Clojure i Erlang. Na przykład niedawno stworzyłem specjalnie zaprojektowany silnik reguł biznesowych dla klienta ze szczególnym uwzględnieniem matematyki. To jest 1000 wierszy języka F # i jest głównie tłumaczem. Lexing, parsowanie, sprawdzanie typów i interpretacja danych wejściowych są znacznie łatwiejsze dzięki dopasowaniu wzorców.
JD

@JonHarrop .. ale nie wszystko. Nie jest to nieodłączna cecha języków funkcjonalnych, o co pytano.
TED,

1

Ogólnie rzecz biorąc, używaj języka, w którym najłatwiej jest opisać rozwiązanie problemu. W przypadku programowania funkcjonalnego jest to sytuacja, w której rozwiązanie problemu można łatwo wyrazić za pomocą funkcji , stąd nazwa. Ogólnie jest dobry do operacji matematycznych, sztucznej inteligencji, dopasowywania wzorców; ogólnie wszystko, co można podzielić na zestaw reguł, które należy zastosować, aby uzyskać odpowiedź. Dopiero po dostatecznym przeanalizowaniu problemu można naprawdę określić „najlepszy” język. Tutaj z pomocą przychodzi pseudokod. Jeśli zauważysz, że piszesz pseudokod, który wygląda jak FP, użyj FP.

Oczywiście wszystkie kompletne języki programowania są funkcjonalnie równoważne, więc tak naprawdę nie ma znaczenia, który wybierzesz pod względem problemów, które możesz rozwiązać. Główne efekty będą dotyczyły wydajności i dokładności kodowania oraz łatwości konserwacji.

Zauważ również, że możliwe jest naśladowanie FP w językach OO poprzez sprytnie zaprojektowane API. Na przykład, widziałem wiele bibliotek Java (jednym z przykładów jest JMock), które używają łańcuchów metod do symulacji FP DSL. Następnie zobaczysz konstrukcje, takie jak:

logger.expects(once()).method("error") .with( and(stringContains(action),stringContains(cause)) );

To zasadniczo tworzy funkcję, która jest oceniana w celu określenia, czy jakaś sekwencja wywoływania na obiekcie pozorowanym jest poprawna. (przykład skradziony z http://www.jmock.org/yoga.html )

Inną składnią podobną do FP w innych językach OO jest użycie domknięć, na przykład w Rubim.


2
„... tak naprawdę nie ma znaczenia, który z nich wybierzesz pod względem problemów, które możesz rozwiązać”. Tylko jeśli masz nieskończoną ilość czasu i pieniędzy, aby rozwiązać swój problem.
JD
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.