Biedny, biedny JavaScript

2011-11-15 21:16

Przyznam, iż jestem trochę zaskoczony. Okazuje się bowiem, że niekiedy zupełnie nie udaje mi się skomunikować tego, co mam w rzeczywistości na myśli. A wydawać by się mogło, że przynajmniej te 500+ notek na blogu powinno dość skutecznie nauczyć mnie, jak klarownie formułować swoje stwierdzenia i opinie. Teoretycznie niby też wiem, że zrozumienie jest często podwójną iluzją, więc z dwóch wyjaśnień należy zawsze wybierać te łatwiejsze i bardziej bezpośrednie – także wtedy, gdy trzeba je dopiero znaleźć. To wszystko wydaje się oczywiste, dopóki – jak się przekonałem – nie okaże się trudne w praktycznym stosowaniu.

O co mi w tym miejscu chodzi? Ano o to, iż niesłusznie zostałem uznany przez kilka osób za – nieco wyolbrzymiając – hejtera JavaScriptu. Tak została przez niektórych odebrana moja niedawna publikacja slajdów z prezentacji pod tytułem The Beauty and the JavaScript; tytułem, który rzeczywiście może dawać co nieco do myślenia ;) I chociaż mógłbym uznać, że wchodzi tu w grę głównie kwestia oceny wykładu po samych slajdach, to jakoś wydaje mi się, że wypadałoby tu dokonać małego sprostowania. Dzięki temu mógłbym też napisać, jak to właściwie jest z tą moją opinią o JavaScripcie, który przecież już od dłuższego czasu jest sam w sobie bardzo nośnym tematem.

Spieszę więc z wyjaśnieniem, że w kwestii JavaScriptu mam raczej osobliwą opinię. Otóż przede wszystkim jest mi go… żal.

Są mianowicie dwa główne powody, dla których uważam język JavaScript za “pokrzywdzony” w pewnym sensie. Pierwszy z nich dotyczy całego szeregu błędnych decyzji projektowych, jakimi został on obarczony. Chodzi mi tu o rzeczy niemal oczywiste: takie, których ewentualne usprawiedliwianie jest wyłącznie racjonalizacją defektów. Obejmuje to chociażby:

  • Brak typu liczbowego dla liczb całkowitych. W JS wszystkie liczby to floaty, co rodzi szereg problemów związanych z dokładnością obliczeń, jeśli jest ona wymagana.
  • Brak natywnej obsługi tablic. To, czego używa się w charakterze tablic, jest tak naprawdę zwykłymi obiektami, mającymi co najwyżej specjalny prototyp (Array.prototype). To, co z wierzchu wygląda na indeksy, jest z kolei zwykłymi atrybutami tychże obiektów. Ma to negatywny wpływ na całe mnóstwo aspektów języka: od wydajności po składnię typowych konstrukcji w rodzaju pętli for-in.
  • Słabe typowanie (weak typing) jest tak słabe, że właściwie nie ma go w ogóle. W skrócie i na przykładach: "2"+2 to w JavaScripcie "22", a "2"-2 to dla odmiany 0. Wyrażenie [] == true to fałsz, ale instrukcja if ([]) “przejdzie”; podobnie jest dla pustego ciągu (""), ciągu białych znaków, "0", [""], [[]], ["0"] i wielu innych wyrażeń, które niby są “równe fałszowi” (==0), ale jako warunki logiczne okazują się nagle prawdą.
    Wyjaśnieniem jest tu kompletnie nieintuicyjny mechanizm koercji typów dla argumentów operatorów (takich jak + i ==). Z wierzchu wygląda on na słabe typowanie (weak typing), ale ze względu na brak pojęcia kontekstu ewaluacji daje wspomniane wyżej, zaskakujące efekty.

Każda z powyższych cech JavaScriptu – i kilka do nich podobnych – jest poważną usterką. Jednocześnie jednak żadna z nich nie wydaje się być ściśle związana z głównymi założeniami architektury języka. Najprawdopodobniej więc każdy z tych błędów projektowych był do uniknięcia. Wszystkie one znalazły się jednak w języku, który w tym roku dobił się do pierwszej dziesiątki indeksu TIOBE i należy do najpopularniejszych narzędzi programistycznych na świecie… Auć.

Incydentalnie dochodzimy w ten sposób do drugiej przyczyny moich nietypowych odczuć w odniesieniu do JavaScriptu. Jego obecna popularność ma bowiem swoją ciemną stronę. Dość powszechne jest bowiem niezrozumienie samych podstaw JS-a, bowiem mało kto uczy się go systematycznie. A doprawdy jest tutaj czego się nauczyć, zwłaszcza jeśli ulegamy kuszącemu – i zupełnie błędnemu wrażeniu – iż jest to język podobny do Javy, C++ czy C#.

JavaScript ma dwie wyróżniające i niezwykle interesujące cechy: obiektowość opartą na prototypach i strukturę polegającą na funkcjach i domknięciach (closures). Te ostatnie występują wprawdzie w wielu popularnych językach, lecz na znacznie mniejszą skalę niż to się dzieje w JS. Z kolei zupełnie bezklasowy, oparty o prototypy OOP właściwie nie ma odpowiednika w żadnym innym mainstreamowym języku. Połączenie obu tych cech daje całkowicie unikalną mieszankę, która dla niepoznaki przebrana jest w znajomą składnię w stylu C.
Ubranie nietypowych cech w typową formę powoduje, że niezwykle łatwo “przejechać” się na pozornie znajomych konstrukcjach językowych, jednocześnie dziwiąc się brakowi “oczywistych” elementów – takich jak klasy. Ów brak klas w JavaScripcie jest niemal przysłowiowy i stanowi motywację do powstania wielu frameworków i bibliotek, które tę “lukę” wypełniają.

Jakkolwiek bezcelowe to jest (bo jest), warto tutaj zatrzymać się i zastanowić. Na ile typowy jest język, w którym można zaimplementować nie tyle wzorce projektowe, co całe programistyczne paradygmaty – takie jak właśnie obiektowość oparta o klasy?… Rzekłbym, że bardzo nietypowy – na tyle, że z miejsca potrafiłbym podać tylko jeden inny przykład takiego języka.

I na tym właśnie polega problem JavaScriptu. Wygląda z pozoru jak C, uważany jest często za niedorobioną Javę, koncepcyjnie jest od niej różny niczym Haskell, a możliwościami rywalizuje z Lispem…
Nic dziwnego, że biedak nie znajduje zrozumienia.



