eGospodarka.pl
eGospodarka.pl poleca

eGospodarka.plGrupypl.comp.programming › Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
Ilość wypowiedzi w tym wątku: 160

  • 61. Data: 2019-01-04 09:20:16
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: Maciej Sobczak <s...@g...com>

    > 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.

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

    Bo problem jest prostszy.
    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ń?

    > 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ć?

    > > 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. 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. 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.

    [*] 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?

    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.

    --
    Maciej Sobczak * http://www.inspirel.com


  • 62. Data: 2019-01-04 09:40:14
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: g...@g...com

    W dniu piątek, 4 stycznia 2019 01:13:33 UTC+1 użytkownik fir napisał:
    > > Ogólnie derywację tego programu mam dość dogłębnie opisaną
    > > w pierwszym rozdziale "Pamphletu":
    > > https://github.com/panicz/pamphlet/raw/master/pamphl
    et.pdf
    > >
    > > W praktyce zapisałbym go raczej np. tak (jeżeli język
    > > wspierałby leniwą ewaluację):
    > >
    > > (sum (map square (initial 7 (only prime? numbers))))
    > >
    > > gdzie "map", "only" i "initial" są zdefiniowane tak:
    > >
    >
    > jakos nie wyglada mi to na prostsze niz wersja w c

    To nie jest tylko kwestia "wyglądania".
    Do zrozumienia tego kodu wystarczy stosować rozumowanie
    "podstawieniowe", które wcześniej pokazałem.
    Do zrozumienia Twojego kodu w C oprócz podstawienia (które też
    jest potrzebne, bo zdefiniowałeś funkcję z parametrem) trzeba
    też rozumieć takie rzeczy, jak przepływ sterowania albo
    operator przypisania.

    > a co to jest tam wyzej sum square (inty?) prime? (funkcja?) i numbers (???)

    jak mamy wyrażenie
    (sum (map square (initial 7 (only prime? numbers))))

    to sygnatury typów będą następujące:

    sum :: Num a => [a] -> a

    oznacza to, że funkcja "sum" bierze listę elementów o jakimś typie
    numerycznym (czyli takim, dla którego zdefiniowany jest operator dodawania)
    i zwraca element numeryczny. Operator :: czytamy jako "jest typu".
    Rzeczy po lewej stronie operatora "=>" to tzw. "ograniczenia typów",
    zaś to po prawej jest już konkretną sygnaturą. [a] oznacza listę elementów
    typu a.

    map :: (a -> b) -> [a] -> [b]

    map jest funkcją, która pobiera jakąś funkcję jednoargumentową
    oraz listę elementów, do których można zastosować tę funkcję,
    i zwraca listę elementów typu wynikowego funkcji.

    Warto zwrócić uwagę, że choć nasza percepcja jest taka, że "map" jest
    funkcją dwuargumentową, z sygnatury typów możemy wyczytać, że jest to
    funkcja pobierająca jakiś argument (funkcję) i zwracająca funkcję
    pobierającą jakiś argument (listę), czyli - mówiąc w pewnym uproszczeniu
    wszystkie wieloargumentowe funkcje w Haskellu są tak naprawdę jednoargumentowymi
    funkcjami zwracającymi funkcje (ten ficzer nosi nazwę "Currying",
    albo - jak chciała polska tłumaczka książki "Język C++" Stroustrupa
    - "doprawianie" (!))

    Funkcji square nie definiowaliśmy, ale jej definicja będzie taka:

    square x = x * x

    a sygnatura typów to oczywiście

    square :: Num a => a -> a

    (czyli funkcja, która bierze coś numerycznego i zwraca coś numerycznego
    tego samego typu).

    initial :: Int -> [a] -> [a]

    Funkcja only pobiera predykat (czyli funkcję zwracającą wartość Boolowską)
    i listę elementów, do których ten predykat daje się zastosować, i zwraca
    "pomniejszoną" listę elementów:

    only :: (a -> Bool) -> [a] -> [a]

    Warto zwrócić uwagę, że system typów Haskella nie pozwala wyrazić tego,
    że wynik funkcji jest "pomniejszony" (ale są języki, takie jak Idris
    czy Liquid Haskell, w których tego rodzaju własności daje się wyrazić
    w sygnaturze typów)

    Wreszcie, numbers to po prostu lista liczb całkowitych:

    numbers :: [Int]

    > nie wyglada to na prostsze od c (dlugie jakies)

    Funkcje "only", "map" i "initial" są już predefiniowane.
    (tylko "only" nosi tak naprawdę nazwę "filter", a "initial" -- "take").
    Ty w C użyłeś np. operatora "for" bez podawania jego definicji
    (czego w C zresztą i tak nie dałoby się zrobić).

    Gdyby korzystać z gotowych funkcji, i nie chcieć definiować np.
    square, to (zakładając dostępność funkcji isPrime) cały program
    wyglądałby tak:

    foldr (+) 0 (map (^2) (take 7 (filter isPrime [2 ..])))

    Warto przy tej okazji powiedzieć nieco o rodzinie funkcji fold.
    Zasadnicza idea jest taka, że

    fold (*) [a,b,c,d] = a * b * c * d

    Jednak powyższe sformułowanie jest niejednoznaczne, bo prawą
    stronę można interpretować jako

    (a * (b * (c * d)))

    albo jako

    (((a * b) * c) * d)

    albo jako

    ((a * b) * (c * d))

    W praktyce Haskell daje dwie funkcje, foldl i foldr, które
    działają w taki sposób:

    foldl (*) e [a,b,c,d] = (((e * a) * b) * c) * d
    foldr (*) e [a,b,c,d] = a * (b * (c * (d * e)))

    Dodatkowy parametr e sprawia, że funkcje mają sensowną wartość
    również dla listy pustej, i rozluźnia nieco wymagania narzucane
    na operator (*).

    (Oczywiście, (*) niekoniecznie oznacza tutaj mnożenie, ale
    dowolny operator dwuargumentowy)

    > a w to ze to bedzie tak szybkie tez nie do konca wierze

    Informatyka to nie jest religia. Jak w coś nie wierzysz, to możesz
    sprawdzić. (Tzn. ściśle rzecz biorąc pewnie nie będzie "tak szybkie",
    bo Haskellowy runtime ma jakieś tam dodatkowe narzuty)

    > przydaloby sie jednak by bylo choc prostsze a nie wyglada

    Moim zdaniem jest tak proste, jak tylko się da.

    > sam ten kod w c chyab w sumie mozna napisac prsciej
    >
    >
    > int PoliczSumeParuPoczatkowychLiczbPierwszych(int ilu)
    > {
    > int i = 0, dodano = 0, suma = 0;
    >
    > for(;;)
    > if(jest_liczba_pierwsza(++i))
    > {
    > suma += i*i ;
    > if(++dodano==ilu) return suma;
    > }
    > }

    Dla mnie nie jest to ani trochę prostsze od poprzedniej wersji.


  • 63. Data: 2019-01-04 10:25:33
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: AK <n...@n...net>

    On 2019-01-04 02:00, AK wrote:
    > W Pythonie wyglada ona np tak (pisane "z palca" o 15 min:):
    >
    > from itertools import count, islice
    Autopoprawka polepszajaca:
    from math import sqrt
    [...]
    erasto = int(sqrt(liczba) + 0.5)
    czy_pierwsza = all(liczba % pierwsza for pierwsza in pierwsze
    if pierwsza <= erasto)

    AK


  • 64. Data: 2019-01-04 11:15:29
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: g...@g...com

    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)


  • 65. Data: 2019-01-04 12:50:34
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: AK <n...@n...net>

    On 2019-01-04 10:25, AK wrote:
    > On 2019-01-04 02:00, AK wrote:
    >> W Pythonie wyglada ona np tak (pisane "z palca" o 15 min:):
    >>
    >> from itertools import count, islice
    > Autopoprawka polepszajaca:

    Co nagle to po diable. Tu wersja jeszcze badziej ulepszona:

    from itertools import count, islice, chain
    from math import sqrt

    N = 15000

    pierwsze = [2]
    def jest_pierwsza(liczba, pierwsze=pierwsze):
    erasto = int(sqrt(liczba) + 0.5)
    czy_pierwsza = all(liczba % pierwsza for pierwsza in pierwsze if
    pierwsza <= erasto)
    if czy_pierwsza: pierwsze.append(liczba)
    return czy_pierwsza

    pierwsze = chain([2], (liczba for liczba in count(3, step=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)

    AK


  • 66. Data: 2019-01-04 13:29:59
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: g...@g...com

    W dniu piątek, 4 stycznia 2019 02:00:15 UTC+1 użytkownik AK napisał:
    > On 2019-01-03 21:51, fir wrote:
    > >
    > > w c taki programik nie wyglada zbyt tragicznie
    > >
    > >
    > > int PoliczSumeParuPoczatkowychLiczbPierwszych(int ilu)
    > > {
    > >
    > > int dodano_pierwszych =0;
    > > int suma = 0;
    > >
    > > for(int i=0;;i++)
    > > {
    > > if(jest_liczba_pierwsza(i))
    > > {
    > > suma+=i*i;
    > > dodano_pierwszych++;
    > > if(dodano_pierwszych==ilu) return suma;
    > > }
    > > }
    > > }
    > >
    >
    > Jakto nie? Koszmar po prostu.

    Szkoda czasu na dyskutowanie o gustach.

    > > to ze nie wydziela on etapow na podej pierwsze, podnies do kwadratu zsumuj wynika
    raczej z tego ze
    > > pisze sie to tak by dzialalo szybko.. jak ktos sie nie upiera by bylo tak szybko
    moze podzielic
    > > na te fazy
    >
    > Ciezki niereformowalny betonie (zakalo tej grupy):

    Chyba nie ma potrzeby zwracania się do siebie w taki sposób.
    Za coś takiego nie daję szacunku.

    > Wbij sobie do twego asemblerowatego lba ze mozna i szybko i z
    > eleganckim rozdzialem na etapy.
    > Oczywiscie w porzdiejzych jezykach od tego syfu C/C++.
    > W dodatku wcale nie funkcyjnych, bo to raczez nie stricte funkcyjnosc
    > jezyka jest zrodlem sukcesu, ale cos co w C++ nie wystepuje, a zwie
    > sie generateory/wyrazenia generatorowe.
    > Idea znana od dziesiecioleci (ale nie Ayatollahom C/C++).
    >
    > W Pythonie wyglada ona np tak (pisane "z palca" o 15 min:):

    Nawet w Pythonie została dodana dość późno.

    > 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)

    w Haskellu chyba zwięźlej:

    sieve (first:rest) = first:(sieve [x | <- rest, x `mod` first /= 0])
    primes = sieve [2 ..]

    -- nie chcemy wypisać "primes", bo jest ich nieskończenie wiele,
    -- dlatego weźmiemy pierwszych 7:
    take 7 primes -- dostajemy [2,3,5,7,11,13,17]

    -- zaś cały przykład to będzie:
    foldr (+) 0 (map (^2) (take 7 primes))

    -- albo jak ktoś nie lubi nawiasów
    foldr (+) 0 $ map (^2) $ take 7 primes

    > No to teraz czekam palancie az usyskasz cos chocby zblizonego
    > w C (w C++ jest latwiej, ale bez zewnetrzych bibliotek
    > "metaprogramowania" sie nei obejdze, a i ta bedzie to potworek
    > w stosunku do w/w w Pythonie.
    >
    > PS: Od lat 90tych istnieje jezyk w ktorym w/w bedzie jeszcze
    > prostrze/czytelniejsze (o ktorym oczywiscie tez nie masz pojecia,
    > jak kazdy"zakochany" w bitach:) i ktory wcale nie jest funkcyjny,
    > ale jak najbardziej (jak i Python) imperatywny (zwal jak zwal).

    Jaki język masz na myśli?
    Ogólnie określenia "język funkcyjny" czy "język imperatywny"
    nie są zbyt użyteczne.
    W Haskellu można programować imperatywnie. W C można programować
    funkcyjnie. To nie język, ale to, w jaki sposób go używamy,
    jest kluczowe.

    (No może są wyjątki. Na przykład język szablonów C++ jest czysto funkcyjny,
    a asembler x86 jest czysto imperatywny)

    > Sam se napisz leniu i niedouku!

    Nie wiem co ma wynikać z rzucania tego rodzaju określeniami.

    Jak ktoś mówi, że chciałby coś zobaczyć, to pewnie adresuje
    swoją wypowiedź do kogoś, kto mu to może pokazać.

    W czym problem?


  • 67. Data: 2019-01-04 13:34:49
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: fir <p...@g...com>

    W dniu piątek, 4 stycznia 2019 09:40:16 UTC+1 użytkownik g...@g...com napisał:
    > W dniu piątek, 4 stycznia 2019 01:13:33 UTC+1 użytkownik fir napisał:
    > > > Ogólnie derywację tego programu mam dość dogłębnie opisaną
    > > > w pierwszym rozdziale "Pamphletu":
    > > > https://github.com/panicz/pamphlet/raw/master/pamphl
    et.pdf
    > > >
    > > > W praktyce zapisałbym go raczej np. tak (jeżeli język
    > > > wspierałby leniwą ewaluację):
    > > >
    > > > (sum (map square (initial 7 (only prime? numbers))))
    > > >
    > > > gdzie "map", "only" i "initial" są zdefiniowane tak:
    > > >
    > >
    > > jakos nie wyglada mi to na prostsze niz wersja w c
    >
    > To nie jest tylko kwestia "wyglądania".
    > Do zrozumienia tego kodu wystarczy stosować rozumowanie
    > "podstawieniowe", które wcześniej pokazałem.
    > Do zrozumienia Twojego kodu w C oprócz podstawienia (które też
    > jest potrzebne, bo zdefiniowałeś funkcję z parametrem) trzeba
    > też rozumieć takie rzeczy, jak przepływ sterowania albo
    > operator przypisania.
    >
    > > a co to jest tam wyzej sum square (inty?) prime? (funkcja?) i numbers (???)
    >
    > jak mamy wyrażenie
    > (sum (map square (initial 7 (only prime? numbers))))
    >
    > to sygnatury typów będą następujące:
    >
    > sum :: Num a => [a] -> a
    >
    > oznacza to, że funkcja "sum" bierze listę elementów o jakimś typie
    > numerycznym (czyli takim, dla którego zdefiniowany jest operator dodawania)
    > i zwraca element numeryczny. Operator :: czytamy jako "jest typu".
    > Rzeczy po lewej stronie operatora "=>" to tzw. "ograniczenia typów",
    > zaś to po prawej jest już konkretną sygnaturą. [a] oznacza listę elementów
    > typu a.
    >
    > map :: (a -> b) -> [a] -> [b]
    >
    > map jest funkcją, która pobiera jakąś funkcję jednoargumentową
    > oraz listę elementów, do których można zastosować tę funkcję,
    > i zwraca listę elementów typu wynikowego funkcji.
    >
    > Warto zwrócić uwagę, że choć nasza percepcja jest taka, że "map" jest
    > funkcją dwuargumentową, z sygnatury typów możemy wyczytać, że jest to
    > funkcja pobierająca jakiś argument (funkcję) i zwracająca funkcję
    > pobierającą jakiś argument (listę), czyli - mówiąc w pewnym uproszczeniu
    > wszystkie wieloargumentowe funkcje w Haskellu są tak naprawdę jednoargumentowymi
    > funkcjami zwracającymi funkcje (ten ficzer nosi nazwę "Currying",
    > albo - jak chciała polska tłumaczka książki "Język C++" Stroustrupa
    > - "doprawianie" (!))
    >
    > Funkcji square nie definiowaliśmy, ale jej definicja będzie taka:
    >
    > square x = x * x
    >
    > a sygnatura typów to oczywiście
    >
    > square :: Num a => a -> a
    >
    > (czyli funkcja, która bierze coś numerycznego i zwraca coś numerycznego
    > tego samego typu).
    >
    > initial :: Int -> [a] -> [a]
    >
    > Funkcja only pobiera predykat (czyli funkcję zwracającą wartość Boolowską)
    > i listę elementów, do których ten predykat daje się zastosować, i zwraca
    > "pomniejszoną" listę elementów:
    >
    > only :: (a -> Bool) -> [a] -> [a]
    >
    > Warto zwrócić uwagę, że system typów Haskella nie pozwala wyrazić tego,
    > że wynik funkcji jest "pomniejszony" (ale są języki, takie jak Idris
    > czy Liquid Haskell, w których tego rodzaju własności daje się wyrazić
    > w sygnaturze typów)
    >
    > Wreszcie, numbers to po prostu lista liczb całkowitych:
    >
    > numbers :: [Int]
    >
    > > nie wyglada to na prostsze od c (dlugie jakies)
    >
    > Funkcje "only", "map" i "initial" są już predefiniowane.
    > (tylko "only" nosi tak naprawdę nazwę "filter", a "initial" -- "take").
    > Ty w C użyłeś np. operatora "for" bez podawania jego definicji
    > (czego w C zresztą i tak nie dałoby się zrobić).
    >
    > Gdyby korzystać z gotowych funkcji, i nie chcieć definiować np.
    > square, to (zakładając dostępność funkcji isPrime) cały program
    > wyglądałby tak:
    >
    > foldr (+) 0 (map (^2) (take 7 (filter isPrime [2 ..])))
    >

    to juz lepiej... w ym widze jakis wiekszy sens
    trzebbylo zaczac od tego, bo trzeba przyznac ze kolegi zdolnosci tlumaczenia spraw
    przypominaja zdolnosci tlumaczacego-inwalidy

    kolega moze tgo nie widzi ale to powoduje ze ja np rozumiem reakcje ludzi na to co
    wuglada jako strumien bzdetów dlatego ze jest zle pisane (zamiast podwac fakty
    kluczowe i prosto kolega wypisuje te niektuczowe w inwalidzki sposob i predzej mozna
    sie nabawic urazy do jezykow funkcyjnych czytajac to niz przeciwnie

    - bo pamietam kiedys sam zajrzalem na jakis tutorial do lispa i nie wygladalo to tak
    zle jak w wydaniu kolegi, tyle ze czego tam sie nauczylem i tak w czesci zapomnielem)



    > Warto przy tej okazji powiedzieć nieco o rodzinie funkcji fold.
    > Zasadnicza idea jest taka, że
    >
    > fold (*) [a,b,c,d] = a * b * c * d
    >
    > Jednak powyższe sformułowanie jest niejednoznaczne, bo prawą
    > stronę można interpretować jako
    >
    > (a * (b * (c * d)))
    >
    > albo jako
    >
    > (((a * b) * c) * d)
    >
    > albo jako
    >
    > ((a * b) * (c * d))
    >
    > W praktyce Haskell daje dwie funkcje, foldl i foldr, które
    > działają w taki sposób:
    >
    > foldl (*) e [a,b,c,d] = (((e * a) * b) * c) * d
    > foldr (*) e [a,b,c,d] = a * (b * (c * (d * e)))
    >
    > Dodatkowy parametr e sprawia, że funkcje mają sensowną wartość
    > również dla listy pustej, i rozluźnia nieco wymagania narzucane
    > na operator (*).
    >
    > (Oczywiście, (*) niekoniecznie oznacza tutaj mnożenie, ale
    > dowolny operator dwuargumentowy)
    >
    > > a w to ze to bedzie tak szybkie tez nie do konca wierze
    >
    > Informatyka to nie jest religia. Jak w coś nie wierzysz, to możesz

    alez debilna wypowiedz... kolega powinien uwazac bo czasami osiaga poziom quelqebuga
    czy innego talatajstwa a na tym poziomie ja nie moge rozmawiac

    religie nie jest oparta na niewierzeniu,
    religie jest oparta na wierze; to pierwsze to wrecz cos dokladnie przeciwnego i jest
    to raczej wyraz sceptyzyzmu wobec wiary... jesli kolredze sie trafiaja takie babole w
    wypowiedziach
    to ostroznosc wobec przyjomania tych tekstow choc i tak wygladaja one nieco
    podejrzanie jako rozumny przekaz staje sie tym bardziej uzasadniona... i ogolnei
    zachodzi pytanie czy kolega bardzij mowi z sensem czy bardziej truje ludzi
    bulszitem... (najprawdopodobniej jest to pewien mix ale z miksami bywa tak ze
    domieszka bulshitu moze powodowac ze czytanie calosci jest bardziej stratnie niz
    korzystne ;c)

    ogolnie nietstsy rozmawianie z takimi ludzmi jest dosyc tragiczne



    > sprawdzić. (Tzn. ściśle rzecz biorąc pewnie nie będzie "tak szybkie",
    > bo Haskellowy runtime ma jakieś tam dodatkowe narzuty)
    >
    > > przydaloby sie jednak by bylo choc prostsze a nie wyglada
    >
    > Moim zdaniem jest tak proste, jak tylko się da.
    >
    > > sam ten kod w c chyab w sumie mozna napisac prsciej
    > >
    > >
    > > int PoliczSumeParuPoczatkowychLiczbPierwszych(int ilu)
    > > {
    > > int i = 0, dodano = 0, suma = 0;
    > >
    > > for(;;)
    > > if(jest_liczba_pierwsza(++i))
    > > {
    > > suma += i*i ;
    > > if(++dodano==ilu) return suma;
    > > }
    > > }
    >
    > Dla mnie nie jest to ani trochę prostsze od poprzedniej wersji.

    no cos, mogłbym wspolczuc ale mi sie nie chce... obecnie zastanawiam sie czy kolega
    ma jakas dysfunkcje mozgu i poprostu lubi lispa czy tez moze nauka lispa wywolala ta
    dysfunkcje czy cos w tym stylu

    samo to w sobie nie bylo by takie zle ale jesli kolega czestuje ta dysfunkcjonalnosci
    ainnych to juz jest pewien trolling (tak to nazwijmy, nie uzwywam zbyt dopasowanych
    okreslen bo
    nie che tracic czasu na te glupie gadki)


    normalny czlowiek moim zdaniem nie powinien miec problemow z rozumieniem na czym
    polega c,
    zgadza sie ze jezyk c jest w pewnym sensie kryptyczny i ze w pewnym sensie jest to
    zle... kwestia jest jednak tak ze
    c powstal przy okreslonych zalozeniach,
    c nie tylko ma wyrazac zapis jakiegos tam taska do wykonania ale umozliwic zapis w
    sposob odwolujacy sie do pewnego typu elementarnych operacji natywnych dla maszyny (o
    czym chyba kazdy powinien wiedziec) i w tym sensie taki programik
    jak wyzej jest naprawde lekki jest to pare instrukcji asemblera na krzyz, wyrazone w
    postaci programu w c

    c jest wlasnie do tego i tutaj lisp nie ma z c szans

    zaznaczam ze do lispa nic nie mam, mam problem jednak z chrzanieniem - kolaga ma
    powazny z tym problem, bierze jakas tematyke i zmieni ja w chrzanienie zamiast jednak
    psiac o tym duzo bardziej normalnie ;c


    sama ta linijka
    > foldr (+) 0 (map (^2) (take 7 (filter isPrime [2 ..])))

    jest ok, coz moge powiedziec jest to jedna z mozliwych opcji budowania jezyka
    skryptowego, ktora ma zapewne w pewnych tematach rzeczywiste zalety, w innych inne
    podejscia raczej by to przebily

    oolenie to ta linijka przypomina troche skladanie i kombinowanie programow z jakiegos
    basha (lub specyficzny sposob skladanie procedur jedna z druga:
    innymi slowy przypomina to troche specyficzny pionowy sposob pisania
    pewnych kawalkow w c

    typu

    x = limit(7)
    l = primes(l)
    l = square(l)
    z = sum(l)

    ew s = sum(square(primes(limit(7))))

    tylko wyrazony poziomo i generalizowany (byc moze w ciakawy sposob, tj ktos tam
    odwalil troche roboty by to podefiniowac),

    nie mam nic do tego ale chrzanienie zbudowane dookola tego to nie jest dobra rzecz


  • 68. Data: 2019-01-04 13:47:27
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: fir <p...@g...com>

    W dniu piątek, 4 stycznia 2019 13:30:00 UTC+1 użytkownik g...@g...com napisał:
    > > Sam se napisz leniu i niedouku!
    >
    > Nie wiem co ma wynikać z rzucania tego rodzaju określeniami.
    >
    > Jak ktoś mówi, że chciałby coś zobaczyć, to pewnie adresuje
    > swoją wypowiedź do kogoś, kto mu to może pokazać.
    >
    > W czym problem?

    aw to znany knajacki emeryt, jakas taka postac jak w tych pogramach o emertyach na
    polsacie czy tvnie, 'trudne sprawy', 'wakacje z dziadami' 'polskie wakacje' czy cos w
    tym stylu (bylo cos takiego z czego pochodizl mem o 'mięsnym jezu', te klimaty)

    niech knajaczy i zyje w zludzeniu ze ja to czytam, powyobraza to sobie pare godzin
    pozniej mu przejdzie - ja szczerze mowiac nie czytam tego bo mam duzo ciekawsze (tj
    mniej glupi) rzeczy do czytania niz tak osobliwe rozrywki jak poczytywanie knajakow w
    necie,
    szczerze mowiac to jzu czytanie kolegi troche przekracza moja wytrzymalosc na
    czytanie slabych tekstow ale jeszcze sie troche pomęcze


  • 69. Data: 2019-01-04 13:52:21
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: g...@g...com

    W dniu piątek, 4 stycznia 2019 13:47:29 UTC+1 użytkownik fir napisał:
    > W dniu piątek, 4 stycznia 2019 13:30:00 UTC+1 użytkownik g...@g...com
    napisał:
    > > > Sam se napisz leniu i niedouku!
    > >
    > > Nie wiem co ma wynikać z rzucania tego rodzaju określeniami.
    > >
    > > Jak ktoś mówi, że chciałby coś zobaczyć, to pewnie adresuje
    > > swoją wypowiedź do kogoś, kto mu to może pokazać.
    > >
    > > W czym problem?
    >
    > aw to znany knajacki emeryt, jakas taka postac jak w tych pogramach o emertyach na
    polsacie czy tvnie, 'trudne sprawy', 'wakacje z dziadami' 'polskie wakacje' czy cos w
    tym stylu (bylo cos takiego z czego pochodizl mem o 'mięsnym jezu', te klimaty)
    >
    > niech knajaczy i zyje w zludzeniu ze ja to czytam, powyobraza to sobie pare godzin
    pozniej mu przejdzie - ja szczerze mowiac nie czytam tego bo mam duzo ciekawsze (tj
    mniej glupi) rzeczy do czytania niz tak osobliwe rozrywki jak poczytywanie knajakow w
    necie,
    > szczerze mowiac to jzu czytanie kolegi troche przekracza moja wytrzymalosc na
    czytanie slabych tekstow ale jeszcze sie troche pomęcze

    Mhm.
    A rozumiem, że to, co napisałeś w tym poście, to są mocne teksty?


  • 70. Data: 2019-01-04 14:01:10
    Temat: Re: Jaki język polecić początkującemu? - komentarz do artykułu w Programista 9/2018
    Od: fir <p...@g...com>

    W dniu piątek, 4 stycznia 2019 13:52:23 UTC+1 użytkownik g...@g...com napisał:
    > W dniu piątek, 4 stycznia 2019 13:47:29 UTC+1 użytkownik fir napisał:
    > > W dniu piątek, 4 stycznia 2019 13:30:00 UTC+1 użytkownik g...@g...com
    napisał:
    > > > > Sam se napisz leniu i niedouku!
    > > >
    > > > Nie wiem co ma wynikać z rzucania tego rodzaju określeniami.
    > > >
    > > > Jak ktoś mówi, że chciałby coś zobaczyć, to pewnie adresuje
    > > > swoją wypowiedź do kogoś, kto mu to może pokazać.
    > > >
    > > > W czym problem?
    > >
    > > aw to znany knajacki emeryt, jakas taka postac jak w tych pogramach o emertyach
    na polsacie czy tvnie, 'trudne sprawy', 'wakacje z dziadami' 'polskie wakacje' czy
    cos w tym stylu (bylo cos takiego z czego pochodizl mem o 'mięsnym jezu', te klimaty)
    > >
    > > niech knajaczy i zyje w zludzeniu ze ja to czytam, powyobraza to sobie pare
    godzin pozniej mu przejdzie - ja szczerze mowiac nie czytam tego bo mam duzo
    ciekawsze (tj mniej glupi) rzeczy do czytania niz tak osobliwe rozrywki jak
    poczytywanie knajakow w necie,
    > > szczerze mowiac to jzu czytanie kolegi troche przekracza moja wytrzymalosc na
    czytanie slabych tekstow ale jeszcze sie troche pomęcze
    >
    > Mhm.
    > A rozumiem, że to, co napisałeś w tym poście, to są mocne teksty?

    skad mam wiedziec co kolega naprawde rozumie... ciezko zgadnac..wyglada to szczerze
    mowiac dosyc srednio

    to teksty ktore ja napisalem nie sa
    mocne bo sa to dorazne komentarze do produkowania babolastych ogolnikow,
    (czyli czesciowo zle powyciaganych wnioskow...bo wypowiedzi kolegi moim zdaniem
    skladaja sie jakby z materialu oryginalnego (jakiejs tam wiedzy na temat lispa i
    innych aspektow programowania)
    i powyciaganych przez kolege wnioskow
    ktore sa ma zle powyciagane lub co najmniej zle uzywane i to jest juz problem, bo
    bardzo zle sie rozmawia z kims kto w wojowniczy sposob zarzyuca
    cie wnioskami blednymi lub zle uzywanymi
    tak jak kolega robi


    ja tak nie robie i to czyni moje wypowiedzi solidniejszymi ;c



strony : 1 ... 6 . [ 7 ] . 8 ... 16


Szukaj w grupach

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: