JavaScript jest funkcjonalnym językiem programowania

34
  • Czy JavaScript jest językiem funkcjonalnym? Wiem, że ma obiekty i można z nim również korzystać z OOP, ale czy jest to również język funkcjonalny, czy można go używać w ten sposób?
  • Wiesz, w jaki sposób OOP stał się / wydaje się następną ewolucją w programowaniu, czy to oznacza, że ​​„Funkcjonalne programowanie” jest kolejną ewolucją (Uwaga: to NIE jest monit o opinię, ale monit o odpowiedź opartą na faktach, a ta notatka jest więcej dla moderatorów niż współpracowników;)).
  • Uczę się najlepiej na przykładach, może ktoś może pokazać wykonywanie tego samego zadania w sposób OOP, a następnie w sposób programowania funkcjonalnego, aby zrozumieć i porównać działanie programowania funkcjonalnego.

Szczerze mówiąc, nie do końca rozumiem „programowanie funkcjonalne”: P Porównywanie Javascript do programowania funkcjonalnego może być całkowicie niepoprawne.

Mówiąc prościej, programowanie funkcjonalne: czy jest to po prostu korzyść z abstracji ZA POMOCĄ korzystania z anonimowych funkcji?

A może to zbyt proste? W prosty sposób OOP jest zaletą abstrakcji poprzez obiekty, ale uważam, że jest to zbyt uproszczone, aby opisywać OOP.

Czy to dobry przykład programowania funkcjonalnego? ...

Przykład JavaScript OOP:

// sum some numbers
function Number( v )
{ 
  this.val = v;
}

Number.prototype.add( /*Number*/ n2 )
{
    this.val += n2.val;
}

Przykład programowania funkcjonalnego:

function forEach(array, action) 
{
   for (var i = 0; i < array.length; i++)
       action(array[i]);
}  

function add(array)
{
    var i=0;
    forEach(array, function(n)
    {
        i += n;
    });
    return i;
}

var res = add([1,9]);
Marek
źródło
Zależy to od definicji „funkcjonalnego języka programowania”. W szerokim sensie można to rozumieć jako zdolność do budowania wartości funkcjonalnych z wartościami zamkniętymi, tj. Jako konstrukt „lambda” (w sensie rachunku lambda), a następnie Javascript pasuje do rachunku.
Basile Starynkevitch,
2
Or is that way too simple?Tak jest. Anonimowe funkcje są czasem kojarzone z językami funkcjonalnymi i językami wieloparadygmatowymi, które sprzyjają programowaniu funkcjonalnemu, ale nie są unikalną cechą języków funkcjonalnych. Ale jeśli postrzegasz je jako implementację rachunku λ, to są one podstawową częścią programowania funkcjonalnego, a główną kwestią jest to, że nie jest to takie proste :)
yannis
Konstrukcja JavaScript uniemożliwia implementacjom przeprowadzanie optymalizacji wywołania ogona. W moich książkach samo to zapobiega oznaczeniu go jako funkcjonalnego.
dan_waterworth
I know it has objects & you can do OOP with it alsoNie możesz Jest to programowanie prototypowe, które eliminuje rozróżnienie między klasą a obiektem. Osobiście uważam, że programowanie prototypowe jest wadliwe na tym podstawowym poziomie.
RokL
JavaScript nie jest językiem funkcjonalnym, na pewno ma cechy funkcjonalne, ale ma też dobre dobre imperatywne C, w rzeczywistości każdy język ma podstawowe cechy funkcjonalne. Czysty język funkcjonalny, taki jak Haskell, ML itp., Jest językiem deklaratywnym, a nie imperatywnym.
ALXGTV

Odpowiedzi:

72

Czy JavaScript jest językiem funkcjonalnym? Wiem, że ma obiekty i można z nim również korzystać z OOP, ale czy jest to również język funkcjonalny, czy można go używać w ten sposób?

Czasami ludzie powiedzą programowanie funkcjonalne, gdy mają na myśli programowanie imperatywne lub programowanie proceduralne . Ściśle mówiąc, programowanie funkcjonalne to:

W informatyce programowanie funkcjonalne jest paradygmatem programowania, który traktuje obliczenia jako ocenę funkcji matematycznych i unika stanu i zmiennych danych . Podkreśla zastosowanie funkcji, w przeciwieństwie do imperatywnego stylu programowania, który podkreśla zmiany stanu. Programowanie funkcjonalne ma swoje korzenie w rachunku lambda, formalnym systemie opracowanym w latach 30. XX wieku w celu zbadania definicji funkcji, zastosowania funkcji i rekurencji. Wiele funkcjonalnych języków programowania można traktować jako rozwinięcia rachunku lambda.

Chociaż Javascript nie jest powszechnie znany ani używany jako język funkcjonalny, zawiera on pewne elementy funkcjonalne :

JavaScript ma wiele wspólnego ze Scheme. To jest dynamiczny język. Ma elastyczny typ danych (tablice), który może łatwo symulować wyrażenia s. A co najważniejsze, funkcjami są lambdas.

Schemat jest dialektem Lispa i prawdopodobnie jednym z języków, o których myśli większość programistów, omawiając programowanie funkcjonalne. Jeśli chodzi o orientację obiektową , JavaScript jest językiem zorientowanym obiektowo. Ale jego orientacja obiektowa opiera się na prototypach :

Programowanie prototypowe to styl programowania obiektowego, w którym klasy nie są obecne, a ponowne użycie zachowania (znane jako dziedziczenie w językach opartych na klasach) odbywa się poprzez proces klonowania istniejących obiektów, które służą jako prototypy. Ten model może być również znany jako programowanie bezklasowe, prototypowe lub oparte na instancjach. Delegowanie to funkcja języka obsługująca programowanie prototypowe.

Więc chociaż JavaScript jest zorientowany obiektowo, nie jest zgodny z bardziej powszechnym modelem opartym na klasach , podobnie jak języki takie jak C ++, C #, Java i PHP (i kilka innych). I oczywiście jest to także język imperatywny, co prowadzi do pomylenia z funkcjonalnym programowaniem, które opisałem powyżej.

Wiesz, jak OOP stał się / wydaje się następną ewolucją w programowaniu, czy to oznacza, że ​​„Funkcjonalne programowanie” to kolejna ewolucja

Orientacja obiektowa i programowanie funkcjonalne to tylko dwa z wielu różnych paradygmatów programowania , są to różne style programowania z różnymi koncepcjami i abstrakcjami. Kluczowym słowem jest „inny”. Nie ma jednego paradygmatu, który byłby lepszy od innych lub bardziej rozwinięty niż inne, każdy z nich pasuje do niektórych scenariuszy lepiej niż inne. Niektóre mogą być nieco starsze niż inne, ale pod względem ewolucyjnym czyni je lepszymi, ponieważ przetrwały dłużej. Ale to nie jest zbyt mądry sposób patrzenia na to.

JavaScript, jak opisałem powyżej i jako kilka innych języków, jest wieloparadygmatyczny. Umożliwia pisanie kodu w imperatywnym, obiektowym i funkcjonalnym stylu opartym na prototypach. Od Ciebie zależy, który najlepiej pasuje do tego, co budujesz. Istnieje również kilka pojedynczych języków paradygmatu, kanonicznym przykładem jest Java, która pozwala tylko na programowanie obiektowe zorientowane klasowo 1 .

Naprawdę powinieneś oprzeć się wszelkiej potrzebie traktowania języków i paradygmatów jako oświadczeń o modzie. Jest tam mnóstwo bzdur, napisanych głównie przez fanów / fanów lub marketingowców, z niewielką (jeśli w ogóle) wiedzą i zrozumieniem programowania. Terminy takie jak „lepszy”, „bardziej rozwinięty” itp. Po prostu nie mają zastosowania.

Uczę się najlepiej na przykładach, może ktoś może pokazać wykonywanie tego samego zadania w sposób OOP, a następnie w sposób programowania funkcjonalnego, aby zrozumieć i porównać działanie programowania funkcjonalnego.

To byłby okropny sposób na naukę. Orientacja funkcjonalna i obiektowa to całkiem różne style, a żaden inny przykład, niż strasznie prosty, nie pasowałby do jednego lub drugiego stylu.

1 Ale ostatnio próbuje rozszerzyć swój zakres na programowanie ogólne, zobaczmy, jak to pójdzie.


Podsumowując:

  • Skoncentruj się na nauce Javascript, to piękny i niezwykle użyteczny język. Naucz się języka, a nie szumu.
  • Całkiem kilka różnych paradygmatów, wszystkie równie przydatne. Od Ciebie zależy, który wybierzesz, a który najlepiej pasuje do tego, co budujesz.
  • Jeśli chcesz nauczyć się programowania funkcjonalnego, wybierz bardziej odpowiedni język, na przykład Scheme lub Clojure . Ale najpierw musisz zrozumieć związane z nimi pojęcia matematyczne.
  • Przeprowadź badania, zanim zapytasz. Odpowiedzi na większość pytań znajdują się w odpowiednich artykułach w Wikipedii. Umiejętność prowadzenia badań i zadawania pytań jest niezwykle ważną umiejętnością dla każdego programisty.
Yannis
źródło
5
+1 Świetna odpowiedź. Ze względu na strukturę edukacji programistycznej wydaje się, że nowi koderzy uważają paradygmaty za wyjątkowe i dyskretne, ale tak nie jest. Spróbuj napisać kod OOP, który wykorzystuje funkcjonalne koncepcje, gdy ma to sens. Programowanie oparte na zdarzeniach jest paradygmatem, ale aspekty EDP mają wpływ na każdy GUI i program internetowy. Polimorfizm , podstawowa cecha OOP, to naprawdę ogólne programowanie. Nazewnictwo tych pomysłów pomaga nam konceptualizować dobre programowanie, ale nie powinieneś używać jednego z wyłączeniem innych.
kojiro
Chociaż oryginalne pytanie i twoja odpowiedź opisują Javascript i jego związek z programowaniem funkcjonalnym, myślę, że twoja odpowiedź jest jednym z lepszych porównań między OO i programowaniem funkcjonalnym, jakie widziałem. Dobra robota.
AnotherDeveloper
„To byłby okropny sposób nauki”. Właśnie skończyłem czytać tę książkę, która przedstawia problem i rozwiązałem ją za pomocą szeregu paradygmatów, w tym stylów OOP i FP: github.com/crista/exercises-in-programming-style . Wiele się z tego nauczyłem!
Nick
@nick To może tylko opisać ci, jak wygląda paradygmat i jak działa, ale nie mówi ci dlaczego , co jest prawdopodobnie najważniejszym aspektem. Ale musisz nauczyć się, jak zanim dowiesz się dlaczego :) czasami zapominamy, że te rzeczy są procesem.
Matthew Brent
8

JavaScript może być używany jako język funkcjonalny, w rzeczywistości robi to całkiem dobrze. Możliwe jest zaimplementowanie monad z obsługą konstrukcji lambda itp. Nie jest to wyłącznie język funkcjonalny, ponieważ ma również wiele cech obiektowych, ale można go w ten sposób wykorzystać. Właściwie uważam, że używanie Javascript jako języka funkcjonalnego to świetny sposób na jego użycie. (Przykład jQuery i underscore.js)

Zachary K.
źródło
dobre i zwięzłe! Zgodzono się, że programowanie funkcjonalne jest często najłatwiejszym sposobem na zrobienie czegoś w js.
bunglestink
Jeszcze bardziej interesujące niż monady, możesz zaimplementować strzałki to JS ( cs.umd.edu/projects/PL/arrowlets ). Pytanie , dlaczego ktokolwiek chciałby mieć strzałki w JavaScript, jest pytaniem otwartym. Ale można to zrobić.
rtperson
Przyznaję, że nie rozumiem wystarczająco dużo na temat strzał, aby wiedzieć, czy będą one przydatne. Ale pracuję nad książką o monadach w Javascripcie i mogę dodać rozdział o Arrowsach ( shop.oreilly.com/product/0636920023890.do )
Zachary K
6

