Czy JavaScript jest funkcjonalnym językiem programowania?

135

Tylko dlatego, że funkcje są obiektami pierwszej klasy, istnieją domknięcia i funkcje wyższego rzędu, czy Javascript zasługuje na miano języka programowania funkcjonalnego? Główną rzeczą, której moim zdaniem brakuje, są Pure Functions i nie `` czuje się '' jak inne języki funkcjonalne, takie jak seplenienie (chociaż to nie jest wystarczający powód, aby nie być funkcjonalnym językiem ...)

hvgotcodes
źródło
12
@slashmais: Nie! To tylko zapobiega temu, by był językiem czysto (ledwie) funkcjonalnym. ML (przynajmniej współczesne dialekty) też są nieczyste - ale nikt nie odważyłby się nazwać ich niefunkcjonalnymi;)
4
Istnieje wiele języków, które są powszechnie uważane za funkcjonalne, ale które nie są czyste. Nie rozumiem, jak to jest wymagane. Jeśli chcesz być tak surowy, to większość tak zwanych języków OOP również nie jest OOP. W rezultacie około 95% wszystkich języków nie jest językami paradygmatycznymi.
jalf
6
Dlaczego to ma znaczenie? Kiedy koduję w C ++, nie obchodzi mnie, czy język jest „OOP”, czy nie. Zależy mi na tym, że ma pewne funkcje OOP i że ma kilka funkcjonalnych funkcji programowania i wiele koniecznych funkcji programowania oraz wiele ogólnych funkcji programowania. Ale czy to „jest” język OOP, język FP, czy coś innego, nie ma znaczenia. Podobnie, kiedy koduję w JS, nie ma znaczenia, czy jest to FP, czy nie. Liczy się to, że obsługuje wiele fajnych funkcji FP. Wydaje się, że to niewłaściwe pytanie.
jalf
3
@hvgotcodes: tak? Nie ma absolutnie żadnej reguły mówiącej, że tak nie jest. Moja zasada jest taka, że ​​jest to język funkcjonalny, jeśli można go używać do programowania w stylu funkcjonalnym. Ponieważ JavaScript ma pierwszorzędne funkcje, zamknięcia i lambdy, uważam, że możesz, i jeśli o mnie chodzi, jest to język funkcjonalny. Oczywiście nie jest to czysty język, ale też większość języków, które zwykle uważamy za FP (na przykład SML). Więc naprawdę myślę, że po prostu musisz się rozluźnić. Jeśli to powoduje drganie oka, musisz udać się do lekarza.
jalf
3
@jalf, absolutnie. Motywacją do pytania było to, że chciałem wiedzieć, co myślą moi rówieśnicy i ludzie mądrzejsi ode mnie.
hvgotcodes

Odpowiedzi:

180

Powtarzając własną odpowiedź na podobne pytanie,

Nie ma przyjętej definicji funkcjonalnego języka programowania.

Jeśli zdefiniujesz język funkcyjny jako język obsługujący funkcje pierwszej klasy i wyrażenia lambda, to tak, JavaScript * jest * językiem funkcjonalnym.

Jeśli weźmiesz również pod uwagę takie czynniki, jak obsługa niezmienności, algebraiczne typy danych, dopasowywanie wzorców, częściowe zastosowanie itp., To nie, JavaScript * nie jest * językiem funkcjonalnym.


Zachęcam do przeczytania następujących powiązanych postów na blogu (a także komentarzy pod nimi):

missingfaktor
źródło
29
+1 za wskazanie, że nie ma uniwersalnej definicji i przedstawienie przykładów archetypowych funkcji języka funkcjonalnego, których JS nie posiada.
1
Późniejsze wersje implementacji JavaScript w Mozilli (zaczynające się od wersji 1.7) mają dopasowywanie wzorców w postaci przypisań destrukturyzujących: developer.mozilla.org/en/New_in_JavaScript_1.7#section_20
jbeard4
JavaScript ma pojęcie podszablonów i częściowo stosuje parametry, więc zastanawiam się, czy twoje stwierdzenie, że tego nie obsługuje, jest błędne?
johnbakers
2
@OpenLearner, częściowo aplikacja jest obsługiwana przez prawie każdy język, jaki przychodzi mi do głowy, nawet C. W każdym razie dla pewnej definicji „wsparcia”. Nie inaczej jest w przypadku JS. Chodzi o to, czy częściowa aplikacja jest łatwa i pierwsza klasa w tym języku. W JS tak nie jest. Jeśli jesteś ciekawy, co mam na myśli, spójrz na OCaml lub Haskell.
missingfaktor
JavaScript obsługuje niezmienność afaik.
fka
26

Powiedziałbym, że jest to język wieloparadygmatyczny.

EDYCJA: To wieloparadygmat i zawiera konstrukcje funkcjonalne.

Niki Yoshiuchi
źródło
tak, zgadzam się, że to mieszanka i kilka różnych rzeczy.
Ashley Grenon
5
ale to nie odpowiada na pytanie, czy jest również funkcjonalne. Bycie wieloparadygmatem oznacza wspieranie wielu paradygmatów. Czy jeden z tych paradygmatów jest programowaniem funkcjonalnym?
jalf
15

jeśli rozciągniesz i przekręcisz termin „programowanie funkcjonalne” do poziomu dyskusji filozoficznych, to pytanie może być ponownie otwarte. Jednak kończy się to na poziomie przydatnych pytań, takich jak „Czy C ++ jest naprawdę językiem programowania”?

Odpowiedź na twoje pytanie na bardziej codziennym poziomie brzmi „nie” .

Programowanie funkcjonalne oznacza, że ​​program jest konceptualizowany jako ocena funkcji, a nie przepływ sterowania. Kod jest opisem funkcji i nie ma nieodłącznej koncepcji przepływu sterowania.

JavaScript ma przepływ kontroli i jest konceptualizowany jako język imperatywny. Z punktu widzenia projektu nie jest to język funkcjonalny.

shuhalo
źródło
1
cel projektowy? Co masz na myśli? Kiedy ostatnio sprawdzałem, jednym z jego źródeł inspiracji był Scheme. Powiedziałbym, że jest całkiem jasne, że jednym z jego celów projektowych było wsparcie programowania funkcjonalnego, a także wielu innych paradygmatów
jalf
2
Obsługuje programowanie funkcjonalne tak samo jak C ++, jeśli sam napiszesz odpowiednie podstawy - o ile możesz emulować imperatywną składnię w, powiedzmy, Haskellu przy odrobinie pracy. Niemniej jednak składnia JavaScript prowadzi do tego, że jest on traktowany jako przepływ pracy, a nie ocena funkcji. Z tego powodu ja (lub większość programistów funkcjonalnych) uważam, że termin „funkcjonalny” jest zbyt obszerny.
shuhalo
@ user411768: więc mówisz, że funkcjonalność języka zależy od projektu jego standardowej biblioteki? Nigdy wcześniej nie słyszałem takiej definicji. Java ma większość narzędzi potrzebnych do programowania w stylu funkcjonalnym (na przykład zamknięcia i funkcje anonimowe), których C ++ (obecnie) nie ma. Myślę, że to sprawia, że ​​JS jest o wiele bardziej FP niż C ++. Fakt, że język nie zmusza cię do programowania w stylu FP, nie czyni go „mniej funkcjonalnym”, prawda?
jalf
1
(i) Biblioteka standardów jest częścią standardu, podobnie jak cechy syntaktyczne i podkreśla pewien idiomatyczny i konceptualny styl. Np. „C ++ z STL” bardzo różni się od „C z klasami”. To ma wpływ. (ii) JavaScript cechuje orientacja obiektowa, funkcje obywatelskie pierwszej klasy - cechy są raczej ortogonalne w stosunku do dychotomii imperatywnej / funkcjonalnej. Jednak ani bezpośrednio nie wdraża curry, ani nie zapewnia czystości, ani nigdy nie był do tego przeznaczony. (iii) Moje ostatnie słowa na ten temat, zobacz pierwszy akapit postu.
shuhalo
3
Stwierdzenie, że JavaScript i C ++ oferują te same funkcje programowania, jest z pewnością błędne. JavaScript sprawia, że ​​programowanie funkcjonalne jest dość proste i proste bez wszystkich niechlujnych konstrukcji, przez które trzeba przejść w C ++, aby osiągnąć to samo. Jest wielu świetnych programistów C ++, którzy wyraźnie twierdzą, że programowanie funkcjonalne nie jest naprawdę zalecane w C ++, jednak jest mnóstwo artykułów na temat programowania funkcjonalnego w JavaScript
johnbakers
9

Termin „język programowania funkcjonalnego” jest obecnie tak przeciążony, że jest prawie bezużyteczny. Istnieją dwa dominujące znaczenia:

  1. Posiada funkcje pierwszej klasy
    • To jest JavaScript!
  2. Opiera się na funkcjach używanych w rachunku lambda, z naciskiem na unikanie trwałego stanu mutowalnego (często zastępując go parametrami przekazywanymi do funkcji)
    • Jak powszechnie napisano, Javascript nie działa zdalnie!

Wybierz swoje znaczenie, a na pytanie odpowiesz.

Głaskanie pod brodę
źródło
Czy istnieje źródło, które używa „programowania funkcjonalnego” w odniesieniu do języków, których funkcje są obywatelami pierwszego rzędu?
shuhalo
@ user411768: Właściwie to inny odpowiadający link do artykułu Wikipedii, który używa tej definicji. en.wikipedia.org/wiki/Javascript - Joel Spolsky również zasugerował tę definicję w swoim "Czy twój język programowania to potrafi?" post na temat korzyści z „programowania funkcjonalnego”
Chuck,
Zauważasz, że, jak powszechnie napisano, JavaScript nie używa twojego drugiego punktu, ale z pewnością nie oznacza to, że nie ma programistów, którzy dokładnie to robią, i że język nie obsługuje takiej funkcji, ponieważ z pewnością tak
johnbakers
@OpenLearner: Cóż, tak, ale to samo dotyczy Javy i wielu innych języków, które są ogólnie uważane za bezwzględnie konieczne - można je pisać w funkcjonalnym stylu, ale nie jest to dobra ścieżka języka.
Chuck,
... ale najnowszy JS to obsługuje.
Erik Reppen,
3

Nie sądzę, aby istniała konkretna definicja programowania funkcjonalnego, jednak wiele rzeczy, które ludzie uważają za „programowanie funkcjonalne”, można zrobić za pomocą javascript. Oto dobry krótki przykład w tym artykule.

marknery
źródło
2

Dla mnie Javascript jest zarówno językiem imperatywnym, jak i funkcjonalnym, i możesz go używać w dowolny sposób, a nawet ( egad ) w obie strony. Lub możesz wybrać jeden paradygmat i nigdy nie dotykać drugiego. To zależy od Ciebie. Podobnie jak Ty, uważam, że Javascript nie należy nazywać językiem funkcjonalnym, ponieważ pozwala on wchodzić i wychodzić z paradygmatu programowania funkcjonalnego. Być może gdyby miał jakąś pragmę, by ograniczyć cię do używania tylko paradygmatów programowania funkcjonalnego, to byłoby to przydatne, jak sądzę. Ale podsumowując, mówię, że jest to bardziej imperatywny / proceduralny język z dorzuconymi niektórymi funkcjami programowania.

Brian Onn
źródło
Z tego powodu F # nie można długo nazywać funkcjonalnym.
Eric Mickelsen
1
Dobrze. Według Wikipedii, F # to dokładnie to, co właśnie nazwałem Javascriptem: „F # [...] to wieloparadygmatyczny język programowania [...] obejmujący programowanie funkcjonalne, a także dyscypliny programowania zorientowanego obiektowo”
Brian Onn
2

Zwykle nie myślę o językach programowania jako o jednym konkretnym paradygmacie, ale że nadają się one do pewnych paradygmatów. Jednak tylko dlatego, że nadają się do określonego paradygmatu, nie oznacza, że ​​musisz używać tego paradygmatu. Całkiem możliwe jest pisanie programów obiektowych w C i imperatywnych w ML. Nie używanie określonego paradygmatu do rozwiązania problemu, ponieważ język nie jest do tego przeznaczony, jest po prostu sztucznym ograniczaniem siebie (oczywiście nadal należy brać pod uwagę ograniczenia języka przy podejmowaniu decyzji, czy dane rozwiązanie będzie dobre).

David Brown
źródło
0

Cóż, nie powiedziałbym, że to programowanie funkcjonalne, ale tak bym powiedzieć, że jest obiektowym i właśnie dzisiaj przyjaciel powiedział, że nie umieścić go na tej półce albo.