13 comments for post “Biedny, biedny JavaScript”.
  1. Banhurt:
    November 15th, 2011 o 21:23

    A tak z ciekawości – co myślisz o Darcie?

  2. Zielony:
    November 16th, 2011 o 1:09

    ActionScript FTW! Na oko nie ma żadnej z wymienionych wad.

  3. cji:
    November 16th, 2011 o 8:58

    “nie ma odpowiednika w żadnym innym mainstreamowym języku”

    To prawda, ale jesli rozejrzec sie troche uwazniej, to pojawiaja sie nowe jezyki oparte o ten sam model obiektowosci (na przyklad Io).

    “Te ostatnie występują wprawdzie w wielu popularnych językach, lecz na znacznie mniejszą skalę niż to się dzieje w JS.”

    Juz kiedys sie sprzeczalem z kims, czy JS jest jezykiem obiektowym, czy funkcyjnym. Dla mnie jego glowna sila jest funkcyjnosc, ale ja jestem akurat fanem tego paradygmatu programowania. W kazdym razie – chociaz closures rzeczywiscie wystepuja w wiekszosci wysokopoziomowych, dynamicznych jezykow, to w JavaScripcie wydaja sie najnaturalniejsze i dosc wygodne w obsludze. (Z drugiej strony mozna argumentowac, ze popularnosc higher order functions i closures w JS wynika z braku innych mechanizmow:))

    Co chcialem powiedziec – JSowi niczego nie brakuje, tak naprawde. Moze poza kompetentnymi programistami – sila tego jezyka jest naprawde duza, znacznie, znacznie wieksza, niz znajoma, oswojona skladnia kazalaby przypuszczac. Do tego brak narzuconych z gory ograniczen (np. wlasnie obiektowosc oparta na prototypach jest znacznie bardziej elastyczna, niz oparta na klasach) sprawia, ze bardzo latwo jest napisac w JSie kompletnie nieczytelny, ciagnacy sie jak spaghetti, absolutnie niemozliwy do utrzymania proceduralno-dziwny kod.

    Jesli jednak wezmiemy CoffeeScript (w sumie niewiele wiecej, niz troche skladniowych cukierkow) i solidne przygotowanie do projektowania i programowania funkcyjnego i obiektowego, na wyjsciu otrzymamy czesto bardzo dobry produkt. Biorac zas pod uwage jak wielki postep dokonal sie wsrod interpreterow/vm JSa w dziedzinie wydajnosci mozna chyba powiedziec, ze obecnie nie ma sensu mu wspolczuc; teraz trzeba mu zazdroscic, bo za cane kilku (pomniejszych, naprawde) bledow projektowych osiagnal wczesnie dominujaca pozycje i teraz, kiedy niejako do tej pozycji dorosl, odcina od niej kupony :)

  4. Xion:
    November 16th, 2011 o 18:17

    @Banhurt: Chwilowo nic (bowiem nie bawiłem się nim w ogóle), ale lubię jego słynnego Hello worlda ;-)

    @Zielony: Ale to Flash, a Flash jak wiadomo jest zuy i w ogóle już umiera :)

    @cji:

    “To prawda, ale jesli rozejrzec sie troche uwazniej, to pojawiaja sie nowe jezyki oparte o ten sam model obiektowosci (na przyklad Io).”
    Może źle kojarzę, ale chyba Scala też jest trochę na bakier z klasami. Poza tym języki dynamiczne w stylu Pythona/Ruby też są pod tym względem podobne do JS, bo chociaż klasy mają, to nie na ich podstawie nie identyfikują możliwości obiektów, bo stosują duck typing. (Interfejsy w Go to też odnoga tego zjawiska).

    “Dla mnie jego glowna sila jest funkcyjnosc, ale ja jestem akurat fanem tego paradygmatu programowania.”
    Fajnie by więc było, gdybyś widział go tam, gdzie jest rzeczywiście ;) JS nie jest bardziej funkcyjny niż choćby Python. Może nawet mniej bo brakuje mu wbudowanych funkcji wyższego rzędu (map, fold/reduce, filter), a currying (częściowa aplikacja) jest wspierany gorzej niż w Pythonie. O typowo funkcyjnych ficzerach – jak leniwa ewaluacja, wydzieleniu kodu z efektami ubocznymi, monady, itd. – już nawet nie wspominam :)

    “W kazdym razie – chociaz closures rzeczywiscie wystepuja w wiekszosci wysokopoziomowych, dynamicznych jezykow, to w JavaScripcie wydaja sie najnaturalniejsze i dosc wygodne w obsludze. (Z drugiej strony mozna argumentowac, ze popularnosc higher order functions i closures w JS wynika z braku innych mechanizmow:))”
    Tak, to ma dwie strony. Ale po prostu JS taki jest, że opiera się właśnie na domknięciach gdy przychodzi do realizacji takich rzeczy jak hermetyzacja czy przestrzenie nazw.

    “Co chcialem powiedziec – JSowi niczego nie brakuje, tak naprawde. Moze poza kompetentnymi programistami – sila tego jezyka jest naprawde duza, znacznie, znacznie wieksza, niz znajoma, oswojona skladnia kazalaby przypuszczac.”
    To właśnie chciałem wczorajszą notką przekazać :)

    ” (…) bardzo latwo jest napisac w JSie kompletnie nieczytelny, ciagnacy sie jak spaghetti, absolutnie niemozliwy do utrzymania proceduralno-dziwny kod. ”
    Dodam jeszcze (chociaż jest to uwaga z gatunku “gdzieś słyszałem że”) to, że model prototypowy jest podobno strasznym bólem głowy ze względu wydajności interpreterów JS. Jeśli interpreter nie potrafi przewidzieć na podstawie statycznej analizy, jakie atrybuty obiektu będą używany, to nie zbuduje czegoś w rodzaju vtable do szybkiego rozstrzygania dostępu do atrybutów obiektów, i wydajność znacznie spada. Jeśli jest to prawdą, to w krytycznych wydajnościową częściach aplikacji należy tak naprawdę poniechać sztuczek opartych na specyficznych cechach prototypowej obiektowości.

    “(…) trzeba mu zazdroscic, bo za cane kilku (pomniejszych, naprawde) bledow projektowych osiagnal wczesnie dominujaca pozycje i teraz, kiedy niejako do tej pozycji dorosl, odcina od niej kupony :)”
    No cóż, popularność języka jest chyba rzadko wynikiem jego “jakości” (cokolwiek się za tym kryje), a częściej jakiegoś bliżej niesprecyzowanego procesu biznesowo-dziejowego :) Przykładami są choćby właśnie JS, Objective-C, C++ czy Java, a kontrprzykładem jest być może Python. Gdyby było inaczej, to wszyscy kodowalibyśmy w lispach lub Haskellu ;-)

  5. cji:
    November 16th, 2011 o 21:46

    “Może źle kojarzę, ale chyba Scala też jest trochę na bakier z
    klasami.”

    Raczej nie – ma “klasyczne klasy”, tyle, ze dodaje do nich sporo, na
    przyklad traits (z tego co pamietam dzialajace jak mixins) i objects.

    “JS nie jest bardziej funkcyjny niż choćby Python.”

    Ale nie jest funkcyjny mniej. Ma domkniecia i higher order functions –
    a to mniej wiecej wystarcza, zeby zbudowac cokolwiek innego… Poza
    tym, porownywalem JSa nie z Pythonem, a z Java i C++ – na ich tle
    JavaScript wydaje sie calkiem mocno funkcyjnym jezykiem ;)

    “Może nawet mniej bo brakuje mu wbudowanych funkcji wyższego rzędu
    (map, fold/reduce, filter)”

    To prawda, ale po pierwsze mozna je latwo napisac, a po drugie – jesli
    sie nie ma na to ochoty – wiele bibliotek je udostepnia. JQuery ma
    each(), a Underscore.js jest zbudowane w calosci wokol tych funkcji.

    “a currying (częściowa aplikacja) jest wspierany gorzej niż w
    Pythonie.”

    Dlaczego gorzej? Faktycznie, nie ma syntactic sugar tak milego, jak *
    i ** w Pythonie – w ogole nie ma (chyba?) “keyword arguments” – ale
    jest apply(), co (jak wiadomo z LISPow:)) absolutnie wystarcza.

    “O typowo funkcyjnych ficzerach – jak leniwa ewaluacja, wydzieleniu
    kodu z efektami ubocznymi, monady, itd. – już nawet nie wspominam :)”

    Oczywiscie, ze monady mozna zaimplementowac w JS. Znow, wydaje mi sie,
    ze mylisz syntactic sugar z mozliwoscia osiagniecia pewnego efektu w
    danym jezyku. Podobnie da sie zaimplementowac lazy evaluation (via
    closures), a wydzielenie kodu z efektami ubocznymi to tylko konwencja.

    Moje stanowisko, w skrocie: mimo ze JS nie wspiera funkcyjnego stylu
    programowania w skladni (ale zobacz CoffeeScript!), to dostarcza
    wszystkich niezbednych narzedzi, zeby ten styl w nim uprawiac – w
    przeciwienstwie do C, C++, Javy (przynajmniej w wersji, ktora znam –
    nieco outdated juz), VB, Delphi i wielu innych.

    “Ale po prostu JS taki jest, że opiera się właśnie na domknięciach gdy
    przychodzi do realizacji takich rzeczy jak hermetyzacja czy
    przestrzenie nazw.”

    Co dla mnie dosc wyraznie swiadczy o jego funkcyjnym “zacieciu” :)

    “model prototypowy jest podobno strasznym bólem głowy ze względu
    wydajności interpreterów JS.”

    Ogladalem filmik – prezentacje googlowego V8, gdzie ktos tlumaczyl,
    jak im sie udalo zamienic prototypy w cos na ksztalt statycznych klas
    (tyle, ze w czasie wykonania). Juz teraz wydajnosc glownych
    interpreterow jest “calkiem, calkiem” – w przyszlosci prawdopodobnie
    jeszcze sie poprawi. Akurat wydajnosc jest problemem wszystkich
    jezykow dynamicznych – zwroc uwage np. jak duzy narzut jest w
    Pythonie, kiedy zamiast zwyklego inta przekazujesz gdzies (albo
    kopiujesz!) PyObject. Do tego w Pythonie mamy welodziedziczenie, ktore
    mysle, ze komplikuje kwestie dostepu do atrybutow rownie skutecznie,
    co prototypy.

    “Gdyby było inaczej, to wszyscy kodowalibyśmy w lispach lub Haskellu
    ;-)”

    Zgoda co do powodow, dla ktorych jezyki staja sie popularne – to
    rzeczywiscie wypadkowa wielu procesow, z ktorych jakosc jezyka nie
    jest chyba najwazniejsza. Koduje w lispie (Scheme) i OCamlu (zamiast
    Haskella – sa porownywalne jesli chodzi o system typow) i w Pythonie –
    a nawet w nim czesto brakuje mi niektorych cech z bardziej
    egzotycznych jezykow (tail call optimization!)… Nie wyobrazam sobie,
    co musza czuc ludzie piszacy wciaz w C++ czy Javie, zgroza po prostu
    ;)

    W kazdym razie JS jest wedlug TIOBE w pierwszej dziesiatce
    najpopularniejszych jezykow – mozna powiedziec, ze to on (wespol z
    Pythonem) wprowadza funkcyjnosc do mainstreamu. Za co czesc mu i
    chwala, niewazne, skad sie wzial w tej pierwszej dziesiatce ;)

  6. Xion:
    November 17th, 2011 o 10:08

    “Ale nie jest funkcyjny mniej. Ma domkniecia i higher order functions – a to mniej wiecej wystarcza, zeby zbudowac cokolwiek innego… Poza tym, porownywalem JSa nie z Pythonem, a z Java i C++ – na ich tle JavaScript wydaje sie calkiem mocno funkcyjnym jezykiem ;)”
    Javy na pewno (zwłaszcza poniżej 7), ale C++ na pewno nie, bo ten ma higher-order functions od bardzo dawna, a w C++11 pojawiło się sporo nowych funkcyjnych ficzerów (ciekawym są jawne domknięcia, tj. określanie jakie zmienne wchodzą do closure i czy robią to przez referencję – z możliwością zmiany – czy nie).

    “To prawda, ale po pierwsze mozna je latwo napisac, a po drugie – jesli sie nie ma na to ochoty – wiele bibliotek je udostepnia. JQuery ma each(), a Underscore.js jest zbudowane w calosci wokol tych funkcji.”
    Można napisać != jest :)

    “Dlaczego gorzej? Faktycznie, nie ma syntactic sugar tak milego, jak *i ** w Pythonie – w ogole nie ma (chyba?) „keyword arguments” – ale jest apply(), co (jak wiadomo z LISPow:)) absolutnie wystarcza.”
    W JS każdy currying wymaga napisania opakowującej funkcji która przekazuje niezbindowane argumenty. W Pythonie bardzo często nie trzeba bo jest functools.partial (a gdy trzeba, to lambda: jest krótsze niż def:, a w JS function() jest zawsze takie samo). Oczywiście ani jedno ani drugie nie porównuje się z Haskellem, gdzie currying jest za darmo.

    “Oczywiscie, ze monady mozna zaimplementowac w JS. Znow, wydaje mi sie, ze mylisz syntactic sugar z mozliwoscia osiagniecia pewnego efektu w danym jezyku. Podobnie da sie zaimplementowac lazy evaluation (via closures), a wydzielenie kodu z efektami ubocznymi to tylko konwencja.”
    Chętnie zobaczę te monady :) Znów używasz też argumentu “przecież można to zakodować”. Na nim opiera(ł) się C++ i nie było to specjalnie szczęśliwe założenie, bo skutkiem była raczej redukcja do wspólnej funkcjonalności i rezygnacja z wielu istniejących ficzerów (wyjątki, szablony) przez programistów zamiast implementowania i upowszechniania się customowych rozwiązań.

    “Akurat wydajnosc jest problemem wszystkich jezykow dynamicznych – zwroc uwage np. jak duzy narzut jest w Pythonie, kiedy zamiast zwyklego inta przekazujesz gdzies (albo
    kopiujesz!) PyObject. Do tego w Pythonie mamy welodziedziczenie, ktore mysle, ze komplikuje kwestie dostepu do atrybutow rownie skutecznie, co prototypy.”
    Trochę zależy to od tego, czy mówimy o CPythonie czy PyPy, który jest w dużym stopniu JITowany – podobnie jak nowoczesne interpretery JS. A co do wielodziedziczenia, to akurat Python jest chyba jedynym językiem w którym jest ono zrobione dobrze (a przynajmniej lepiej niż w drugim popularnym języku gdzie ono jest :)).

    “w Pythonie – a nawet w nim czesto brakuje mi niektorych cech z bardziej egzotycznych jezykow (tail call optimization!)…”
    +1, chociaż tall-call to w dużym stopniu funkcyjny sposób na realizację pętli i przydatność tego rozwiązania jest zdecydowanie mniejsza w języku typowo imperatywnym, jak Python.

    “W kazdym razie JS jest wedlug TIOBE w pierwszej dziesiatce najpopularniejszych jezykow – mozna powiedziec, ze to on (wespol z Pythonem) wprowadza funkcyjnosc do mainstreamu.”
    I z tym się mogę zgodzić. Dzięki JS, Pythonowi i ostatnio C++ funkcyjne ficzery stają się powoli standardem i nawet Java musi je w końcu dostać :)

  7. cji:
    November 17th, 2011 o 15:25

    “Znów używasz też argumentu „przecież można to zakodować”.”

    Mam prawdopodobnie wywodzace sie jeszcze z mojej przygody z C++ dosc
    silne poczucie odrebnosci jezyka i biblioteki; niekoniecznie chcialbym
    po prostu krytykowac sam jezyk za braki w jego bibliotekach. Podobnie
    zreszta, jak za roznice miedzy implementacjami jezyka. W kazdym razie,
    jesli mowisz, ze JavaScript “nie ma” czegos, to odbieram to jako “w
    jezyku JavaScript nie mozna zakodowac”; z drugiej strony, gdybys
    powiedzial, ze “stdlib JS nie dostarcza” czegos, to oczywiscie
    zgodzilbym sie natychmiast :)

    “W JS każdy currying wymaga napisania opakowującej funkcji która
    przekazuje niezbindowane argumenty. W Pythonie bardzo często nie
    trzeba bo jest functools.partial (a gdy trzeba, to lambda: jest
    krótsze niż def:, a w JS function() jest zawsze takie samo).”

    Powiedzialbym, ze functools.partial da sie w JS napisac bez problemu,
    ale nie chce sie narazac ;)

    “Oczywiście ani jedno ani drugie nie porównuje się z Haskellem, gdzie
    currying jest za darmo.”

    “Za darmo” to znaczy defaultowo? Nie znam Haskella, ale podejrzewam,
    ze jest tak jak w OCamlu, tzn. jesli

    let f a b = 9;;
    f;;
    – : ‘a -> ‘b -> int =

    to

    f 8;;
    – : ‘_a -> int =

    – ale zauwaz, ze juz na przyklad w Scali currying nie jest defaultem,
    trzeba podac _ jako jeden z parametrow, albo zadeklarowac funkcje w
    specjalny sposob. Podobnie w Scheme (curry) nie jest w zaden sposob
    wbudowane w jezyk; nie jest nawet forma skladniowa, jest po prostu
    kolejna higher order funkcja.

    Ale kurcze, przeciez zgodzilem sie, ze JS nie wspiera programowania
    funkcyjnego rownie mocno, co niektore inne jezyki! Moj point jest
    tylko taki, ze rowniez nie uniemozliwia go i nawet niespecjalnie w nim
    przeszkadza, jesli to jest styl, ktory Ci odpowiada.

    “Chętnie zobaczę te monady :)”

    Hmm, jesli jako “monady” rozumiesz syntactic sugar dla “bind”
    (haskellowe >>= chyba?) to oczywiscie nie znajdziesz ich ani w JS, ani
    w Pythonie; musialbym siegnac po F#, ktore wspiera monady skladniowo
    poprzez let! i return!. Jesli jednak trzymac sie definicji monady jako
    po prostu pewnego typu, umozliwiajacego pewne operacje, to oczywiscie,
    ze da sie je zaimplementowac; w Pythonie sa przynajmniej dwie fajne
    implementacje, w tym jedna wykorzystujaca metode send() na
    generatorach – w JSie natomiast “jQuery jest monada”
    (importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/)
    tudziez “mozna je zbudowac” (amix.dk/blog/post/19509). Bottom
    line: monady nie sa jakos specjalnie magiczne, przeciwnie, w
    wiekszosci (state, list monad) sa bardzo proste w konstrukcji, tyle,
    ze troche mniej przyjemne w uzyciu w jezykach, ktore nie daja wsparcia
    skladniowego.

    “+1, chociaż tail-call to w dużym stopniu funkcyjny sposób na
    realizację pętli i przydatność tego rozwiązania jest zdecydowanie
    mniejsza w języku typowo imperatywnym, jak Python.”

    Identycznego argumentu uzywa Guido… a mnie dalej brakuje naturalnej
    rekurencji, przy ktorej nie musialbym sie martwic o RuntimeError:
    recursion… ;).

    Dzieki za rozmowe – mysle, ze udalo mi sie (pierwszy akapit)
    zidentyfikowac jedyna roznice miedzy naszymi pogladami, wiec juz nie
    bardzo jest sie o co spierac :) Poczekam na kolejna notke i podrecze
    Cie pewnie przy jej okazji ;)

    Pozdrawiam, Piotr Klibert.

  8. cji:
    November 17th, 2011 o 15:28

    Hmm, cos Twoj WordPress mnie nie lubi; nie mam pojecia, o co moze mu chodzic. Postne odpowiedz na swoim blogu.

  9. Xion:
    November 17th, 2011 o 20:31

    Albo w samym WordPressie, albo w mojej jego instalacji jest jakiś żenujący bug który powoduje niewyświetlanie komentarzy dłuższych niż 2000 znaków jeśli zawierają one jakiegokolwiek URL-a (!). Wydaje mi się, że zidentyfikowałem nawet fragment kodu WP, który to robi, ale nie wiem czy to bug czy feature ;-) W każdym razie materiał na pytanie do StackOverflow :)

  10. yarpo:
    July 2nd, 2012 o 13:18

    Pozwolę sobie odnieść się do:
    <>

    A w C dałoby radę? :) Mam dziwne wrażanie, że w PHP działałoby to podobnie, jeśli użyć operator `+’. Tak, w PHP jest też `.’, ale w JS można to obejść bez większego problemu, choćby:
    “2” *1 + 2 // na pewno liczba
    “2” + ” + 2 // ma pewno ciąg znaków

    Choć może najrozsądniej jest użyć parseInt / parseFloat?
    Druga sprawa, jak często w dojrzałym kodzie są takie dziwne sytuacje?

    Co do falsy values powstalo już winternecie tyle, że nie będe się rozpisywał :). Patrząc na konkretne przykłady to rzeczywiście wygląda dziwnie. jednak od pewnego czasu programuję głównie w JavaScript (Dojo Toolkit) i jakoś te problemy z warunkami są niezauważalne. Tablicę najczęsciej jeśli porównuję to sprawdzam, czy ma pole `length’ [choć Crockford pokazywal kiedyś jeszcze ciekawszą konstrukcję] :).

    Ogólnie chyba rozumiem, co chciałeś powiedzieć w tym wpisie. Uważam jednak, że JS ma w sobie pewien urok dzięki temu, że jest tak dziwny. Wiem, wiem – nie o urok chodzi w programowaniu. Chociaż… powiedz to np. Perlowcom :P

    W swojej magisterce napisałem 2 podrozdziały zatytułowane “asemblaryzacja JavaScript” oraz “Sukces mimo wszystko”. Sądzę, że dosyć dobrze uzupełniają ten wpis :)
    JavaScript na poważnie (strony 22 i 56)

  11. yarpo:
    July 2nd, 2012 o 13:19

    Zżarło mi kawałek ten:

    1. "2"+2 to w JavaScripcie "22", a "2"-2

    w miejsce dwóch ostrych nawiasów.

  12. Xion:
    July 5th, 2012 o 10:18

    "2"-2 powinno po prostu rzucić jakiś wyjątek. Nie odejmuje się liczb od stringów, po prostu :)

    Tablicę najczęsciej jeśli porównuję to sprawdzam, czy ma pole `length’

    W jQuery jest $.isArray która to funkcja jest właśnie implementacją ‘sposobu Crockforda’.

    Uważam jednak, że JS ma w sobie pewien urok dzięki temu, że jest tak dziwny. Wiem, wiem – nie o urok chodzi w programowaniu. Chociaż… powiedz to np. Perlowcom :P

    Trochę to podpada pod syndrom sztokholmski :)

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.