Ewolucja zwykle oznacza stopniową zmianę. OOP nie jest przyrostowym dodatkiem do programowania proceduralnego - w rzeczywistości jest całkowicie ortogonalny w stosunku do podstawowego modelu programowania i może być łączony z dowolnym z nich. Programowanie funkcjonalne nie jest przyrostowym dodatkiem do procedur, OOP itp. - jest alternatywną podstawą do wyrażenia podstawowych zasad obliczeniowych i jest tak naprawdę pierwszą taką podstawą sformułowaną na długo przed pojawieniem się pierwszych komputerów. Ważne jest, aby zrozumieć, że wszystkie takie podstawowe systemy są równoważne (tzn. Jeden można wyrazić w kategoriach innego).

Aby zrozumieć funkcjonalne podejście, musisz najpierw zdobyć podstawową matematykę . Jeśli chcesz poczuć, co to znaczy kodować w funkcjonalnym stylu w Javascript, zacznij używać jQuery .

Logika SK
źródło
2

Nie.

JavaScript jest przede wszystkim językiem obiektowym.

Nie oznacza to, że nie możesz pisać programów JavaScript w funkcjonalnym stylu, ponieważ możesz zaadaptować funkcjonalny styl w dowolnym języku Turinga, jeśli spróbujesz wystarczająco mocno. Jeśli chcesz, możesz programować funkcjonalnie w asemblerze. Ale to nie sprawia, że ​​każdy język działa. Równie dobrze możesz nazwać imperatyw Haskella, lub Javę logicznym językiem programowania - jeśli zastosujesz takie podejście, warunki wkrótce staną się bez znaczenia.

IMO sposobem na zaklasyfikowanie języka do odpowiedniego paradygmatu jest rozważenie:

  • Jaki jest dominujący styl umożliwiany przez konstrukcje językowe (wyraźnie OOP dla JavaScript, języki funkcjonalne zamiast tego podkreślają funkcje i niezmienne wartości danych)
  • Jaki paradygmat jest obsługiwany w podstawowych bibliotekach języka (ponownie wyraźnie OOP dla JavaScript)
  • Jakie funkcje są wyłączone lub zniechęcone w języku (języki funkcjonalne zniechęcają lub zabraniają zmiennych zmiennych, co nie ma miejsca w JavaScript)
  • Jaki styl programowania jest powszechny w społeczności programistów używających języka (ponownie, OOP jest wyraźnie rozpowszechniony w świecie JavaScript)

Osobiście uważam za dość zabawne, że wiele osób lubi twierdzić, że język jest „funkcjonalny” tylko dlatego, że jest to obecnie modny termin :-)

Jeśli chcesz mieć nieco długą, ale zabawną perspektywę programowania paradygmatów na przestrzeni lat, warto obejrzeć wideo wujka Boba Martina „The Last Programming Language” . Dla mnie świetnym spostrzeżeniem z tej rozmowy było to, że paradygmaty programowania są definiowane przez to, jakie funkcje zabierają , a nie jakie wprowadzają ......

mikera
źródło
What is the dominant style enabled by the language constructsWyzywam cię, byś spróbował zastosować to do Perla ... Albo jakikolwiek inny z twoich punktów, naprawdę :)
yannis
2
Perl? Dobre wyzwanie! Jest to trochę jak język asemblerowy, w tym sensie, że możesz zhakować praktycznie dowolny paradygmat, który chcesz razem, ale we wspólnym zastosowaniu, które widziałem (skrypty), jest używany głównie jako język imperatywny / proceduralny.
mikera
Cóż, oop jest również dość powszechny. Oczywiście w zgubny sposób. I również funkcjonalne , choć rzadkie. perl jest po prostu perl, nie ma sensu próbować nadawać mu sensu :)
yannis
JavaScript jest nieco bardziej funkcjonalny niż Java, ponieważ ma przynajmniej zamknięcia i funkcje pierwszej klasy. Ale masz rację, JavaScript jest tak samo funkcjonalny jak C #.
Raynos
2

