56 komentářů k článku Jiří Knesl: OOP a funkcionální programování se navzájem vylučují:

  1. tacoberu

    pure fp a pure oop
    Hodně výstižná mi přijde věta: „není možné psát souběžně čistě objektově a čistě funkcionálně.“

    Dovolím si ji dovést do extrému: Nejde psát čistě funkcionálně nikdy nikde. V žádném jazyce. Ani v Haskellu protože Monády. A psát čistě objektově sice jde, ale je to hrozně nepraktické, pracné, a nikdo to stejně neumí.

    Já jsem zvolil způsob, kdy píšu co nejvíc funkcionálně to jde, v jazyku který jsem nucen používat. Plus jsem si z OOP vzal ty nejužitečnější koncepty: api, zastupitelnost a zapouzdření (plus určitě i něco dalšího).

    No, a spousta věcí vůbec s OOP ani s FP nesouvisí, jak si sám napsal: „Funkce nezná žádné okolo (ignorujeme-li věci jako globální proměnné). Dostane parametry a vždy vrátí totéž. To není jen věc FP, tohle je slušnost i v Pascalu.“.

    1. Jiří Knesl

      Re: pure fp a pure oop
      „Nejde psát čistě funkcionálně nikdy nikde.“ to záleží, jak vnímáš pure FP. Jestli nemáš opravdu žádné side effecty, mutable stav apod. (pak by žádný program fakt napsat nešlo, nebo šlo, ale nedostal by se z něj žádný výsledek), nebo jestli je to nemít ve svém programu. Tzn. pokud oddělíš ne-pure-FP runtime a tvůj pure-FP program, který ten runtime využívá, pak soudím, že je možné psát čistě funkcionálně.

    2. Atamiri

      Re: pure fp a pure oop
      Monády ale čistě funkcionální jsou, alespoň v teoretické rovině, takže pokud se bavíme o konceptu a pomineme konkrétní implementace, čistě funkcionálně psát jde.

  2. v6ak

    Scala a domunantni pristup
    Zrovna u Scaly bych rekl, ze dominuje spise funkcionalni paradigma. Bylo by to krasne videt napriklad na Play frameworku. Doporucuje se pristup: Dokud muzes, bud radsi funkcionalni, ale nepouzivej monady apod. jen abys zustal funkcionalni. A ostatne v clanku uvedene pouziti metody (ano, metody…) map taky napovida, ze bude dominovat fuincionalni paradigma. Ta imperativni verze mi ve Scale prijde dost exoticka.

    Jako typicka ukazka objektoveho pristupu s nadechem funkcionalniho mi prijde Ruby s Rails.

    (Samozrejme, muzu kterykoli z techto jazyku vzit a pouzit jinak, nez je mainstream.)

    (BTW, davat takove side effects do metody map je hnus. Kdyz uz musim, tak ne map, ale foreach.)

    1. Jiří Knesl

      Re: Scala a domunantni pristup
      Nemám přehled o tom, jak vypadá mainstreamové použití Scaly, ale z meetupů s Scalisty mi přišlo, že jsou to objektoví vývojáři, kteří používají zatím Scalu jako lepší Javu a postupně nakukují i do světa FP. Ale jsou výjimky a najdou se Scalisti, kteří ten jazyk používají podobně jako Haskell, jen já je osobně nepotkal.

      U toho zdrojáku jsem musel použít map, protože ty usery vracím a mám novou kolekci.

      1. v6ak

        Re: Scala a domunantni pristup
        Byl jsem na pár (asi dvou) meetupech v Brně a mám pocit, že relativně velká část byli nováčci, kteří šli z Javy. Takže přirozeně budou používat přístup „lepší Java“. (No offense, taky jsem tak začínal.) Plus tu mohlo být pár typicky imperativních témat jako actory.

        Já mám přehled spíš o tom, jak píšou kód autoři různých knihoven (včetně Play frameworku, který je dnes pod LightBendem) a jak ho píšu já. V Play 2 si neušpiníš ruce imperativním kódem, pokud nemusíš (typicky databáze), ledaže bys chtěl. U asynchronního přístupu (např. reactive streams) je tu taky snaha být maximálně deklarativní.

        Z toho všeho mi Scala přijde spíš jako „Haskell bez monád“ než jako „lepší Java“. Akorát asi hodnotíme podle jiného vzorku.

        Z tomu zdrojáku: Sice mám novou kolekci, ale v čem se bude lišit od té předchozí?

  3. v6ak

    Ciste objektovy pristup
    Zminene vygenerovani faktury IMHO lze udelat ciste objektove. Proste objektu tridy User reknu, at mi kousek te faktury vykresli. A on mi vykresli veci jako adresu apod. na zadane misto.

    Je to samozrejme poruseni MVC. Je tu samozrejme spousta duvodu, proc to muze byt neprakticke delat takto. Ale pokud se nahodou chceme drzet skriktne OOP (za cenu ustupku jinde), moznost tu je.

    1. Jiří Knesl

      Re: Ciste objektovy pristup
      Ano. Mnohokrát jsem nad tím uvažoval. V MVC si umím představit řešení jako „předávání šablony modelu“, tedy obrácení toho, jak se to obvykle řeší. Model pak řekne: „Dej mi render pro tato data.“ Taková implementace by ale byla hodně nestandardní a asi i dost nepraktická.

      1. x86

        Re: Ciste objektovy pristup
        Může být praktická, standardní, elegantní i užitečná – viz třeba QPainter a renderování do Svg v Qt.

  4. v6ak

    Ciste funkcionalni pristup...
    „Na úrovni strojového kódu jsou monády implementovány jako imperativní kód (stejně jako vše ostatní).“

    Pri argumentaci ohledne funkcionalniho pristupu nabizenymi komponentami jazyka radsi argumentuju vnejsim chovanim, treba absenci side effectu nebo lepe nejakou urovni referencni transparentnosti. Jinak, jak ostatne i trosku naznacujes, nebude ciste funkcionalni ani scitani Integeru, protoze z

  5. v6ak

    Re: Ciste funkcionalni pristup...
    Predcasne odeslano, sorry.

    Jinak, jak ostatne i trosku naznacujes, nebude ciste funkcionalni ani scitani Integeru, protoze za nim je nejaka imperativni instrukce procesoru.

    Ve skutecnosti to ani s tou referencni transparentnosti neni az tak jednoduche. Vezmeme si priklad String.toLowerCase() v Jave. Je to referencne transparentni?

    • Ne, protoze uvedenou substituci zmenime delku vypoctu. S takovou bychom ale nemeli nic referencne transparentniho, takze tuto vlastnost promineme.
    • Ne, protoze poprve nam to treba projde a podruhe hodi OutOfMemoryError. S timto se da poprat ruzne, ale asi tez budeme muset trosku couvnout. (Da se pak ale diskutovat napr. o tom, zda muzeme chytat OutOfMemoryError.)
    • Ne, protoze dve ruzna volani vrati dve neidenticke (byt ekvivalentni) instance Stringu. Toto by se dalo vyresit (napr. zakazat test identity), ale ja se radsim spokojim s oslabenim definice referencni transparentnosti.

    Podobne komplikovane to je i u side effects.

  6. Ondřej Novák

    hrušky jabka
    Srovnávají se hrušky s jabkama. Mohu používat OOP a přitom funkcionální styl programování. Stačí, když důsledně budu používat immutable objekty. On totiž, kdo napíše, že OOP se vylučuje s funkcionálním programování jen ukazuje, že nepochopil OOP. Sorry člověče.

    Ale co mi to ta funkce ve funkcionálním programování vrací? Objekt ne? On i základní typ je objekt. Může mít metody, dědičnost, polymorfismus. Místo aby měnila svůj vnitřní stav, může fungovat jako továrna.

    User disabledUser = user.createDisabledUser()

    Je to krásná teorie, a rozhodně se tohle hodí mít zavedeno u multithreadingu, protože odpadá většina synchronizace. I na změny sdílených immutable objektů mám cosi, čemu říkám future-stream, každý objekt kromě svého aktuálního stavu poskytuje futuru na svou budoucí změnu. Změna objektu znamená nastavení futury a každý, kdo objekt sleduje se ihned dozví, že už existuje nová verze.

    Ale jako vždy je to všechno o praktickém využití. Mít megový JSON dokument a chtít ve sedmý úrovni zanoření změnit jedno číslo abych dostal novou verzi megovýho JSONu… to rozhodně rychlosti nepřidá. Pro hromadné změny potřebujeme transakce … ehm… objekty (RIAA, atd)

    1. tacoberu

      Re: hrušky jabka

      On totiž, kdo napíše, že OOP se vylučuje s funkcionálním programování
      jen ukazuje, že nepochopil OOP. Sorry člověče.

      OK. Můžeš mi prosím vysvětlit jak pošlu zprávu nějakému objektu, kterýžto mě informuje o svém výsledku také pomocí zprávy – ale tak, aby nedocházelo k side-effectům? Přirozeně očekávám, že to bude asynchronní. Protože takto je definováno pure OOP.

      To, že nějaká funkce vrací objekt není OOP, to je jen slovíčkaření.

      1. Ondřej Novák

        Re: hrušky jabka
        Mně fascinue, jak se vždycky teoretici při kritice oboru, kterému nerozumí zabřednou v technikáliích. „Asynchroně“ nemá s OOP nic společného. Poslání zprávy může být klidně realizováno i voláním metody. Nijak to smysl OOP nenarušuje.

        Prostě „poslat zprávu“ je jen pojem vyjadřující nějakou interakci, aniž by popisovalo, jak ta interakce je realizována.

        Nevím, jaké side-efekty máte na mysli.

        1. tacoberu

          Re: hrušky jabka
          Mě fascinuje věcí.

          kód: 1 + 1 není OOP, je FP.
          kód: m += 1 není FP, ale je OOP.

          Je jasné proč. A je jasné, proč to nejde skloubit. Cokoliv mimo to nesouvisí s OOP ani s FP.

          Na asynchronnosti je zajímavé, že takto byl OOP původně navržen. A že ji do FP nenaroubuješ ani kdyby si se na hlavu postavil.

          1. Ondřej Novák

            Re: hrušky jabka
            Já to asi už chápu. Vy prostě synchronnímu volání říkáte funkcionální programován, a asynchronímu volání říkáte OOP. Že se to neslučuje asi celkem jasné. Ale já s tím prostě nesouhlasím. OOP není jen o asynchroním posílání zpráv. Já tohle chápu jen zobecnění nějaké představy.

            Jako objekt v reálném životě mohu na úřad poslat dopis se žádostí a čekat na odpověď. Nebo mohu na úřad dojít a počkat si u okénka. Jedno je poslání zprávy, druhé volání funkce (synchronní zpráva). Poznávací znamení? – to první vyžaduje, aby příjemce věděl, kam má poslat odpověď. To druhé nic takové nepotřebuje, úřednice ví, že má odpovědět tomu, kdo zrovna stojí u okénka.

            1+1 je taky OOP. 1.operator+(1). Uřednice úřadu 1 u okénka operator+ mi sdělí, že výsledkem požadavku 1 je 2.

            1. Taco

              Re: hrušky jabka

              1+1 je taky OOP. 1.operator+(1). Uřednice úřadu 1 u okénka operator+ mi sdělí, že výsledkem požadavku 1 je 2.

              A podle jaké definice je toto objektové?

              1 + 1 je ve skutečnosti, že si zajdu k úřednici úřadu 1, řeknu: „s dovolením si půjčím tady jedno +“ a předhodím mu jinej úřad? To je podle vás objektové?

              Jako jedno se vám musí uznat. Odpovídá to dnešnímu chápání většiny OOP vývojářů. Bohužel, ale ano.

        2. falken

          Re: hrušky jabka
          to je fakt, a čím větší hlouposti, tím větší expert (s vyjímkami potvrzujícími pravidlo); váš popis je přesně to co o tom jenom tuším já, i když jsem to v posledni dobe zatím ani nepotřeboval (jo, kdysi kolem 1990 jeden DOS file manager ve stylu nortonu, ArcShell se to jmenovalo, umel psat shell bat-skripty s promennymi ktere se spoustely nad mnozinou souboru/adresaru vyselektovanych pres UI (map?) – to bylo defacto funkcionalni pouziti uz tenkrat, az na to, ze tomu tak tenkrat nikdo nerikal – a bylo to naprosto super, tak super, ze jsem to pak par let hledal nekde ve windows, doufaje ze TotalCommander treba nekdy embeduje LUA a pujdou takovehle veci skriptovat, fakt rychle, ad hoc, „jako tenkjat“ … nikoliv, nestalo se; a vubec jakekoliv volani po ultra cistote mi taky evokuje nejake fasizovani, takze pryc od toho…)

        3. Jiří Knesl

          Re: hrušky jabka
          Martin Takáč (tacoberu) nejspíš odkazuje na koncept OOP, kdy se předpokládalo, že všechny objekty budou „living“, tedy souběžně běžící a komunikující prostřednictvím zpráv. Je vidět, že oba máme nastudováno víc než vy. Ale bez urážky, v ad hominem si nelibuji.

          Můžete si nastudovat některý výroky Alana Kaye (autora OOP) zde: http://mythz.servicestack.net/blog/2013/02/27/the-deep-insights-of-alan-kay/

          Zajímavá je část: „To me, one of the nice things about the semantics of real objects“, kde své vnímání naznačuje. Můžete se pokusit jeho názory vyvrátit, ale nepředpokládám, že rozumíte OOP víc než jeho autor.

          Poslání zprávy je potom operace, kdy objektu přichází na dispatch message a on rozhoduje, jak s ní naloží. Nemusí vůbec nic vrátit. Někteří vývojáři razí názor, že Actor model je právě ztělesněním OOP, jazyky jako Erlang jsou v tomto pohledu (ne-pure) OOP.

          To je přístup, který je naprosto nepochybně plný side-effectů.

            1. Jiří Knesl

              Re: hrušky jabka
              Celé je to složitější. Hoare přišel s record classami. Nic, co by ale nějaký vývojář vzal a používal to, teoretický koncept. Nydahl, Nyygard to vzali, nacpali do Simuly a vytvořili první jazyk s objektovými rysy. Jazyk pořád nebyl pure (vše je objekt). Pak Kay, Ingalls a Goldberg udělali Smalltalk, první pure-OOP jazyk (vše je objekt). Nemám problém kohokoliv z těchto lidí označit za autora OOP. Kay mi tam jako teoretik OOP přijde určitě nejvýraznější.

    2. Jiří Knesl

      Re: hrušky jabka
      Článek není o tom, že můžu používat OOP a funkcionální styl. Článek mluví o tom, že když jedno doženete do krajnosti, druhé se stane nemožným.

      Co se immutable objektů týká, pořád zůstává problém s identitou. Nám 2 samostatně vytvořené instance StringBufferu sb1, sb2, v obou string „Hello World“. Má platit sb1 == sb2? V objektových jazycích se vám toto vyhodnotí jako false, ve funkcionálních jako true.

      Ad datové struktury – např. JSON) nemusím používat copy on write přístup, existují persistentní datové struktury. Nejsou sice tak efektivní, jako mutable, ale jsou mnohem lepší než copy on write přístup.

      1. Ondřej Novák

        Re: hrušky jabka
        berete operátor == jako dotaz na to, zda jde o stejný objekt, nebo zda dva objekty jsou stejné?

        Jde o různé objekty, které vypadají stejně. Já a moje dvojče jsou stejné objekty, ale každý je samostatná entita.

        Také záleží, jak je zavedena identita objektu. Pokud jako ID dám SHA256 obsahu, pak není možné vytvořit dva objekty se stejným obsahem.

        Jiný příklad. a=new koule(červená), b=new koule(červená), (*a==*b) == true, (a==b) == false
        jsou to dva objekty, ale jsou stejné.

        Hraje to roli? Jirka a Jarda jsou dvojčata, oba vědí/umí zařídit totéž. Je tedy jedno, zda se zeptám Jirky nebo Jardy.

        1. Jiří Knesl

          Re: hrušky jabka
          Beru to tak, že FP jazyk zná jen hodnoty, ne identity. V OOP tuto otázku musíte zodpovědět.

          x = new Koule(červená)
          y = new Koule(červená)

          x == y – má být true nebo false? IMHO v OOP false, v FP true.

          x.setBarva(modrá)

          x == y – teď má být false v obojím

          A samozřejmě se mi může stát, že budu chtít vytvořit více objektů se stejnou barvou. Třeba když budu simulovat kulečník (karambol, snooker), kde mám koule stejných barev, ale každá je samostatná, má svou identitu. V mutable světě může objekt projít situací, kdy se hodnoty objektů rovnají a pak zase divergují. V FP světě je hodnota stálá a nezávislá na čase, byla tady vždy, ještě před počátkem vesmíru.

          Další důležitý aspekt, byť je to spíš o výkladu, než o jakési vědecké slučitelnosti, jsou zvyklosti vývojářů v OOP a FP světě. OOP vývojář usiluje o autonomní komponenty, které dovedou samostatně fungovat. Postarají se o sebe včetně stavu. Oddělit stav od dat by bylo považováno za projev špatného stylu (terminologií anemický model na jedné straně, feature envy na druhé). V FP je to naopak preferovaná cesta, kdy není výjimkou, že se píšou aplikace, kde celý stav aplikace napříč všemi komponentami je v 1 proměnné.

          1. Ondřej Novák

            Re: hrušky jabka
            A kde jste definoval že operace == je identita objektů?

            Vyrobil jsem si dvě koule, obě jsou červené. FP mi tedy dává špatný výsledek, pokud se ptám, zda jde o stejnou kouli. Pokud se ale ptám na to, zda koule stejně vypadá, pak je to OK. Tohle totiž vůbec nesouvisí se stylem programování ale s definicí toho, co chcete.

            setBarva – vezmu tu kouli a nabarvím ji na modro. Ve FP to znamená, že musím vyrobit novou kouli. Opět záleží na tom, co chci dělat, zda chci koule přebarvovat nebo klonovat přebarvené. OOP má hlavně odraz v reálném životě. Snaží se napodobovat tak, jak to ve světě funguje. FP se naopak snaží chovat jako matematika. Nicméně všichni v reálném světě matematiku používáme a nevylučuje se.

            Ale nikdo, opakuji, NIKDO by neměl tvrdit, že OOP neumí porovnat objekty, nebo že zprávy se musí posílat asynchroně. Ten kdo to tvrdí ve skutečnosti neví nic o objektovém programování. Možná mluví jen o úzké implementaci, třeba o smalltalku, nebo o Javě. Ale takhle já OOP nechápu a odmítám chápat. Je to totiž mnohem širší pojem, než jen omezení se na pár „pěkných“ nápadu ze smalltalku. A je mi naprosto jedno, jestli ten pohled prosazuje nějaký pan Knesl, pan Kay, nebo Bůh. Není to svaté písmo. Možná že pan Kay našel určitý směr myšlení, ale ta myšlenka se dostala mnohem dál než on sám.

            1. Jiří Knesl

              Re: hrušky jabka
              „A kde jste definoval že operace == je identita objektů?“

              Prakticky ve všech objektových jazycích to tak je. Napadá vás nějaká výjimka?

              FP nedává špatný výsledek. Ono neříká, že jsou „jedna koule“, ono říká, že ty koule jsou stejné. Když chci změnit hodnotu, nemusí vytvářet novou kouli, pokud použiju persistentní datovou strukturu. Ta je sice náročnější než mutable stav, ale není to copy on write.

              To, že OOP má odraz v reálném životě, je těžce nadužívané tvrzení. Máte pro toto tvrzení nějaké opodstatnění?

              Netvrdím, že OOP neumí porovnat objekty. Jen tvrdím, že OOP cílí na jiné věci, než FP a když se jedno dožene do extrému, popře se tím to druhé. OOP vytváří izolované jednotky, které v sobě obsahují jak stav, tak chování. FP tyto věci odděluje. OOP se snaží o zapouzření, FP nikoliv. Kód, který bude dobrý v OOP bude porušovat principy FP a naopak.

              Co se vašeho chápání OOP týká, je mi to jedno. Přidržím se toho, jak ho vnímá autor OOP. Je pro mě autorita. Vás jsem v životě neviděl, netuším, co vlastně o programování víte, četl jsem pouze vaše komentáře (s kterými nesouhlasím a které autora OOP popírají) takže se na mě nemůžete zlobit, když řeknu, že vaše vnímání OOP je zkomolené a nesprávné.

              1. Ondřej Novák

                Re: hrušky jabka
                Poslední věta mě v zásadě utvrzuje v názoru, že nerozumíte OOP. Osobně si myslím, že mu nerozumí ani jeho Autor. Osobně si nemyslím, že by nějaký autor OOP vůbec kdy existoval. Mě OOP učili na UHK v předmětu Objektové Modelování (a už to nějaký pátek bude). OOP jako způsob myšlení v softwarovém inženýrství je úplně něco jiného, než prezentuje jeho „autor“.

                „To, že OOP má odraz v reálném životě, je těžce nadužívané tvrzení. Máte pro toto tvrzení nějaké opodstatnění?“

                Samozřejmě. Tak jako svět se skládá ze samostatně fungujících entit, tak i OOP se skládá se samostatně fungujících objektů, které spolu spolupracují. Ale neznamená to, že objekty musí žít nebo mít stav. Červená koule je jen jedinečná instance, vznikne a už se nemění. Její poloha nemusí být uložena v jejím stavu (je poloha stavem koule?, podle mě nikoliv). I neživé koule se můžete ptát (jakou máš barvu?) Hlavním smyslem OOP je ale uvědomění si, že data a operace nad nimi patří k sobě. Neznamená to ovšem, že by ty data nebyly přístupné z venku, ani to, že se musí vnitřní stav měnit.

                Hlavním přínosem OOP je jednotný definice interfaců. K udržení většího projektu je třeba nadefinovat jak jednotlivé části komunikují a to lze právě pomocí interfaců. Interface pokrývá kód i data a tvoří tak objekt. Objekty v tomhle tvaru lze najít už v prvních unixech, vlastně celý shell je o objektech, kdy objektem je process, rozhraním je příkazová řádka a standardní vstup a výstup (a chybový výstup). Zobecnění toho přístupu vede na k use case diagramů, kde začíná jasné oddělení rolí a komponent a rozhraní mezi nimi.

                Pokud na FP nahlížíte jako na způsob návrhu algoritmů, kdy mám data plně oddělena od kódu (kdy se dostáváme k relačním databázím, k E-R schámatům a zpátky do minulého století), pak v tomto směru toto vidím jako slepou větev. Pokud ale dál v FP čerpáte výhody OOP (například javascript sice má na všechno funkci, a lze ta programovat funkcionálně, ale beztak si tam nakonec začnete předávat objeky), pak jste jen vzal OOP a omezil jste ho na immutable objekty a volání metod. Nemám s tím problém, ale je to sorry, pořád OOP, jen se jinak na něj díváte

                Takže a = fn(b,c) je ekvivalentni k a = b.fn(c).

                Takhle se programovalo za mě v době, kdy C++ byla vyšší dívčí a kdy jsem jsem ještě stále zůstával v ANSI C a snažil se nějak objekty simulovat, protože jsem je prostě potřeboval (aniž jsem si to uvědomoval)

                1. tacoberu

                  Re: hrušky jabka

                  Hlavním přínosem OOP je jednotný definice interfaců. K udržení většího projektu je třeba nadefinovat jak jednotlivé části komunikují a to lze právě pomocí interfaců. Interface pokrývá kód i data a tvoří tak objekt

                  Podle této definice je Haskell OOP. Kurnik, já si to myslel! :)

          2. Jirka Kosek

            Re: hrušky jabka
            Proč by x == y mělo ve funkcionálním jazyce vracet true? To přece záleží na tom, jak si nadefinuji datový model a identitu nad jeho prvky.

            Jsou x a y identické? Nejsou. Mají stejný obsah? Mají. Ve spoustě jazyků máte odlišné operátory/funkce pro porovnávání identity a samotného obsahu.

            Např. v XSLT, což je funkcionální jazyk, můžete testovat buď identitu

            $x is $y
            

            nebo jen shodu obsahu:

            deep-equals($x, $y)
            
            1. Jiří Knesl

              Re: hrušky jabka
              Vrací true proto, že func.jazyky žádné identity neřeší. Řeší jen hodnoty. Pokud se v nějakém pojmenovaném kousku paměti (který se v imperativním programování nazývá proměnná) objeví stejná data jako v druhém, tak záleží jen na těch datech.

              Ano, může se stát, že data reprezentovaná stejnými bity, ale jiného typu, budou v paměti stejná, ale na úrovni typu ne, protože jedno bude char[] a druhé string a jazyk v tomto bude vidět rozdíl. To je ale jiná situace.

              V okamžiku, kdy mám stejný typ a stejnou hodnotu, tak si troufnu říct, že není FP jazyk, kde by a == b bylo false. Opak platí pro objektové jazyky. Třeba se mýlím v tvrzení toho, že nejsou výjimky, ale v jazycích, které používá 99 % vývojářské populace, to tak je.

              1. jirkakosek

                Re: hrušky jabka
                Troufnout si můžete, ale mýlíte se. Troufám si odhadnout, že nejpoužívanější funkcionální jazyk je dnes XSLT, a tam zrovna tohle neplatí.

              2. v6ak

                Re: hrušky jabka
                Obecně identita nemá smysl v pure FP. Dokonce by nám rušila referenční integritu, pokud ji chceme chápat extrémně.

                Ekvivalence má smysl u FP i OOP, byť u FP je víc v popředí. Java má Object.equals(Object), má tedy taky ekvivalenci. A – ačkoli to kontrakt java.lang.Object striktně nevyžaduje – chová se typicky funkcionálně, zejména u immutable objektů, jako třeba java.lang.String.

                Mimochodem, tady je Scala spíše funkcionální. Operace == ekvivalence a ne identita. Možnost testovat identitu ve Scale sice taky je (jako i v dalších non-pure funkcionálních jazycích), ale je „skrytá“ pod eq a nepamatuju si, kdy jsem to napodledy použil (popř. viděl). Snad na nějakou mikrooptimalizaci. Narodíl od Javy se snaží Scala ekvivalenci i propagovat, protože na case classes defaultně funguje typicky funkcionálnálně, zatímco v Javě musím ručně psát equals a hashCode. A to ještě nepočítám problémy s null.equals v Javě.

                1. tacoberu

                  Re: hrušky jabka
                  Nejsem si jist, jak to s tou identitou Jirka myslel, ale:

                  V OOP je identita dost důležitá, protože ty můžeš vytvořit dva zcela ekvivalentní objekty. U druhého si zaregistruješ posluchače. A když pošleš zprávu prvému objektu tak nepřekvapivě informaci o změně prvního objektu nedostaneš. Takže v OOP je kardinální rozdíl mezi identitou a ekvivalencí.

                  A ve FP? Vytvoříš dva objekty. Zaregistruješ si u druhého posluchače = máš tři objekty. Prvnímu pošleš zprávu = už máš čtyři. A takhle to jede dál… dokavad nepochopí člověk, že se to v FP musí dělat jinak. Na identitu či ekvivalenci si ani nevzpomeneš.

                  1. Palo

                    Re: hrušky jabka
                    To co pisete o OOP je blbost. Ked chcem napisem to tak ze budete dostavat hlasenie o zmenach aj z druheho objektu ak sa zaregistrujete na prvom. Problem je ze obvykle to tak NECHCEM a preto sa to OBVYKLE nepouziva, nie preto ze by sa to nedalo.

                    1. tacoberu

                      Re: hrušky jabka
                      Zdá se mi, že jste si nepřečetl co jsem napsal. Dejte se prosím pozor, ať neargumentuje proti něčemu, co jsem neřekl.

  7. Ondřej Novák

    hrušky jabka
    Psal jsem komentář a nějak se ztratil, nevim

    ale napsal jsem něco ve smyslu, že je to srovnávání hrušek a jablek. Zkrátím to. Co vrací funkce ve funkcionálním programování? Jakého typu je hodnota? Může to být objekt? Proč by ten objekt neměl používat vlastnosti OOP?

  8. balki

    Z clankoch o paradigmach (a o navrhovych vzoroch) na zdrojaku sa mi vzdy zjezja vlasy. Rychlokvaseni odbornici na vsetko maju jasne nazory, miesto toho aby si nieco precitali :(

  9. Pavel Strnad

    Monady a jine zajimavosti
    Clanek je bohuzel velmi zavadejici a pouze ukazuje castecne znalosti/neznalosti autora. Pokud autor neco tvrdi, pak je dobre tvrzeni oprit o nejaky dukaz, pripadne citaci. Doporucuji autorovi si o monadach neco precist a prosim neplest dve veci teorii a implementaci v konkretnim jazyku. Jako vychozi material doporucuji (http://homepages.inf.ed.ac.uk/wadler/papers/marktoberdorf/baastad.pdf).
    Jinak ocenuji odvahu autora neco takoveho sepsat :-)

    1. Jiří Knesl

      Re: Monady a jine zajimavosti
      Která konkrétní tvrzení chcete dokázat?

      Je pravda, že roky programuju v ne-pure FP jazyce. Monády chápu pouze do určité úrovně. To uznávám.

  10. David Fogaš

    Není program jako program
    Když se podíváme na program, je složen ze dvou částí:
    algoritmy
    datové struktury
    Nad datovými strukturami programy něco počítají, komunikují atd.

    Hm, z výše uvedeného mi vyplývá, že program provádí operace s nějakým podprogramem a sám o sobě může být předmětěm manipulace ze strany programu mu nadřazenému. Pochopil jsem to správně? Jestli ano tak mi to přijde nešikovně napsané.

    1. Jiří Knesl

      Re: Není program jako program
      Bylo to myšleno tak, že mám data, která nejsou executable a algoritmy. Ty algoritmy berou vstupy, data a počítají a pracují s těmi daty.

  11. Radek Miček

    1) Chybí mi tu přesná definice, co autor považuje za OOP a funkcionální programování. Například je to, co dělám v beztypovém lambda kalkulu (se záznamy) funkcionální programování? Co když pak nad tímto lambda kalkulem vybuduji jazyk s objekty?

    Referenční transparence je koncept, který říká, že: „funkce při zavolání se stejnými parametry, musí vždy vrátit stejnou hodnotu“.

    2) BTW tahle definice příliš dobře nefunguje v jazyce s vedlejšími efekty. Například mohu mít klasicky definovaný map, ale když mu jako funkci, pomocí níž se mapuje, dám rand, tak podle té vaší definice nebude referenčně transparentní (i když normálně bychom ho za referenčně transparentní považovali).

    3) Píšete

    Nevím, funkce, které píšu já, obsahují v 80 % případů side effecty a nejsou tedy čisté funkcionální programování.

    ale podle

    Na úrovni strojového kódu jsou monády implementovány jako imperativní kód (stejně jako vše ostatní).

    jenž je psáno o kousek výš, byste měl side effecty všude (ne jen v 80 % případů). IMO lepší by bylo do toho vůbec netahat strojový kód a soustředit se například jen na operační sémantiku jazyka.

    4) Ještě jednou k:

    Někteří vývojáři ve funkcionálních jazycích tvrdí, že mají 90 % kódu čistý funkcionální kód a side effecty mají stranou. Nevím, funkce, které píšu já, obsahují v 80 % případů side effecty a nejsou tedy čisté funkcionální programování.

    Funkce s vedlejšími efekty lze přesunout do nějakého interpretru – tj. váš hlavní program pouze řekne, že se má zavolat například println a co se má dělat po zavolání – tj. celý program kromě interpretru je bez vedlejších efektů.

    V Haskellu je pak interpretr pro IO mimo program – tj. program je bez vedlejších efektů (pokud nepoužijete FFI, unsafePerformIO apod.).

    1. Radek Miček

      Re:

      tj. program je bez vedlejších efektů

      To je špatně – program v Haskellu může divergovat, což je efekt.

    2. čumil

      Re:
      Chlape, furt strašíš s tím interpretováním operací dělajících side efekty ?

      Sakra, uvědom si, že podle týdle jebnutý logiky je funkcionální (bez side efektů a mutable dat) úplně každý jazyk, protože konec konců, ty ÚPLNĚ VŽDY jenom říkáš interpretru (procesor) jaký side efekt má udělat a co má dělat po něm …

      Přestaň prosím šířit bludy, už jich kolem FP pobíhá dost samo o sobě (tímto zdravím immutable cyklické struktury … :( )

      1. Taco

        Re:
        Když koukám na kus kódu:

        foo :: String -> Int -> String

        Tak pokud mi vrací pro stejné dva argumenty stále stejný výsledek, tak je referenčně transparentní, a nemá side-efekty. A nezajímá mě jak toho ve skutečnosti dosahuje. (Leda, kdybych to chtěl dokazovat.) Zásadní je, že navenek se chová FP. Stejně tak není podstatné, že já se k němu budu chovat neFP, a budu třeba výsledek té funkce posílat do sítě.

        A naopak.

        To posuzování je vždy z pohledu volajícího.

        Proto třeba imperativní monády mohou běhat ve funkcionálním kódu.

        Proto nemáš pravdu.

        1. Jiří Knesl

          Re:
          To je demagogie jako hrom.

          Ne, dílo od Shakespeara není funkcionální kód.

          Navíc i v samotném programu může být pure-FP program skutečně pure.

          Když budu psát funkci, která přečte soubor, vezme první řádku, z té udělá uppercase a to vypíše na obrazovku.

          Tak imperativně ten interpret DOOPRAVDY otevře soubor, přečte první řádku, udělá uppercase, to vypíše.

          Zatímco v FP ten interpret DOOPRAVDY vrátí funkci „otevírající soubor“ s callbackem s daty, což se předá do funkce vracející první řádku, což padne do funkce uppercase, což padne do funkce, která vrátí callback „poté, co došlo k printu ven“.

          Ten kód je čistě funkcionální i na runtime úrovni. Pak je tu úroveň pod tím, která to skutečně vyhodnocuje. Ta je ale neviditelná. V programu vývojář fakt píše funkce, vrací funkce a ono se to děje „vespod“, ale jinak. Vývojář nevolá funkci „načti data“, on vrátí funkci „poté, co jsi načetl data“ a v tom je velký rozdíl.

          Co se šíření bludů týká, čumile, docela jste se vyznamenal.

      2. Radek Miček

        Re:

        podle týdle jebnutý logiky je funkcionální (bez side efektů a mutable dat) úplně každý jazyk

        Tahle logika neříká nic o tom, zda je každý jazyk funkcionální, ta pouze říká to, že ve většině jazyků můžete mít drtivou většinu kódu bez vedlejších efektů a drtivá většina funkcí může být referenčně transparentní. Taková transformace jde udělat mechanicky. Například kdykoliv má v původní funkci proběhnout vedlejší efekt, např. readLine, tak funkci jednoduše ukončím a vrátím dvojici (ReadLine, Next), kde první prvek dvojice říká, co se má dělat za efekt, druhý prvek říká, co se má dělat poté. Funkce vracející dvojici je bez vedlejších efektů, a opakováním této transformace získáme i Next bez vedlejších efektů.

        Tj. všechny funkce v původním programu mohu takto zbavit vedlejších efektů. Abych program mohl spouštět, vytvořím jednu funkci s vedlejšími efekty, ta bude v cyklu volat transformované funkce bez vedlejších efektů a vykonávat vedlejší efekty. Skončí se například v okamžiku, kdy je vrácen efekt Stop (první prvek dvojice je Stop).

        ÚPLNĚ VŽDY jenom říkáš interpretru (procesor) jaký side efekt

        Cílem je, aby fungoval substituční model v programu (funkce v programu byly referenčně transparentní) – nezáleží na tom, co se děje v procesoru/paměti počítače.

    3. tacoberu

      Re:

      2) BTW tahle definice příliš dobře nefunguje v jazyce s vedlejšími efekty. Například mohu mít klasicky definovaný map, ale když mu jako funkci, pomocí níž se mapuje, dám rand, tak podle té vaší definice nebude referenčně transparentní (i když normálně bychom ho za referenčně transparentní považovali).

      No, já bych ho v takovém případě za referenčně transparentní nepovažoval. Pokud umožní, aby jej funkce s vedlejšími efekty nakazila…

  12. Honza

    Špatný příklad v článku
    Kód, který autor uvádí jako „objektový“, je designově principálně špatně!

    order = new Order(...)
    invoice = order.generateInvoice(user)
    

    Tímto se vnáší nežádoucí dependency – typ Order musí znát typ Invoice, což by neměl.

    Místo toho by mělo být buď

    invoice = new Invoice(order, user)
    

    nebo ještě lépe

    invoice = invoiceFactory(order, user)
    

Napsat komentář

Tato diskuse je již příliš stará, pravděpodobně již vám nikdo neodpoví. Pokud se chcete na něco zeptat, použijte diskusní server Devel.cz

Zdroj: https://www.zdrojak.cz/?p=18249