Czy programowanie funkcjonalne jest po prostu inne , czy też jest naprawdę trudniejsze ?
Powiedz kogoś, kto nigdy wcześniej nie nauczył się programowania i jest nauczony programowania funkcjonalnego. kontra ktoś, kto nigdy wcześniej nie nauczył się programowania i uczy się programowania imperatywnego. co będzie trudniejsze? czy to samo?
Moje pytanie: powiedzmy, że teraz problemem jest wejście do wielbłąda,
taki, który qwe_asd_zxc_rty_fgh_vbn
staje sięqweAsdZxcRtyFghVbn
Procedura polega na:
- podzielić to wzdłuż
_
- zapętlaj tablicę, pomijając pierwszy element
- do każdego wpisu dodajemy wielką literę
- połącz wyniki razem
Funkcjonalny sposób to:
- jeśli nie można znaleźć
_
zwrotuinput
- przeciąć pierwszy
input
wzdłuż_
(tak, że dostajemyqwe
iasd_zxc_rty_gfh_cvb
) - wielką literą pierwszą literę
head
i konkatuj to zf(tail)
Ok, jeśli masz zaplecze funkcjonalne ORAZ posiadasz duże doświadczenie w programowaniu procedur, chciałbym zapytać: czy zajmie ci to więcej czasu, aby dowiedzieć się, jak to zrobić, czy też zajmie ci więcej czasu, aby dowiedzieć się, jak to zrobić?
Jeśli posiadasz doświadczenie proceduralne, ale masz wieloletnie doświadczenie w programowaniu funkcjonalnym, chciałbym zadać to samo pytanie: czy zajmie Ci to więcej czasu na opracowanie procedury, czy też zajmie Ci więcej czasu na zrozumienie działania droga?
map
kroku 3 zamiast pętli mutacyjnej. Drugie podejście rozważam tylko wtedy, gdy w standardowej bibliotece nie ma funkcji podziału (w takim przypadku należy ją porównać do rozwiązania imperatywnego, które również nie korzystasplit
).x=x+1
może wysadzić nieoczekiwany mózg. Programowanie funkcjonalne jest naturalne, nie jest niczym więcej niż czystymi i wygodnymi funkcjami ściśle matematycznymi.Odpowiedzi:
Po prostu inny. Programowanie funkcjonalne jest znacznie ściślej związane z matematyką, którą zna większość ludzi. Cała ta „niezmienna zmienna” jest szokiem dla programistów-imperatywów, w których „zmienne” nastawienie jest głęboko zakorzenione.
Dla początkujących jest często dość intuicyjne, że nie można po prostu zmienić wartości czegoś.
Tam, gdzie studiowałem CS, uczyliśmy się języka funkcjonalnego jako naszego pierwszego kursu. I wszyscy, którzy wcześniej nauczyli się C ++ lub Java, mieli z tym problem. Ci, którzy byli nowicjuszami w programowaniu, dość łatwo to zauważyli.
źródło
Po prostu jest inaczej
Kiedy programujesz, zasadniczo tłumaczysz sposób rozumowania na kod, odległość między twoimi myślami a ostatecznym rozwiązaniem można by nazwać „luką poznawczą”. Im większa szczelina, tym trudniej będzie ją pokonać.
Jeśli pochodzisz z przeszłości proceduralnej, nauczysz się myśleć proceduralnie, więc różnica będzie mniejsza niż w przypadku kodu funkcjonalnego i odwrotnie.
Jedynym sposobem, aby paradygmat programowania był wewnętrznie łatwiejszy niż cokolwiek innego, byłoby zmapowanie go do czegoś, co już znasz, na przykład zwykłego języka, aby zacząć od krótszej luki.
W każdym razie funkcjonalna i proceduralna koncepcja jest dość płynna i często się pokrywają
źródło
Tak, programowanie funkcjonalne może być trudne do zrozumienia dla wielu osób (powiedziałbym, zwłaszcza tym, którzy już wcześniej byli narażeni na programowanie proceduralne).
Powiedziałbym również, że twój przykład programowania funkcjonalnego nie jest naprawdę dobrym przykładem programowania funkcjonalnego. Wykorzystuje rekurencję i po prostu komponuje wynik zamiast modyfikować stan, ale niewiele więcej.
Aby uzyskać lepszy przykład programowania funkcjonalnego, rozważ bardziej ogólny problem: zamiast „szukać podkreślenia i przekonwertować następną literę na wielkie litery”, rozważ to jako jeden szczególny przypadek wyszukiwania wzorca i wykonania dowolnego kodu, gdy zostało znalezione.
Wiele języków obsługuje to, ale aby to zrobić, musimy określić wzorzec jako coś w rodzaju wyrażenia regularnego. Wyrażenia regularne nie są jednak niczym więcej niż językiem programowania specjalnego przeznaczenia, a implementacja RE jest kompilatorem i / lub tłumaczem dla tego języka. Rezultatem kompilacji RE jest w zasadzie funkcja, która wykonuje się (na specjalnej maszynie wirtualnej RE), aby dopasować wyrażenie do niektórych danych wejściowych.
W czymś takim, jak Perl, używasz specjalnego języka do określenia wzorca, specjalnego kompilatora do konwersji tego ciągu na coś w rodzaju funkcji, a także specjalnego interpretera, który bierze tę funkcję do wykonania. W języku funkcjonalnym zwykle używasz samego języka, aby określić wzorzec, a własnego kompilatora używa się do wygenerowania prawdziwej funkcji. Możemy wygenerować tę funkcję w locie (mniej więcej tak, jak możemy skompilować RE, kiedy chcemy), ale kiedy to zrobimy, wynik może być wykonany jak każda inna funkcja w języku zamiast potrzebować specjalnych rzeczy RE w tym celu.
Rezultatem jest to, że można generalizować problemu powyżej stosunkowo łatwo. Zamiast na stałe wpisywać „_” i „wielkie litery” bezpośrednio w transformacji, możemy jednak mieć coś takiego:
Ale w przeciwieństwie do czegoś, w którym określamy wzorzec jako RE, możemy określić wzorzec bezpośrednio jako rzeczywistą funkcję i nadal go używać, coś w stylu:
A następnie przekazujemy tę funkcję s & r. W tej chwili jest to dość trywialna funkcja i zakodowaliśmy ją całkowicie statycznie. Język funkcjonalny w dużej mierze staje się interesujący, gdy używamy go tak, jak możemy REs i generujemy całkowicie nową funkcję w locie na podstawie czegoś takiego jak dane wejściowe użytkownika, ale w przeciwieństwie do RE, ta funkcja nie potrzebuje specjalnego interpretera RE - to jest po prostu normalna funkcja jak każda inna.
źródło
Oto pełny kod w Racket :
Jako funkcjonalny programista z doświadczeniem proceduralnym nie sądzę, że zajęłoby mi więcej czasu, aby „wymyślić” rozwiązanie proceduralne, ale z pewnością zajęłoby mi więcej czasu, aby je wpisać.
BTW, przykładowy oczekiwany wynik w oryginalnym poście jest niepoprawny: brakuje mu litery „h” pod koniec.
źródło
Moja teoria zwierząt domowych polega na tym, że modele programowania są łatwiejsze do zrozumienia, im bliżej są faktycznej pracy komputerów. Wskaźniki są trudne do zrozumienia, dopóki nie uświadomisz sobie, że są to zasadniczo adresy maszynowe. Trudno jest zrozumieć rekurencję, dopóki świadomie nie przejdziesz małego przykładu, nie zobaczysz ramek stosu i nie zauważysz, gdzie przechowywane są różne wartości tej samej zmiennej. Nie oznacza to, że programowanie asemblera jest łatwiejsze niż programowanie na wysokim poziomie, ale widzenie, jak to się robi, czyni cuda dla modelu mentalnego, który jest kluczem do biegłości - czy to w programowaniu, czy w ogólnej użyteczności.
Teraz model proceduralny jest nieco bliższy zwykłej architekturze maszyny: przypisania są zapisywane w pamięci (lub rejestrze). Wywołania procedur są tak naprawdę tylko fantazyjnymi skokami, w
if
rzeczywistości są skokami warunkowymi itp. Ale w Lisp, na przykład, nie ma prostego niskiego poziomu odpowiednika wiązania leksykalnego lub wyrażenia lambda. Zrozumienie tego wymaga wyobrażenia sobie zupełnie odrębnej abstrakcyjnej maszyny funkcjonalnej między poziomem języka a maszyną fizyczną, ponieważ i najwyraźniej większość ludzi nigdy nie dociera tak daleko.(Ja jestem zaznajomiony z ideą, że architektura von Neumanna jest ostatecznie arbitralne, a my nie powinniśmy umysły początkujących uchybia z taką nieistotnych szczegółów architektury maszyny, a zamiast bezpośrednio wprowadzić je do semantyki języków programowania. W rzeczywistości, mam sam prowadziłem kilka takich kursów. Ale coraz bardziej czuję, że jest to szlachetny, ale mylony cel; ludzie uczą się programowania, budując zrozumienie od podstaw, a droga do programowania funkcjonalnego jest po prostu nieco dłuższa.)
źródło
011011001001101...
byłyby najłatwiejszym językiem do nauki!