Dědičnost dnes

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Dědičnost dnes
« Odpověď #525 kdy: 28. 01. 2017, 13:25:07 »
I když pokud má jazyk/runtime třeba channels, tak to vyjde nastejno i v opačném směru, asynchronizační funkce vrátí "channel rettype" a hodnotu si pak přečtu asynchronně, ale kód vlastně bude vypadat synchronně.
Jo, channel tam vlastně sehraje úlohu toho "asynchronizačního bufferu". Pořád je to ale to "něco navíc", co musím někde vytvořit, má to (aspoň teoreticky) nějakou režii, nějak to komplikuje kód. Přijde mi daleko přímočařejší kód, který když nechci, aby blokoval, tak nedělám nic, když chci, aby blokoval, tak prostě čekám na místě, dokud nedojde k události. Vytvářet thread/rutinu/channel kvůli jednomu volání je prostě (pocitově) pro mě míň estetické ;)

...ale to jsme se dostali do zbytečných detailů, myslím, že si rozumíme a nejsme v žádném sporu :)
Možná mi něco nedocvaklo, ale blokování asynchronního volání (resp. čekání) má taky režii, potřebuju třeba semafor nebo tak něco, ne? Jinak bych to asi fakt ukončil, v konečném důsledku ten zápis v obou případech závisí na konkrétním jazyce a příslušném běhovém prostředí.


Re:Dědičnost dnes
« Odpověď #526 kdy: 28. 01. 2017, 13:26:29 »
Erlang je v některých ohledech přísnější než Elixir. Elixir má narozdíl od Erlangu mutable proměnné. Což považuji za výhodu.
Ne! To je jenom syntaktický cukr, aby člověk nemusel psát
Kód: [Vybrat]
v = 1
v1 = v+2
v2 = v1 + 3
...což strašně komplikuje přepisování kódu.

Elixir a Erlang se v tomhle liší jenom syntaxí, ale podvozek je úplně stejný.

Viz http://stackoverflow.com/a/30000838/3150343

Re:Dědičnost dnes
« Odpověď #527 kdy: 28. 01. 2017, 13:29:50 »
Možná mi něco nedocvaklo, ale blokování asynchronního volání (resp. čekání) má taky režii, potřebuju třeba semafor nebo tak něco, ne?
V implementaci jo. Ale v jazyce můžu mít třeba jenom to zmíněné
Kód: [Vybrat]
receive do
  :message_i_am_waiting_for -> :ok
end
...což mi přijde parádně čitelné - na první pohled vidím "tady čekám na zprávu".

Re:Dědičnost dnes
« Odpověď #528 kdy: 28. 01. 2017, 14:02:35 »
Neznam Elixir, ale myslim, ze nebyl ciste FP, takze bych se nedivil, kdyby tam byly mutable veci podobne jako ve Scale.
Ne, tak jako ve Scale ne, ani trochu.

Elixir je taková "nadstavba" nad Erlangem, tady z těch základních věcí tam platí všechno, co v Erlangu:

1. data jsou naprosto striktně immutable, nejde je měnit vůbec nijak (neexistuje ani žádný hack/pragma/meta/výjimka, která by to umožnila)

2. funkce můžou mít vedlejší efekty => není garantovaná referenční transparentnost

3. primárním cílem Erlangu/Elixiru není funkcionální programování, ale "concurrent programming". FP je tam jenom do té míry, do které dává smysl jako podvozek pro CP. Proto Elixir ani Erlang nejsou "čisté" funkcionální jazyky, spíš pragmatické. Ale zase to není takový ten kočkopes jako Scala, kde si můžu vybrat, že v téhle části kódu použiju X a v jiné Y, tady budu mutabilní a tady ne. To v Elixiru není.

4. základním stavebním blokem Erlangu jsou procesy, které komunikují pomocí zpráv a nemůžou sdílet stav jinak než přes databázi (protože bod 1).

5. Erlang a (trochu míň) Elixir mají kořeny v Prologu,  ne v FP. Proto je tam z FP jenom to, co pragmaticky dávalo smysl pro celek toho jazyka (a vybrali to velmi dobře - ten jazyk a celý ekosystém je neuvěřitelně dobře navržený, pořád mě to nepřestává překvapovat, jak dobře to tenkrát udělali).

javaman ()

Re:Dědičnost dnes
« Odpověď #529 kdy: 28. 01. 2017, 14:51:31 »
To zní dost dobře. Takže proč se nepoužívá víc? Znám třeba RabbitMQ, který je hodně populární. Ale třeba ActiveMQ umí cca to stejné a i stejně rychle. Takže v Erlangu by byl vývoj rychlejší? Je lépe udržovatelný? Nebo co je ta hlavní výhoda a zároveň proč se nepoužívá více?


Re:Dědičnost dnes
« Odpověď #530 kdy: 28. 01. 2017, 15:19:49 »
To zní dost dobře. Takže proč se nepoužívá víc? Znám třeba RabbitMQ, který je hodně populární. Ale třeba ActiveMQ umí cca to stejné a i stejně rychle. Takže v Erlangu by byl vývoj rychlejší? Je lépe udržovatelný? Nebo co je ta hlavní výhoda a zároveň proč se nepoužívá více?
Pro nic z toho nemám žádná tvrdá data, takže těžko říct, můžu posloužit jenom mými subjektivními dojmy...

Subjektivně má Elixir trochu zvlněnou křivku učení - ty základy (syntaxe, moduly, funkce, protokoly) dá programátor v jiném jazyce tak za den, dva. Potom ale musí projít velkým mind-twistem, aby pochopil, jak se z nezávislých procesů, komunikujících jenom pomocí zpráv, stavějí větší systémy. U programátora bez zkušeností třeba s tím SmallTalkem nebo ObjC může tohle trvat docela dlouho. A pak nastává období, než ty patterny začne psát úplně automaticky. Teprve až projde tímhle, začíná být v Elixiru opravdu produktivní. Tohle by mohlo být spoustě lidem nepříjemný.

Druhá věc je, že se o Elixiru prostě neví (proto ho tady propaguju, protože podle mě stojí za pozornost pro každého programátora jako občerstvení a nakouknutí, jak se dají věci řešit i jinak...). O Erlangu se ví trochu víc, ale Erlang má dost nepříjemnou syntaxi, která asi hodně lidí odradí.

Třetí věc je, že co se týče hrubého výkonu, je Erlang (a tímpádem i Elixir) poměrně dost pomalý - v testech typu https://benchmarksgame.alioth.debian.org/ nemá šanci. To je tím, že byl původně navržený pro konkrétní problém (programování telefonních ústředen Ericsson) s návrhovými kritérii: 1. obrovský důraz na spolehlivost 2. masivní paralelizace 3. distribuovanost 4. možnost updatů za běhu (souvisí s 1). Rychlost byla požadovaná jenom na úrovni "soft-realtime". Hrubá rychlost number crunching nebyla cílem.

Čtvrtá věc je, že Erlang se nikdy nevezl na módní vlně, spíš přesně naopak - vznikal v době, kdy největší buzzword byl OOP a přitom šel do velké míry proti němu (v té jeho tehdejší módní podobě). Dneska už je to trochu jinak, do módy se dostává právě spíš FP a paralelismus, takže Elixir imho má celkem šanci, ale nějaký velký, masový úspěch bych mu nepredikoval, na to je málo easy, cool. Masový úspěch bych čekal spíš u Go.

Jinak, moje subjektivní zkušenost je taková, že jakmile jsem si na koncepty Elixiru zvykl, píše se mi v něm strašně příjemně, přirozeně - nemusím si strašlivě trápit hlavu a prostě si jenom tak hezky píšu a ono to funguje ;) Tím je to pro mě výrazně příjemnější než třeba to OOP, kde se pořád dokola řeší nějaké filosoficko-návrhové prkotiny typu co má být private, co dědit z čeho, co je "pravé" OOP, co je antipattern atd. atd. nebaví mě to, nechtěl bych se do tohodle světa vracet :)