Tak więc, chociaż nie powiedziałbym, że tak jest, myślę, że jest miejsce na opinię. Ma klasyczne cechy programowania funkcjonalnego, ale nie ma innych.

Slezica
źródło
2
JavaScript jest zorientowany obiektowo. OO nie wymaga klas, wymaga jednak obiektów.
Incognito
3
Javascript nie jest zorientowany obiektowo, jest oparty na prototypach.
Kris
1
JavaScript to zupa programistyczna. Trochę tego i trochę tamtego.
Andrew S
0

Javascript jest do rzeczy. To naprawdę zależy od tego, jak go zaprogramujesz. Jeśli koduję w sposób OO, czy nie byłoby to OO? Więc jeśli po prostu kodujesz rzeczy w sposób „funkcjonalny”, będzie to funkcjonalne. Wydaje mi się, że jest to język wieloparadygmatyczny, więc nazwanie go tylko jedną rzeczą nie jest do końca trafne.


źródło
0

@petraszd Przepiszę trochę Twój kod, aby uzyskać „nowy” dla operatora:

   
   function ffor(a, b, f){
     function it(i){
       if(i > b)return
       f(i)
       it(i+1)
     }
     it(a)
   }

   print("----" + new Date()+"----")

   var funcs = []
   ffor(0, 9, function(i){
     funcs.push(function(){return i})
   })

   ffor(0, 9, function(i){
     print(funcs[i]())
   })

Ale wiem, że ten sposób ma wady dla dużych pętli ...

Powiązane pytanie o optymalizację rekurencji ogona w JS

PS Zamieszczone tutaj, bo mam problem z formatowaniem kodu podczas wysyłania jako komentarz

aeracode
źródło
0

W Javascript możesz zrobić coś takiego !!

// Data
var fruits = [
    { name: 'apple',  price: 5 }, 
    { name: 'orange', price: 10 }, 
    { name: 'lemon',  price: 15 }
]

// Request Data from magicURL
request('magicURL')
    .then(selectKeyOf('price'))
    .then(priceMethod('sum'))
    .then((result)=>{
        console.log(result) // 30
    })

Stworzyłem stronę github w celu demonstracji tej koncepcji i możesz sklonować / wyświetlić moją implementację

Wayne Chiu
źródło
0

Jak wiemy, funkcjonalny język programowania nie pozwala na zmianę lub mutację elementów (stanu) funkcji, ale w javascript jest to dozwolone w tym sensie, że nie jest funkcjonalnym językiem programowania, chociaż traktuje funkcję jako obywatela pierwszej klasy.

Sourabh Ranka
źródło
-2

To, czego naprawdę nienawidzę w javascript (jeśli spróbujesz spojrzeć na to jako język FP), to:

function getTenFunctionsBad() {
  var result = [];
  for (var i = 0; i < 10; ++i) {
    result.push(function () {
      return i;
    });
  }
  return result;
}

function getTenFunctions() {
  var result = [];
  for (var i = 0; i < 10; ++i) {
    result.push((function (i) {
      return function () {
        return i;
      }
    })(i));
  }
  return result;
}

var functionsBad = getTenFunctionsBad();
var functions = getTenFunctions()
for (var i = 0; i < 10; ++i) {
  // using rhino print
  print(functionsBad[i]() + ', ' + functions[i]());
}

// Output:
//   10, 0
//   10, 1
//   10, 2
//   10, 3
//   10, 4
//   10, 5
//   10, 6
//   10, 7
//   10, 8
//   10, 9

Musisz zrozumieć środowisko stosu JS (ja nie, jeśli to właściwe określenie), aby zrozumieć takie zachowanie.

Na przykład w schemacie nie możesz czegoś takiego stworzyć (ok, ok - z pomocą odnośników do języków bazowych możesz to zrobić):

(define (make-ten-functions)
  (define (iter i)
    (cond ((> i 9) '())
          (else (cons (lambda () i) (iter (+ i 1))))))
  (iter 0))

(for-each (lambda (f)
            (display (f))
            (newline)) (make-ten-functions))
petraszd
źródło
1
Hm, myślę, że Javascript zawiera odniesienie do zmiennej, ale nie zawiera odniesienia do wartości .
aeracode
1
Zrozumienie zakresu zmiennych ma kluczowe znaczenie dla skutecznego programowania w dowolnym języku. Javascript nie jest w tym sam.
bogate wspomnienie