JavaScript jest najpierw prototypowy, z funkcjami funkcjonalnymi - przyznawanymi przez wykorzystanie funkcji jako obiektów pierwszej klasy.

Oznacza to, że możesz używać funkcji jako danych, co ma dziwny efekt, ponieważ zmniejsza zapotrzebowanie na zmienne utrzymujące stan. Jeśli zauważysz, że sięgasz po instrukcję var lub korzystasz z jednej lub więcej instrukcji „if”, to zbłądzisz ze stylu funkcjonalnego.

Inną godną uwagi cechą stylu funkcjonalnego jest to, że funkcje powinny WYŁĄCZNIE zwracać wynik ich oceny i nie powinny mieć żadnych skutków ubocznych dla stanu poza ich zakresem:

// oops, this is producing a side effect
function sideEffecter(){//theres no input...        
    window.thingy = 'foo';
    // hey, this isn't returning anything!!!
} 

Języki funkcjonalne są nieniszczące - co oznacza, że ​​nie mutują danych wejściowych, ale zwracają całkowicie nowe dane na podstawie danych wejściowych. Zobacz ten wątek: https://stackoverflow.com/questions/749084/jquery-map-vs-each

Języki funkcjonalne mają również wiele wspólnych metod - o nazwach takich jak „mapa”, „fold”, „zmniejsz” przetwarzających listy / kolekcje. W JS, w przeciwieństwie do innych języków, musimy ręcznie je uporządkować, aby zobaczyć przykłady - zobacz biblioteki takie jak underscore.js , chociaż najnowsza implementacja JS ma kilka z nich od razu po wyjęciu z pudełka.

Ważną rzeczą do zapamiętania (IMO) jest to, że chociaż JS może wykorzystywać pewne wzorce funkcjonalne, nie zawsze jest on odpowiednio przygotowany do wykonania.

Weźmy na przykład iterację po tablicy. Możesz to zrobić za pomocą stylu funkcjonalnego lub rodzimej konstrukcji pętli - i ogólnie mówiąc, pętla jest bardziej wydajna. Weź ten przykład - uderz go w pętle o coraz większym rozmiarze i zapisz czasy wykonania w różnych przeglądarkach (już to zrobiłem, ale straciłem testy - przepraszam!):

var test = ['foo', 'bar', 'baz'], removeFunc, removeLoop;

//(semi)functional style...
// to be really functional each condition in the ternary would be another function
removeFunc = function(src, trg) {
    return src.length === 0 ? 
        src : 
            src[0] === trg ? 
                src.slice(1) : 
                    [src[0]].concat(removeFunc(src.slice(1), trg));
};

//but this is faster
removeLoop = function(src, trg){
    var len = src.length, // using variables to represent state...
        i=0, 
        result = [];        
    while(i < n){
       if(src[i] !== trg){
          result.push(src[i]);
       }
       i = i+1;
    }
}

Ponadto, jeśli używasz funkcjonalnej konstrukcji do uderzania w pętle o znacznych rozmiarach i nie korzystasz z jakiejś formy zarządzania stosami ad-hoc, możesz zalać stos (chociaż, żeby być uczciwym, potrzebujesz DUŻEJ listy, aby do tego doszło. ..). Musisz również uwzględnić różne warianty optymalizacji w każdej przeglądarce - chociaż jeśli pracujesz w środowisku Node.js, jest to oczywiście bardziej stały cel.

Nie oznacza to, że nie powinieneś używać funkcjonalnych konstrukcji w JavaScript - po prostu miej świadomość ograniczeń w implementacji w stosunku do środowiska.

Oto kilka linków, które mogą Cię zainteresować:

Dobry rozdział na temat programowania funkcjonalnego w JavaScript ze wspaniałego „Eloquent Javascript”

Mały Schemer

mój przyjaciel napisał bibliotekę JS opartą na Little Schemer

Dobry samouczek na temat Schematu, który może pomóc lepiej zrozumieć FP

sunwukung
źródło