Jinak objektivněji, Erlang má suprově navrženou knihovnu OTP, která umožňuje velice snadno dosáhnout věcí, které v jiných jazycích sice jdou třeba taky, ale je to hrozně náročný a spousta lidí si na tom vyláme zuby. Typicky ta distribuovanost a updaty za provozu. Proto si z OTP vzal příklad Akka framework a třeba takový Flink může díky němu poskytnout krásnou, jednoduchou a rock-solid distribuovanost hned ze startu - rozdíl např. oproti klasickým databázím, kde se podobné věci řeší desetiletí a pořád to tak nějak limitovaně funguje, ale sem tam jenom když je pátek odpoledne, bezvětří a nezapisuješ moc často ;)
« Poslední změna: 28. 01. 2017, 15:21:59 od Mirek Prýmek »

Re:Dědičnost dnes
« Odpověď #531 kdy: 28. 01. 2017, 15:35:48 »
Třetí věc je, že co se týče hrubého výkonu, je Erlang (a tímpádem i Elixir) poměrně dost pomalý - v testech typu https://benchmarksgame.alioth.debian.org/ nemá šanci.
Taky k tomu ještě doupřesnění, ať nevzniká mylnej dojem: z tohodle nijak neplyne nepoužitelnost pro praktické problémy nebo špatný výkon v reálných aplikacích. Zatímco třeba Python nebo Ruby jsou prostě pomalý a nemají to čím vyvážit, takže jediný způsob, jak s nima dělat něco použitelnýho, je začít využívat hrubé hacky jako nativní céčkové knihovny nebo kdovíjaké obcházení GILu, Erlang tu základní "hrubou" pomalost víc než vyvažuje právě tou parádní paralelizovatelností a ještě jinými drobnostmi, jako třeba elegantním garbage collectorem (díky nepřekročitelné immutabilitě), takže celkový výkon bývá velice příjemný.

Doporučuju třeba zkusit zagooglit "phoenix benchmark" - phoenix je Elixirovský webový framework s parádním výkonem.

gll

Re:Dědičnost dnes
« Odpověď #532 kdy: 28. 01. 2017, 15:36:19 »
1. data jsou naprosto striktně immutable, nejde je měnit vůbec nijak (neexistuje ani žádný hack/pragma/meta/výjimka, která by to umožnila)

Data možná, ale hodnota proměnné lze změnit. Narozdíl od Erlangu.

Kód: [Vybrat]
iex(1)> fn -> a=1; a=2; a end.() 
2

Re:Dědičnost dnes
« Odpověď #533 kdy: 28. 01. 2017, 15:41:09 »
Data možná, ale hodnota proměnné lze změnit. Narozdíl od Erlangu.

Kód: [Vybrat]
iex(1)> fn -> a=1; a=2; a end.() 
2
Opakuju: nemá  to vůbec žádné důsledky, je to jenom syntaktický cukr. Neplyne z toho, že by byl Elixir "míň striktní".

To elixirovské
Kód: [Vybrat]
a = 1
a = 2
f(a)
se prostě jakoby do Erlangu převede jako:
Kód: [Vybrat]
a1 = 1
a2 = 2
f(a2)

Re:Dědičnost dnes
« Odpověď #534 kdy: 28. 01. 2017, 16:26:46 »
Tak jsem to pročetl... Je-li pan Armstrong spoluautorem Erlangu, je zarážející, že podstatu OOP naprosto, ale NAPROSTO nepochopil:
Ve tvrzeních o Armstrongovi bych byl opatrnější. Když člověk trochu zná výsledky jeho práce, vidí na vlastní oči, jak velice dobře různé problémy Erlangovský tým vyřešil. Člověk občas až žasne, jak u spousty problému zvolili řešení, které prozíravě předchází problémům, které se (ne)projeví až o několik tahů později. Působí to na mě jako přesný opak třeba javascriptového světa, kde každý krok typicky jeden problém vyřeší a deset nových způsobí :)

Objection 1: OOP oproti FP "data" a "funkce" spojuje z jednoduchého důvodu, a to, že data bez funkcí jsou k ničemu stejně tak jako funkce bez dat, přičemž funkce jsou vytvořeny pro daná data (to nevylučuje práci s obecnými daty jako v FP!). Myšlenka nutnosti nespojovat funkce a data jen z důvodu, že se jedná o jiné kategorie, je neopodstatněná (to ale neznamená, že to nejde).
Tam jde myslím spíš o to, že OOP svazuje konkrétní fce s konkrétními ("svými") daty a tím komplikuje (záměrně - a podle některých chybně) přístup k datům jinými fcemi.

Stupidní příklad: fce List.reverse(list) může fungovat nad listem čehokoli, protože o položkách nic nepředpokládá. Vesele teda jednou jedinou funkcí otáčím listy zákazníků, faktur i planet sluneční soustavy. Když chci totéž udělat u OOP, tak mi tenhle jeden problém exploduje do tisíce dalších: asi teda chci nějaké rozhraní IReversable, nebo chci nějak data zpřístupnit? Nebo pro každý objekt úplně nezávisle napíšu tutéž fci o.reverse()? Co je správně? Co je antipattern? Co porušuje zapouzdření? Neměl by objekt PlanetList dědit z List? No jo, ale já potřebuju, aby dědil z PlanetsOfSolarSystem. Co s tím? Vícenásobná dědičnost? Ale ne, to je fuj. atd.atd.atd. Armstrong tvrdí (nemusíš s ním souhlasit, ale myslím, že to nemůžeš jenom tak šmahem odbýt), že kdybys ty data nesvázal s konkrétními, předem danými funkcemi, měl bys míň problémů.

Objection 2: Různé třídy (typy; či prototypy) pro různé časové údaje se používají v implementacích OOP naprosto běžně - tento bod je nadbytečný.
Ten bod je spíš špatně vysvětlený. Nejde tam imho o to, že máš víc typů, ale že ty typy jsou "ubiquitous and data structures representing times can be manipulated by any function in the system" a že "There are no associated methods.". Čili to souvisí s předchozím a následujícím bodem. Např. na některé typy zachycující čas můžu v FP aplikovat List.reverse, když mi to bude dávat smysl. V OOP by nikdo nepředpokládal, že to budu chtít udělat, takže by neimplementoval IReversable, takže bych musel z Time dědit do svého MyReversableTime, který o IReversable rozšířím, jenže pak ho nemůžu serializovat stejně jako Time, protože na druhé straně MyReversableTime nemám a navíc ... (opět exploze pseudoproblémů)

Objection 3: Všudypřítomné "typy" se realizují třídami či prototypy. Poslední věta fabuluje cosi o nutnosti dědění.
Opět je tam klíčové to "ubiquitous". Prostě na jednom místě mám definováno, jakou strukturu mají data pojmenovaná "List" a používám to všude. Nepotřebuju řešit pseudoproblémy typu "Všechny objekty musí dědit z Object".

Objection 4: Objekty mají skryté stavy, ale nedávno mi tu pan Prýmek vysvětlil na Elixíru, že FP je má taky, akorát je jinak ukládá. Kde je potom rozdíl?
Říká tam, že stav nechceme, protože je s ním opruz, ale nějakým způsobem potřebujeme řešit, protože práce se stavem je cílem programování v reálném světě. Takže stav nějak ošetřit potřebujeme, máme na to několik možností. A Armstrong říká (opět s ním nemusíš souhlasit), že způsob práce se stavem, který zvolilo OOP, je nejhorší možný z dostupných.

---
Btw, velmi doporučuji se kouknout na video, kde Armstrong s Kayem diskutují. Neřekl bych, že by si nějak zvlášť vjížděli do vlasů. Spíš naopak - vypadá to, že oba dva se shodují na tom, že to, co se z OOP stalo, stojí za starou belu ;)

[EDIT: sorry, nějak jsem si spletl Kaye s Johnsonem ;) ]

https://www.infoq.com/interviews/johnson-armstrong-oop

Ještě je na YT jedno video s nima oběma, to jsem ale zatím neviděl.
« Poslední změna: 28. 01. 2017, 16:32:15 od Mirek Prýmek »

gll

Re:Dědičnost dnes
« Odpověď #535 kdy: 28. 01. 2017, 16:41:38 »
Data možná, ale hodnota proměnné lze změnit. Narozdíl od Erlangu.

Kód: [Vybrat]
iex(1)> fn -> a=1; a=2; a end.() 
2
Opakuju: nemá  to vůbec žádné důsledky, je to jenom syntaktický cukr. Neplyne z toho, že by byl Elixir "míň striktní".

To elixirovské
Kód: [Vybrat]
a = 1
a = 2
f(a)
se prostě jakoby do Erlangu převede jako:
Kód: [Vybrat]
a1 = 1
a2 = 2
f(a2)

Při zkoušení příkladů z tutoriálů (dál jsem se nedostal) je to užitečná vlastnost.

Jak funguje třeba funkce Map.put? Vytvoří kopii celé původní mapy nebo na ní odkáže?

Re:Dědičnost dnes
« Odpověď #536 kdy: 28. 01. 2017, 16:44:39 »
Při zkoušení příkladů z tutoriálů (dál jsem se nedostal) je to užitečná vlastnost.
Ano, je to příjemná změna syntaxe.

Jak funguje třeba funkce Map.put? Vytvoří kopii celé původní mapy nebo na ní odkáže?
Já vlastně ani nevím a je mi to jedno ;) Dležitý je, že starou i novou mapu můžu pořád někam předávat  a nemusím se bát, že by mi je někdo změnil. Jestli to vnitřně nějaká data sdílí (předpokládám že jo), je mi jako programátorovi šuma fuk, mě zajímají ty vnější garance.

javaman ()

Re:Dědičnost dnes
« Odpověď #537 kdy: 28. 01. 2017, 17:29:54 »
Super, Mirku. Díky za info. Musím se tím probrat.

javaman ()

Re:Dědičnost dnes
« Odpověď #538 kdy: 28. 01. 2017, 17:47:56 »

Jinak, moje subjektivní zkušenost je taková, že jakmile jsem si na koncepty Elixiru zvykl, píše se mi v něm strašně příjemně, přirozeně - nemusím si strašlivě trápit hlavu a prostě si jenom tak hezky píšu a ono to funguje ;) Tím je to pro mě výrazně příjemnější než třeba to OOP, kde se pořád dokola řeší nějaké filosoficko-návrhové prkotiny typu co má být private, co dědit z čeho, co je "pravé" OOP, co je antipattern atd. atd. nebaví mě to, nechtěl bych se do tohodle světa vracet :)

S tím docela souhlasím. Hlavně to vidíš i tady. OOP Java podle některých není OOP. Dědičnost je podle některých super, podle jiných k ničemu. Pak v tom dělej :D

Re:Dědičnost dnes
« Odpověď #539 kdy: 28. 01. 2017, 18:00:16 »
Super, Mirku. Díky za info. Musím se tím probrat.
Určitě se na Elixir koukni, fakt je to zajímavý i jenom na hraní, jako osvěžení. Kdyžtak klidně napiš třeba tady přes fórum, nebo si na mě vygoogli mail, rád s Elixirem pomůžu komukoli, je to pro dobro lidstva ;)