eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programmingJaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
  • X-Received: by 2002:a37:4dc5:: with SMTP id a188mr746736qkb.4.1546596929848; Fri, 04
    Jan 2019 02:15:29 -0800 (PST)
    X-Received: by 2002:a37:4dc5:: with SMTP id a188mr746736qkb.4.1546596929848; Fri, 04
    Jan 2019 02:15:29 -0800 (PST)
    Path: news-archive.icm.edu.pl!news.icm.edu.pl!newsfeed.pionier.net.pl!goblin1!goblin.
    stu.neva.ru!v55no1045160qtk.0!news-out.google.com!m21ni13458qta.0!nntp.google.c
    om!v55no1045151qtk.0!postnews.google.com!glegroupsg2000goo.googlegroups.com!not
    -for-mail
    Newsgroups: pl.comp.programming
    Date: Fri, 4 Jan 2019 02:15:29 -0800 (PST)
    In-Reply-To: <1...@g...com>
    Complaints-To: g...@g...com
    Injection-Info: glegroupsg2000goo.googlegroups.com; posting-host=46.186.77.192;
    posting-account=f7iIKQoAAAAkDKpUafc-4IXhmRAzdB5r
    NNTP-Posting-Host: 46.186.77.192
    References: <c...@g...com>
    <f...@g...com>
    <a...@g...com>
    <7...@g...com>
    <a...@g...com>
    <6...@g...com>
    <0...@g...com>
    <a...@g...com>
    <1...@g...com>
    <e...@g...com>
    <6...@g...com>
    <1...@g...com>
    <2...@g...com>
    <5...@g...com>
    <9...@g...com>
    <1...@g...com>
    User-Agent: G2/1.0
    MIME-Version: 1.0
    Message-ID: <8...@g...com>
    Subject: Re: Jaki język polecić początkującemu? - komentarz do artykułu w
    Programista 9/2018
    From: g...@g...com
    Injection-Date: Fri, 04 Jan 2019 10:15:30 +0000
    Content-Type: text/plain; charset="UTF-8"
    Content-Transfer-Encoding: quoted-printable
    Xref: news-archive.icm.edu.pl pl.comp.programming:213163
    [ ukryj nagłówki ]

    W dniu piątek, 4 stycznia 2019 09:20:17 UTC+1 użytkownik Maciej Sobczak napisał:
    > > A teraz inny przykład:
    > >
    > > int g(int x) {
    > > return x + 2;
    > > }
    > >
    > > Jaką wartość ma wyrażenie g(5)?
    > > Na to pytanie odpowiesz bez problemu.
    >
    > Tak.
    >
    > > Nie będziesz musiał zadawać dodatkowego pytania
    > > w rodzaju "jaka była poprzednia wartość tego wyrażenia?".
    >
    > Ale to jest bardzo dobre pytanie w przypadku maszyn stanów, ogólnie. Żeby wiedzieć,
    jaki będzie następny stan, trzeba wiedzieć, jaki był poprzedni. Właściwie jest to
    pytanie, którego nie da się uniknąć. Albo unikanie tego pytania będzie prowadziło do
    niepotrzebnych kosztów i komplikacji systemu.
    > Świat rzeczywisty bardzo dobrze modeluje się maszynami stanów.

    Maszyny stanów bardzo dobrze modeluje się czystymi funkcjami.

    > > I to właśnie brak tego rodzaju pytań sprawia, że
    > > ten model jest prostszy.
    >
    > Bo problem jest prostszy.

    Tak. I ja właśnie o tym mówię: jeżeli mamy prostsze problemy,
    to korzystanie ze środków, które są potrzebne do radzenia sobie
    z bardziej złożonymi problemami jest błędem.
    (Kiedyś słyszałem określenie "principle of least power")

    > Ale weźmy inny przykład - dowolną implementację funkcji skrótu, np. CRC albo inne
    MD5. Choćby takie coś:
    >
    > https://codereview.stackexchange.com/questions/16387
    2/md5-implementation-in-c11
    >
    > Nie mam pojęcia, czy to jest poprawne ani ile złych nawyków tam jest. Chodzi o coś
    innego - o wykorzystanie operacji przypisania jako naturalnego mechanizmu dochodzenia
    w wielu etapach (być może iteracjach) do właściwej wartości końcowej. To jest inny
    model, niż Twoje wyrażenia gotowe do podstawień, ale jest on częsty w realnych
    problemach. Tam w środku po prostu jest maszyna stanów. To jest przykład funkcji,
    która jako całość nie korzysta ze stanu globalnego ani statycznego i nie trzeba tam
    pytać, jaka była poprzednia wartość. Używając nomenklatury języków funkcjonalnych,
    funkcja MD5 jest "czystą funkcją". Czyli taka funkcja spełnia Twoje kryterium
    prostszego modelu.
    >
    > Ale jakoś implementacja takiej funkcji z użyciem operatorów przypisania jest
    bardziej naturalna, niż bez nich. Tak bardzo, że implementacji bez operatorów
    przypisania w ogóle nigdzie nie znalazłem (nie żebym jakoś mocno szukał[*]).
    > Czy w celu podparcia swoich dotychczasowych tez podjąłbyś wyzwanie napisania takiej
    funkcji bez przypisań?

    Mógłbym się podjąć, gdyby problem był dla mnie interesujący.
    Akurat liczenie MD5 w obecnej chwili nie jest takim problemem.

    > > Używanie statycznych zmiennych w obrębie funkcji nie jest
    > > niszowe. W niektórych sytuacjach jest użyteczne.
    >
    > Więc dlaczego taką możliwość krytykujesz? Czy nie lepiej jest taką możliwość mieć
    (i nie korzystać gdy nie jest potrzebna), niż nie mieć?

    Nie krytykuję tej możliwości.
    Krytykuję korzystanie z tej możliwości wtedy, kiedy nie jest to
    konieczne.

    > > > Czy to znaczy, że taki program jest równie dobry, jak program, w którym
    przypisań nie ma?
    > >
    > > Nie rozumiem pytania.
    >
    > Krytykujesz operacje przypisania jako zły nawyk albo konstrukcję niepotrzebną i
    nadmiarową. Tak przynajmniej rozumiem ten (pod)wątek.

    Nie. Krytykuję stosowanie operacji przypisania tam, gdzie można
    tego uniknąć, jako zły nawyk.
    Na początku dyskusji podałem link do swojego wpisu na Quorze,
    w którym odnosiłem się do implementacji algorytmu A* w C++.

    Autorzy krytykowanego fragmentu kodu mieli jakieś dwie globalne
    tablice, w których coś tam trzymali. Dzięki temu interfejs użycia
    funkcji, oprócz argumentów, obejmował inicjalizację zewnętrznych
    globalnych struktur danych. Jest to jedna z gorszych rzeczy
    dla modularności, jakie można zrobić. I jest to kwestia wyłącznie
    złego nawyku.

    Podobnie złym nawykiem jest stosowanie arbitralnych kodowań, które
    było zarówno w prezentowanym kodzie, jak i w skrytykowanej przeze
    mnie książce Stroustrupa (który gdzieś tam sobie wymyśla, żeby
    używać znaczku '8' do reprezentowania czegoś tam)

    Jak sam zauważyłeś, interfejs do kodu liczącego MD5 jest czystą
    funkcją (nawet jeśli pod spodem znajduje się jakaś maszyna stanów).

    I to jest dobry nawyk, że nawet jeśli w implementacji czegoś
    użyjesz jakichś stanów, to nie wypychasz tego do użytkownika.

    AK tutaj równolegle do nas napisał coś takiego:

    from itertools import count, islice

    N = 15000

    pierwsze = []
    def jest_pierwsza(liczba, pierwsze=pierwsze):
    czy_pierwsza = all(liczba % pierwsza for pierwsza in pierwsze)
    if czy_pierwsza: pierwsze.append(liczba)
    return czy_pierwsza

    pierwsze = (liczba for liczba in count(2) if jest_pierwsza(liczba))
    pierwszeN = (liczba for liczba in islice(pierwsze, N))
    kwadraty = (liczba**2 for liczba in pierwszeN)
    suma = sum(kwadraty)

    print(suma)

    Jak widać, jest tutaj sobie globalna tablica o nazwie "pierwsze",
    która gdzieś tam jest modyfikowana. W takim małym przykładzie
    może nie jest to szkodliwe, ale przy budowaniu większych systemów
    już tak.

    Bardzo dużo widziałem kursów programowania, które skupiają się
    na małych przykładach, które przy próbie skalowania powodowałyby
    chaos.

    > Natomiast ja się z taką tezą nie zgadzam i próbuję wykazać, że model programowania
    z przypisaniami (ogólnie: imperatywny) jest nie tylko wartościowy, ale często po
    prostu optymalny i nie tylko dlatego, że odzwierciedla działanie komputera, ale
    dlatego, że właściwie odzwierciedla postawiony problem.

    Jeżeli właściwie odzwierciedla postawiony problem, to w porządku.


    > Dlatego oczekuję od języka programowania, że będzie to wspierał jako podstawową
    operację i konsekwentnie odrzucam języki, które tego nie mają, jako niepraktyczne.

    W porządku. Używaj sobie czego chcesz. To Twoja sprawa.
    Ja natomiast mówię o perspektywie innej, niż Twoja.
    Pytanie postawione w wątku brzmi "jaki język polecić początkującemu".
    Operator przypisania w językach takich jak C czy Python jest
    łatwo dostępny, i sprawia wrażenie, że jest prostą operacją.

    Brutalna rzeczywistość jest jednak taka, że używanie operatora
    przypisania stwarza możliwość do popełnienia wielu błędów,
    i właśnie z tego powodu w pierwszych dwóch rozdziałach SICP
    nie znajdziesz ani jednego użycia tego operatora, a kiedy wreszcie
    zostaje wprowadzony, jest obwarowany ostrzeżeniami i przykładami
    problemów, które może powodować. (I nie ma to najmniejszego
    związku z językiem Scheme)

    I nie, nie chodzi o to, żeby nigdy nie używać przypisania.

    Pomijam kwestię, że dla osób, które uczyły się matematyki, zapis
    w rodzaju
    x = x + 1
    jest po prostu równaniem pozbawionym rozwiązań, zaś jedynym
    rozwiązaniem formuły
    x = 2 * x;
    jest x = 0.

    > [*] No dobra, znalazłem:
    >
    > http://hackage.haskell.org/package/cryptohash-md5
    >
    > "The implementation is made in C with a haskell FFI wrapper that hides the C
    implementation."
    >
    > No tak. Tak było chyba *praktyczniej*, prawda?

    No najwidoczniej tak.

    > Ale jest też wersja dla "purystów":
    >
    > http://hackage.haskell.org/package/pureMD5-2.1.3/src
    /Data/Digest/Pure/MD5.hs
    >
    > Totalna masakra. Nie chcę też nawet pytać, co tam robią słowa "unsafe" i czy z
    takimi słowami to na pewno nadal jest "pure".
    >
    > W skrócie: uciekanie od imperatywności jest sztuczne i szkodzi zdrowiu.

    Jak kiedyś będę miał więcej czasu, to może przyjrzę się temu zagadnieniu bliżej.
    (Ogólnie wygląda mi na to, że ten przykład powinien się dobrze nadawać
    do wyrażenia w postaci funkcyjnej)

Podziel się

Poleć ten post znajomemu poleć

Wydrukuj ten post drukuj


Następne wpisy z tego wątku

Najnowsze wątki z tej grupy


Najnowsze wątki

Szukaj w grupach

Eksperci egospodarka.pl

1 1 1

Wpisz nazwę miasta, dla którego chcesz znaleźć jednostkę ZUS.

Wzory dokumentów

Bezpłatne wzory dokumentów i formularzy.
Wyszukaj i pobierz za darmo: