Fórum Root.cz
		Hlavní témata => Vývoj => Téma založeno: scalac  30. 08. 2015, 16:02:19
		
			
			- 
				Něco jsem si o Scale přečetl a trochu ji vyzkoušel, ale nejsem si jistý, jestli má smysl se o tento jazyk nějak víc zajímat.
Nějaké vlastnosti:
- Actor model - po vzoru Erlangu lze mít objekty, které čekají na zprávy a ty potom zpracovávají. Tipuju, že to bude implementované teda nějak tak, 
že po spuštění aplikace napsané ve Scale tam bude několik vláken, které budou sloužit pro zpracovávání zpráv z front jednotlivých Actorů.
Tohle by mělo být normálně možné udělat i v Javě, není to jakoby  vlastnost, které v Javě nelze docílit. 
 - Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
 - Immutable typy - taky věc, co se dá udělat i v Javě, prostě budu mít jen konstruktory a žádné metody na modifikaci. 
 -  Klíčové slovo val, kdy pak není možné měnit proměnnou - Java má final
 - Akademická syntaxe - ta syntaxe je prostě taková, aby to nevypadalo jako Java :)
 
Nechci, aby to vypadalo jako nějaký hejt Scaly, ale opravdu by mě zajímalo, proč bych to měl chtít na něco použít místo Javy, když bych si musel zvykat na tu syntaxi. Samozřejmě můžu dát pročítat články na netu, ale nějaká diskuze nemusí být od věci :).
			 
			
			- 
				u toho Funckcionálního programování jde také o to, že v Javě 8 už jsou anonymní funkce, ne tedy jen o tu třídu java.util.Stream.
Lze tedy psát např:
Collection<Integer> numbers = Arrays.toList(10,20,30,40);
int countBiggerThan50 = numbers.stream().filter(number -> number > 50).count();
			 
			
			- 
				
Javě chybí to val (aka var/let), jinak výhody moc nejsou.
			 
			
			- 
				
Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
Pokročilejší FP se v Javě stále dělá dost těžko - to je dáno typovým systémem (například argumentem generik ve Scale nemusí být typ, ale může to být typová funkce - tj. generická třída bez argumentů; nebo tzv. path-dependent typy (http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types)).
Kromě silnějšího typového systému má Scala navíc implicitní argumenty (aplikací jsou například typové třídy) a makra.
			 
			
			- 
				
Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
Pokročilejší FP se v Javě stále dělá dost těžko - to je dáno typovým systémem (například argumentem generik ve Scale nemusí být typ, ale může to být typová funkce - tj. generická třída bez argumentů; nebo tzv. path-dependent typy (http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types)).
Kromě silnějšího typového systému má Scala navíc implicitní argumenty (aplikací jsou například typové třídy) a makra.
Samozřejmě Scale nechybí ani pattern matching a case classy.
			 
			
			- 
				
Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
Pokročilejší FP se v Javě stále dělá dost těžko - to je dáno typovým systémem (například argumentem generik ve Scale nemusí být typ, ale může to být typová funkce - tj. generická třída bez argumentů; nebo tzv. path-dependent typy (http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types)).
Kromě silnějšího typového systému má Scala navíc implicitní argumenty (aplikací jsou například typové třídy) a makra.
Myslim, ze neco takovyho pujde i v Jave:
public class MyClass<X extends Function<Y, Z>> ...
			 
			
			- 
				
Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
Pokročilejší FP se v Javě stále dělá dost těžko - to je dáno typovým systémem (například argumentem generik ve Scale nemusí být typ, ale může to být typová funkce - tj. generická třída bez argumentů; nebo tzv. path-dependent typy (http://stackoverflow.com/questions/2693067/what-is-meant-by-scalas-path-dependent-types)).
Kromě silnějšího typového systému má Scala navíc implicitní argumenty (aplikací jsou například typové třídy) a makra.
Myslim, ze neco takovyho pujde i v Jave:
public class MyClass<X extends Function<Y, Z>> ...
To není ono. Měl jsem na mysli higher-kinded generics (http://stackoverflow.com/questions/21170493/when-are-higher-kinded-types-useful).
Příkladem je MyClass<X>, kde X označuje generickou třídu se dvěma parametry, tj. uvnitř MyClass mohu použít třeba X<String, String>, X<Integer, String> a X<T, U>, kde T i U jsou typové parametry.
			 
			
			- 
				
Myslim, ze neco takovyho pujde i v Jave:
I když teoreticky jde ledacos, cokoliv trochu komplikovanějšího zabije:
- reifikace
 - knihovny nenavržené pro generiky
 - reflection (a té se jen tak nezbavíme, hlavně kvůli absenci metatříd)
 
			 
			
			- 
				
Tohle by mělo být normálně možné udělat i v Javě, není to jakoby  vlastnost, které v Javě nelze docílit. 
actor model v akka funguje pre scalu aj pre javu 
maju dve sady api
ale niektore veci v java api nezapisete resp. to vyzera ako perl
			 
			
			- 
				Muj nazor je, ze na Scalu ma smysl se podivat. Zda se, ze to je budoucnost Javy/JVM - hodne modernich projektu ma API pro Scalu nebo je v ni primo napsano, takze myslim existuje kriticka masa "early adopters". I kdyz jako jazyk je to.. asi jako kdyz kocicka s pejskem varili dort. Na muj vkus trochu prekomplikovane, ale zvyknete si, tak jako si generace pred vami zvykla na C++. :)
Co se tyce syntaxe, Scala bere pulku syntaxe od staticky typovanych funkcionalnich jazyku, kdy se argumentu oddeluji mezerami. Obecne, spojeni OOP a FP mi nepripada uplne stastne. Je to asi jako nekomu, kdo nezna SQL a relacni databaze, vnutit ORM, s tim, ze to bude mit snazsi. No zpocatku asi trochu ano, nez narazi na zakladni problemy vyplyvajici z nepochopeni podstatnych odlisnosti obou modelu, a pak tvrde narazi a zivot si zkomplikuje. Ze stejneho duvodu bych doporucoval Javistum, kteri se zajimaji o FP, naucit se (pred Scalou) aspon trochu nejaky ciste funkcionalni jazyk, treba Haskell, pak bude snazsi pochopit, z ceho ze to FP do te Scaly vlastne prislo a jakou to ma roli (treba vyznam veci jako ciste funkce, line vyhodnocovani, pattern matching, algebraicke datove typy, currying apod.).
			 
			
			- 
				
I kdyz jako jazyk je to.. asi jako kdyz kocicka s pejskem varili dort. Na muj vkus trochu prekomplikovane
Ano, Scala je komplikovaná, ale nepřijde mi to jako nějaká splácanina - naopak mi přijde, že je tam jen pár konstrukcí, na nichž je vše postaveno (v tomto ohledu mi Scala přijde mnohem čistší než OCaml nebo GHC Haskell).
Jako hlavní problém ovšem vidím zabugovanost kompilátoru a určité problémy typového systému - oboje by mohl vyřešit DOT (http://lampwww.epfl.ch/~amin/dot/fool.pdf) a jeho implementace dotty.
Obecne, spojeni OOP a FP mi nepripada uplne stastne.
Jelikož objekty ve Scale mohou obsahovat typy, lze je chápat jako přirozené zobecnění modulů z ML (např. z OCamlu).
			 
			
			- 
				Vlastnosti Scaly ocení člověk, který vidí trochu do hloubky. Pro průměrného javistu je obtížně srozumitelná - mluvím z vlastní zkušenosti :-) 
Ale na druhou stranu je to šance, jak se toho dost přiučit, takže bych to nevzdával hned na začátku. Taky proto, že jazyky nad jvm mají podle mě budoucnost, protože spojují to, co je známé a už funguje (jvm a knihovny) a přidávají k tomu pokrokové prvky (nový jazyk). 
			 
			
			- 
				
I kdyz jako jazyk je to.. asi jako kdyz kocicka s pejskem varili dort. Na muj vkus trochu prekomplikovane
Ano, Scala je komplikovaná, ale nepřijde mi to jako nějaká splácanina - naopak mi přijde, že je tam jen pár konstrukcí, na nichž je vše postaveno (v tomto ohledu mi Scala přijde mnohem čistší než OCaml nebo GHC Haskell).
Tohle je takovy akademicky pohled. V praxi je myslim jedno, z kolika soucastek lze poskladat vlastnosti jazyka, daleko uzitecnejsi mi prijde jista "konzistence" vysledku (tedy ze to, co napisu, dela co bych asi tak cekal). Ale abych byl trochu konkretni - znas nejakou vlastnost programovacich jazyku, ktera je zrovna v mode a kterou se Oderski rozhodl do Scaly nepridat? Mluvim treba o XML syntaxi, makrech, async atd. Neni to jen problem z hlediska programovani, ale proste uz je IMHO cas na to, aby se Scala prestala prekotne vyvijet, pokud chce vyrust v pouzivany programovaci jazyk. 
Jako hlavní problém ovšem vidím zabugovanost kompilátoru a určité problémy typového systému - oboje by mohl vyřešit DOT (http://lampwww.epfl.ch/~amin/dot/fool.pdf) a jeho implementace dotty.
Vubec se tomu nedivim, kdyz se podivam, co vsechno za vlastnosti Oderski ve Scale chce mit. Ale IMHO ten paper jde presne smerem, kterym by uz Scala mela prestat jit - pokud bude Oderski povazovat Scalu za svoji experimentalni platformu pro vyzkum programovacich jazyku, nikdy se poradne neprosadi. Zase tam chteji pridat nejake silene zobecneni, ktere ovsem bude mit v praxi spoustu vyjimek (protoze nikdo jaksi poradne nepromyslel, jak to zkombinovat s temi ostatnimi vlastnostmi, je-li to vubec mozne), takze to realne programovani spis zamlzi nez zjednodusi.
Obecne, spojeni OOP a FP mi nepripada uplne stastne.
Jelikož objekty ve Scale mohou obsahovat typy, lze je chápat jako přirozené zobecnění modulů z ML (např. z OCamlu).
No ja mluvim spis (ale ne vylucne) o syntaxi. Scala se rozhodla k volani metody jak se zapisuje v OOP (instance.metoda(parametr)) jeste pridat system pouzivany ve funkcionalnich jazycich (metoda instance parametr). Vysledek je, ze kod je potencialne spatne citelny pro vsechny. Jeste je tam par jinych takovych pripadu.
Dalsi priklad jsou implicity, to jsem vubec nepochopil. Kdyby proste pridal typove tridy, mohlo to byt krasne ciste.
			 
			
			- 
				
I kdyz jako jazyk je to.. asi jako kdyz kocicka s pejskem varili dort. Na muj vkus trochu prekomplikovane
Ano, Scala je komplikovaná, ale nepřijde mi to jako nějaká splácanina - naopak mi přijde, že je tam jen pár konstrukcí, na nichž je vše postaveno (v tomto ohledu mi Scala přijde mnohem čistší než OCaml nebo GHC Haskell).
znas nejakou vlastnost programovacich jazyku, ktera je zrovna v mode a kterou se Oderski rozhodl do Scaly nepridat? Mluvim treba o XML syntaxi, makrech, async atd.
async je jen makro. Není tam třeba LINQ.
Jako hlavní problém ovšem vidím zabugovanost kompilátoru a určité problémy typového systému - oboje by mohl vyřešit DOT (http://lampwww.epfl.ch/~amin/dot/fool.pdf) a jeho implementace dotty.
Vubec se tomu nedivim, kdyz se podivam, co vsechno za vlastnosti Oderski ve Scale chce mit. Ale IMHO ten paper jde presne smerem, kterym by uz Scala mela prestat jit - pokud bude Oderski povazovat Scalu za svoji experimentalni platformu pro vyzkum programovacich jazyku, nikdy se poradne neprosadi. Zase tam chteji pridat nejake silene zobecneni, ktere ovsem bude mit v praxi spoustu vyjimek (protoze nikdo jaksi poradne nepromyslel, jak to zkombinovat s temi ostatnimi vlastnostmi, je-li to vubec mozne), takze to realne programovani spis zamlzi nez zjednodusi.
Osobně mi to přijde jako zjednodušení - průnik typů tam je nově komutativní. Navíc při typové kontrole nevznikají nekonečné typy.
No ja mluvim spis (ale ne vylucne) o syntaxi. Scala se rozhodla k volani metody jak se zapisuje v OOP (instance.metoda(parametr)) jeste pridat system pouzivany ve funkcionalnich jazycich (metoda instance parametr).
Opravdu? Myslel jsem, že tam je jen instance metoda parametr - tj. bez tečky a závorek.
Dalsi priklad jsou implicity, to jsem vubec nepochopil. Kdyby proste pridal typove tridy, mohlo to byt krasne ciste.
Mj. GHC Haskell má oboje. Výhoda implicitních parametrů je, že můžete předávat normální hodnoty - například spojení do databáze. Navíc typové třídy v Haskellu dovolují (víceméně) pouze jednu instanci typové třídy pro jeden typ (program s více instancemi GHC AFAIK neslinkuje) - implicity ve Scale toto omezení nemají. Někdo sice říká, že toto omezení je výhodné, ale na druhou stranu někdy je užitečné (a přirozené) mít více instancí - například aditivní i multiplikativní monoid.
			 
			
			- 
				Mj. Odersky měl nedávno prezentaci o novém kompilátoru Dotty: Compilers are Databases (https://www.youtube.com/watch?v=48js0H6ooBY&feature=youtu.be).
			
 
			
			- 
				
async je jen makro. Není tam třeba LINQ.
Aha, nicmene nezavisle na tom, ze je to makro (nebo mozna proto), ma to urcita omezeni (ktera si uz nepamatuji). Mozna jsou to smysluplna omezeni, ale prijde mi, ze se v tom pak programuje hur, pokud ta omezeni nejsou na prvni pohled zjevna. Obavam se, ze tato, byt nutna omezeni, vyplyvaji z prilis vysokych ambici tvurce jazyka - coz je presne pripad toho "vareni dortu" (neocekavane  interakce ruznych, samostatne nepochybne uzitecnych, abstrakci).
S LINQem mas pravdu. Jak je na tom vlastne Scala a databaze? Existuje ve Scale nejaky oficialni zpusob, jak k nim pristupovat?
Opravdu? Myslel jsem, že tam je jen instance metoda parametr - tj. bez tečky a závorek.
Mas pravdu, unahlil jsem se. Ale ze svoji (spis male) zkusenosti se Scalu naucit je to dost matouci, a to znam oba zapisy. Moji kolegove na tom nebyli o moc lepe. 
Asi je to o pohledu, z meho hlediska skutecne pri pouzivani programovaciho jazyka nehraje roli, z kolika primitiv byl postaven. Dulezitejsi je, jestli se abstrakce/operatory, ktere ma programator k dispozici, daji dobre skladat, chovaji se tak nejak predvidatelne (nemaji treba ruzna tezko vysvetlitelna omezeni) a zbytecne se svoji funkcionalitou neprekryvaji. V tomhle povazuji Python za neprekonanou jednicku, prestoze ma nejspis mizerny typovy system a je v podstate imperativni. (Coz je asi i odrazem toho, ze mi programovani ve staticky typovych systemech zvlast nevyhovuje.) Proste prumysl ma IMHO trochu jine potreby nez akademici (treba stabilitu) a pokud se Scala ve svem vyvoji trochu neuklidni, obavam se, ze moc uspesna nebude (coz by byla skoda, protoze IMHO, Java si zaslouzi nahradu, a Scala je v mnoha smerech pokrok).
Mj. GHC Haskell má oboje. Výhoda implicitních parametrů je, že můžete předávat normální hodnoty - například spojení do databáze. Navíc typové třídy v Haskellu dovolují (víceméně) pouze jednu instanci typové třídy pro jeden typ (program s více instancemi GHC AFAIK neslinkuje) - implicity ve Scale toto omezení nemají. Někdo sice říká, že toto omezení je výhodné, ale na druhou stranu někdy je užitečné (a přirozené) mít více instancí - například aditivní i multiplikativní monoid.
No rad bych aspon videl nejaky popis, jak pomoci implicitu ve Scale dosahnout aspon tehoz, co delaji typove tridy. Cetl jsem ten originalni Oderskeho clanek, ale byl mi nesrozumitelny. Stejne tak na tech vic instanci by to asi chtelo nejake lepsi priklady.
Jinak tu Oderskeho prednasku o Dotty jsem videl, ale moc jsem nerozumel, k cemu to vlastne dela. Ta tvoje poznamka o DOT to aspon trochu dovysvetluje, dik.
			 
			
			- 
				
No rad bych aspon videl nejaky popis, jak pomoci implicitu ve Scale dosahnout aspon tehoz, co delaji typove tridy. Cetl jsem ten originalni Oderskeho clanek, ale byl mi nesrozumitelny. Stejne tak na tech vic instanci by to asi chtelo nejake lepsi priklady.
V Haskellu:
import Data.List (sort)
data Osoba = Osoba { jmeno :: String }
  deriving (Show, Eq)
-- Mohli bychom odvodit i pres deriving, nicmene pro blizsi korespondenci
-- se Scalou nechame zvlast.
instance Ord Osoba where
  compare x y = compare (jmeno x) (jmeno y)
setrid :: Ord t => [t] -> [t]
setrid = sort
main :: IO ()
main = do
  let lide = [Osoba "Dana", Osoba "Alena", Osoba "Cenek"]
  print $ setrid lide
Totéž ve Scale:
case class Osoba(jmeno: String)
// Implicity pro třídu Osoba umístíme do companion objektu Osoba:
object Osoba {
  // Instance typové třídy Ordering. Ve skutečnosti obyčejná hodnota
  // typu Ordering[Osoba].
  // Hodnotu jsme zkonstruovali pomocí funkce Ordering.fromLessThan.
  implicit val usporadani: Ordering[Osoba] = Ordering.fromLessThan(_.jmeno < _.jmeno)
}
object Program {
  // Podmínka T : Ordering říká, že pro T musí
  // existovat instance typové třídy -
  // tj. implicitní hodnota typu Ordering[T].
  def setrid[T : Ordering](xs: List[T]) = xs.sorted
  def main(args: Array[String]): Unit = {
    val lide = List(Osoba("Dana"), Osoba("Alena"), Osoba("Cenek"))
    println(setrid(lide))
  }
}
Kdyby se nám standardní uspořádání na osobách nehodilo, můžeme definovat jinou implicitní hodnotu:
object Program {
  def setrid[T : Ordering](xs: List[T]) = xs.sorted
  implicit val jineUsporadani: Ordering[Osoba] = Ordering.fromLessThan(_.jmeno > _.jmeno)
  def main(args: Array[String]): Unit = {
    val lide = List(Osoba("Dana"), Osoba("Alena"), Osoba("Cenek"))
    println(setrid(lide))
  }
}
Jinak def setrid[T : Ordering](xs: List[T]) je zkratka za def setrid[T](xs: List[T])(implicit x: Ordering[T]) - hodí se, když implicitní parametr x nepoužíváme uvnitř funkce explicitně.
			 
			
			- 
				Uznávám, že dnes není těch důvodů pro Scalu tolik, jako v době, kdy jsem přecházel já (2010). Tehdy byla Java 6 a pokusy programovat v Javě funkcionálně byly trochu krkolomné. Dnes je tu Java 8 a je to o poznání méně krkolomné, byť zdaleka ne ideální.
Kdyby tehdy tu byla Java 8, nevím, jestli bych na Scalu přecházel. Ale z dnešního pohledu by mi to přišlo škoda, Scala má stále co nabídnout.
Actor model – to je mnohem obecnější záležitost, jednotlivé actory mohou být i na úplně jiném stroji. A jinak toto bylo ve Scale deprecated a doporučuje se používat actory z Akka.
Funkcionální programování – zkoušel jsem Javu 8 a nedá se to srovnávat.
* Třeba udělat z kolekce Stringů kolekci java.net.URL jde ve Scale snadno, v Javě musím řešit checked exceptions. Ne, že bych vyloženě neměl checked exceptions rád, ale dokud tu nebude pro ně dobrá podpora v lambda funkcích, budou komplikovat funkcionální programování.
* Myslím, že pro Scalu je – aspoň dnes – lepší funkcionální ekosystém.
Immutable typy – ano, dá se to dělat i v Javě a já to tak dělal. Místo case classes se dá použít Lombok, který sice neumí úplně všechno, co case classes (např. pattern matching by v Javě neměl smysl), ale to základní ano. Na druhou stranu je tu trošku problém s ekosystémem – například když buu v Javě chtít (de)serializovat JSON do objektů, tuto konstrukci mi snad žádná knihovna podporovat nebude. Ve Scale použiju upickle nebo Play-JSON. V Javě ani jeden z nich tak snadno nepoužiju, protože to chce makra. Stručně: V Javě s tímto přístupem spíše narazím.
Klíčové slovo val, kdy pak není možné měnit proměnnou - Java má final – ano. Varianta s final je ukecanější, ale v zásadě ano.
Akademická syntaxe – nevím, jestli je akademická, ale vyhovuje mi celkem. Je svým způsobem jednodušší: například v syntaxi není níc jako typecast či instanceof – místo nich máme metody asInstanceOf a isInstanceOf. Nemáme operátor pro sčítání, třída Int má metodu „+“. (Kompilátor to pak zkompiluje vhodným způsobem, takže se to přeloží na checkcast, iadd apod. a žádné volání metody v takovémto bytecode nebude.)
XML syntaxe – pokud si dobře vzpomínám, tak ta se má z core jazyka oddělit do samostatného modulu. Snad má být implementována pomocí maker a string interpolation.
Databáze – je tu například knihovna Slick, za kterou dnes stojí Typesafe.
K „neklidnému vývoji“ – nemám pocit, že by tato výtka byla dnes na místě. Před pěti rokama ano. Dnes, když vyjde mová minor (setinková) verze, ověřuje se, že je 100% kompatibilní. Když vyšla nějaká desetiknová verze, slibovali kompatibilitu zdrojáků, s výjimkou zavržených a experiemntálních fíčur. A Dotty? To je dnes samostatný jazyk. Co je dnes v Dotty, to se může – pokud se to osvědčí – dostat časem do Scaly. Ale tím pískovištěm dnes není Scala, ale právě Dotty. Není to naopak dobře?
Mám pocit, že ke klidnějšímu vývoji přispělo i založení Typesafe.
			 
			
			- 
				
V Haskellu:
...
Totéž ve Scale:
...
Diky za odpoved! Uz tomu trochu zacinam rozumet.
			 
			
			- 
				Když jsou ty svátky, tak to chce i něco kvalitního tady. Jak je na tom Scala dnes? Sem tam narazím firmu, kde ji ještě používají, ale nějaký velký boom asi už nepřijde. Nebo myslíte, že Scala pořád má co nabídnout? Nebo je lepší se poohlédnout po něčem jiném? Myslím proti Javě. Co třeba Go, to zdejší koumáci už někde určitě mají nasazené.
			
 
			
			- 
				
Nebo myslíte, že Scala pořád má co nabídnout?
Scala má určitě co nabídnout - a to nejen oproti Javě nebo C# (C# 7 je velmi složitý a moc toho nenabízí, Scala je složitá, ale alespoň nabízí řadu věcí, co jiné jazyky nemají), ale i třeba oproti Haskellu.
Co třeba Go, to zdejší koumáci už někde určitě mají nasazené.
Z pohledu vývoje programovacích jazyků je Go krokem cca 30 let nazpět.
			 
			
			- 
				Proti Haskellu má třeba co? Pokud jste to rozebírali, tak to stačí vypíchnout. Mně se líbí, že Scala jede na JVM. C# je pro mě mimo kvůli MS.
Právě Go si sem tam někdo pochvaluje, že odebralo takové ty novinky, které jen věci znepřehledňují. Podle mě to není pravda, ale neměl jsem na něj skoro žádný čas, takže těžko říct. Takže myslíš, že Go ani nemá cenu někam nasazovat? Nebo třeba jen kvůli výkonu?
			 
			
			- 
				Go má určitě taky co nabídnout. :)
Dokonce jsem přesvědčen, že si s Javou ani moc nekonkurují a spíš doplňují. Go určitě nemá takovou podporu knihoven jako Java, ale za poslední roky se situace hodně zlepšila a v oblasti, kde se Go používá, nic zásadního už nechybí.
Go je více určeno na systémové věci, systémové utility a pak pro web. Rozhodně bych v něm nedělal ekonomický systém, i když se najdou lidé, kteří to zkoušejí. S Javou pak Go sdílí jednoduchou křížovou kompilaci a snadné nasazení. V oblasti, kde je JVM zbytečnou zátěží, těžko hledat něco vhodnějšího.
Překážkou může být, že pochopení idiomatického Go může být pro Javistu problém.
			 
			
			- 
				
Proti Haskellu má třeba co? Pokud jste to rozebírali, tak to stačí vypíchnout. Mně se líbí, že Scala jede na JVM. C# je pro mě mimo kvůli MS.
Právě Go si sem tam někdo pochvaluje, že odebralo takové ty novinky, které jen věci znepřehledňují. Podle mě to není pravda, ale neměl jsem na něj skoro žádný čas, takže těžko říct. Takže myslíš, že Go ani nemá cenu někam nasazovat? Nebo třeba jen kvůli výkonu?
Jak kvůli výkonu? JVM je přece rychlejší, než fyzický procesor nad kterým běží. Nebo se zase něco změnilo?
			 
			
			- 
				
Proti Haskellu má třeba co? Pokud jste to rozebírali, tak to stačí vypíchnout.
Věci z OOP - např. podtypový polymorfismus (lze využít pro typové třídy nebo pro tagování - př. Int @@ Customer je podtyp Intu, který jde použít všude, kde je třeba Int, ale naopak nejde použít Int, když je vyžadován Int @@ Customer) nebo dědičnost. Nebo třeba to, že v jednom programu může být více instancí jedné typové třídy pro jeden typ.
Nebo to, že Scala je menší jazyk než GHC Haskell, kde se řada featur všelijak překrývá (např. implicitní parametry se překrývají s typovými třídami nebo víceparametrické typové třídy se překrývají s typovými třídami s asociovanými typy) - což dává prostor k nekompatibilitám - např. je třeba dělat dvě verze některých knihoven.
Mně se líbí, že Scala jede na JVM. C# je pro mě mimo kvůli MS.
Oracle je možná ještě horší než MS (viz třeba Oracle finally targets Java non-payers – six years after plucking Sun
Thought Java was 'free'? Think again (http://www.theregister.co.uk/2016/12/16/oracle_targets_java_users_non_compliance)) a CLR  je pod MIT licencí, zatímco OpenJDK je pod GPL.
Právě Go si sem tam někdo pochvaluje, že odebralo takové ty novinky, které jen věci znepřehledňují. Podle mě to není pravda, ale neměl jsem na něj skoro žádný čas, takže těžko říct. Takže myslíš, že Go ani nemá cenu někam nasazovat? Nebo třeba jen kvůli výkonu?
Zásadní potíží Go je, že uživatel nemůže vytvářet nové generické typy. Velmi dobrou alternativou ke Go může být v brzké době OCaml (až se do hlavní distribuce zamerguje podpora pro paralelní běh) - i z hlediska výkonu viz Golang’s Real-time GC in Theory and Practice (https://blog.pusher.com/golangs-real-time-gc-in-theory-and-practice/).
Takže myslíš, že Go ani nemá cenu někam nasazovat?
Já osobně bych to nedělal (hodně cením vyjadřovací sílu jazyka), ale je řada lidí, kteří jsou s Go spokojeni.
			 
			
			- 
				
 CLR  je pod MIT licencí
Oprava: Má být .NET Core místo CLR.
			 
			
			- 
				Ještě tu nikdo nezmínil Kotlin. Ten v podstatě kombinuje to nejlepší/nejdůležitější ze Scaly a Groovy a zároveň zachovává bezproblémovou obousměrnou kompatibilitu s Javou. Co se týče Androidu, tak tam se s trochou nadsázky pomalu stává mainstreamem.
			
 
			
			- 
				Super, díky za info. Přečtu a prozkoumám.
			
 
			
			- 
				Ak ta zaujima funkcionalne programovanie, tak si pozri aj jazyk Clojure, ktory tiez bezi na JVM. Podla mna je hodne dobry a celkom dobre sa v nom programuje.
			
 
			
			- 
				
Co třeba Go, to zdejší koumáci už někde určitě mají nasazené.
Z pohledu vývoje programovacích jazyků je Go krokem cca 30 let nazpět.
 Nicméně stále je překvapivě dobře použitelné.
			 
			
			- 
				
...
...java...
...
No to zase bude flejm...
			 
			
			- 
				Dost kritiky Scaly v tomto vlakne je nepravdiva a/nebo neaktualni. XML jazyk opousti (nebo uz opustilo?), komunita si naopak stezuje, ze novych veci je pomalu a vyvoj je prilis pomaly (takze pro to prave korporatni pouziti je uz asi zrala :-\). Pouzivat Akku z Javy je hruza - strasne moc boilerplatu. Je to podobne jako s Play, pokud nepouzijete Scalu, tak to neni o nicem, protoze nevyuzijete nejvetsi vyhody knihovny.
Syntaxe Scaly me prijde lepsi nez treba Javy, mene ukecana, vice k veci. Neprijde mi dobry ten pristup "on ten boiler plate muze vygenerovat IDE" - proc tam musi byt boilerplate, kdyz se stejne vzdy generuje? Akorat to IMO znecitelnuje kod.
Python nemam rad a stejne tak pristup "pouze jeden zpusob". Ja mam radeji na vyber a pouziju nejvhodnejsi pristup pro dany problem, ne ze jsem omezeny na jeden univerzalni pristup a ten je mi vnucen jako "vzdy nejlepsi pro kazdy problem". Kvuli tomu treba v Pythonu je FP dost tragicke, mel bych psat asi spis "FP".
A argument, ze s Java 8 jde krasne psat FP stejne/lepe nez ve Scale ci ze s Java 8 uz Scala neni potreba? ;D Uz jsem na nazor podobneho ignoranta reagoval na quore, tak to jen znovu shrnu. V Jave stale hodne veci chybi, napr. lepsi typovy system (treba implicits, path-dependent typy), case classes, for comprehensions, pattern matching s extractory (nejen match statement, ale i pro val), neprekonane kolekce* (nesrovnatelne s Javou, kde se vse musi vselijak obalovat a vybalovat), moznost psat DSL, strucnejsi syntaxe (tzn. mene nevyznamoveho balastu). Mam pocit, ze i uplne zaklady typu Option (v Jave myslim Optional) mely v Jave dost kriticke problemy. Problem lamdb a vyjimek v Jave tu uz nekdo uvadel.
Scala rozhodne neni dokonala, ma problemy (jak nekdo zminil, obcas bugy v prekladaci, velikost std. knihovny [problem na starsich Androidech], problemy s obfuscatory, spatna podpora maker v IDEA, ne vzdy funguje typova inference, pomalejsi preklad), ale jeji vlastnosti ty drobne problemy v pohode prevazi (nemalo jich vyresi prave Dotty). Scala je stale, co se funkci tyce, mnoho kroku pred Javou.
*: Po pravde jsem zatim v zadnem jinem jazyce nenasel lespi std. knihovnu pro kolekce (obsahem, inuitivnosti, konzistenci [napr. flatMap pro Option i List]).
A jen tak mimochodem ani ten Haskell neni nejaky zlaty gral. Si hraju s prekladacem a intepretem jazyka v Haskellu a treba records jsou dost za trest - Haskell nepodporuje (primo) pretezovani funkci, takze v jednom namespacu zadny record (neco jako struct nebo case class) nesmi mit stejne pojmenovane fieldy, protoze pak koliduji jmena getteru (pripadne jmena lens). (Ano, vim, jde pouzit type classy, ale co jsem cetl, tak je to bad practice. Pouzivam kombinaci importu a qualified importu a kvuli tomu pribylo dost boiler platu a navic s kazdym novym record se musi upravovat build file :( ) Trochu pokukuji po OCamlu, ktery vypada, ze tyto problemy nema, ale zatim jsem nemel moc casu se na neho podivat blize.
			 
			
			- 
				
*: Po pravde jsem zatim v zadnem jinem jazyce nenasel lespi std. knihovnu pro kolekce (obsahem, inuitivnosti, konzistenci [napr. flatMap pro Option i List]).
Bohužel kolekce ve Scale mají i svou temnou stranu. Například co přesně dělá následující kód?
Map(8 -> "osm").map(_._1)
Jaký je statický typ? Jaká kolekce je vrácena skutečně? Pokud tomu kódu chceme porozumět, je třeba si uvědomit, že se jedná o zkratku za
Predef.Map.apply(Predef.ArrowAssoc(8).->("osm")).map(((x$1) => x$1._1))(Iterable.canBuildFrom)
tedy statický typ je Iterable[Int] a vrácená kolekce je List. Na první pohled to není vůbec zřejmé, ale když jde o výkon, je důležité to vědět.
			 
			
			- 
				BTW nedávno jsem sepsal poznámky popisující pár základních vlastností Scaly, třeba se to někomu bude hodit:
- Základy Scaly (https://github.com/radekm/notes-cs/blob/master/2016/Zaklady%20Scaly.pdf)
 - Základy Scaly – 2. část (https://github.com/radekm/notes-cs/blob/master/2016/Zaklady%20Scaly%202%20-%20poznamky.pdf)
 
			 
			
			- 
				Jiste, kolekce ve Scale nejsou dokonale (ostatne typovy system zaplatil cenu za snahu byt nejak kompatibilni s Javou a nutnosti behu na JVM), ale co do pouzitelnost jsem opravdu nenasel lepsi. Rozsirovat nejakou Scala kolekci neni take uplne primocare a bez znalosti implementacnich detailu celkem obtizne (ano, i to jsem si zkusil :D). K tomu vykonu - nepouzivaji se v pripade opravdove starosti o vykon spise specializovane knihovny?
Jeste jsem zapomnel na to, ze v Jave jsou lambdy, kdezto ve Scale closure (doufam, ze jsem to neprohodil). V Jave se v lambde nemuzete odkazovat na vnejsi promennou (myslim funguje pouze pro final, nebo takove podobne omezeni), ve Scale to neni problem (podobne jako v JavaScriptu).
Moc jsem Go ani Kotlin nestudoval, ale neprisly mi nicim moc vyjimecne. Prinasi neco navic oproti treba te Scale? Jedinne o cem v Kotlinu vim, co vypada dobre, je podpora proxy primo v jazyce (potreboval jsem to nekolikrat pri praci s Javovskymi tridami, ktere jsem nemohl upravovat). Go vypada jako tuctovy jazyk, podle slov jejich vyvojaru zamereny na rychle nauceni se, coz moc jako kvalitu nevnivam. Proc mit dalsi Python (nebo cokoliv jineho), kdyz nauceni se jazyka mi potrva zlomek casu (treba tyden/mesic), nez samotna prace v jazyce (roky)?
The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.
– Rob Pike
Jazyk pro lopaty?
PS: Psani sem me donutilo si neco o Go precist a teda ten jazyk je tak neuveritelne zpatecnicky, ze se az divim, ze s tim prisel Google.
Why Go’s design is a disservice to intelligent programmers (http://nomad.so/2015/03/why-gos-design-is-a-disservice-to-intelligent-programmers/)
			 
			
			- 
				Na skalu jsem se vyzadekijoval jen jsem viděl co všechno se v ní dá dělat. V tomhle jazyce se da neuveritelne prasit a v praxi ma misto jen ve velmi uzkem spektru aplikaci a situaci. Pocinaje Javou 8 a lambdama je uz uplnemimo misu. Navic vsechny testy srovnavajici performance ktere jsem videl ukazuji scalu jako pomalejsi nez javu.
			
 
			
			- 
				Prasata mate vsude, to neni nejaka nevyhoda jazyka. I v tom hloupouckem a omezenm Go se prasi pomoci reflexe, aby se prekonaly omezeni jazyka. Ja budu mit radeji jazyk, kde mam vetsi volnost a nemusim prasit z duvodu, ze to jinak nejde.
Jste si asi neprecetl vyse, co vsechno Java 8 pro rozumne praktikovani FP postrada. Jiste, pokud nechcete FP, vice ficur, expresivnejsi jazyk, lepsi typovy system, tak Scala moc neprinese, ale to jste v prve rade Scalu ani nemusel zvazovat, kdyz vam vyhovuje uzvanena Java se svymi omezenimi (o tom snad tento topic neni).
Ano, ve vetsine benchmarku je Scala o neco malo pomalejsi (nic dramatickeho), ale to se da cekat. Musim (spise pro pobaveni) ale rict, ze existuji i benchmarky, kdy je Scala rychlejsi nez Java (tusim, kdyz se benchmark lepe strefi do datovych struktur a optimalizaci prekladace Scaly).
			 
			
			- 
				Jo to je sice hezke ze mas rad jazyk ve kterem mas volnost, nez budes muset pracovat po programátotech, kteří tu volnost měli taky a obzvláště když jsou z Indie nebo jsou to prOstě jen úplní začátečníci.
To si taky rikam, ze javascript je vlastne strasne fajn, dokud nemusim delat neco v appce kde se prehnalo stado prasat.
Protoze porad se jeste da vyznat v aplikaci, kterou psali indie-like programatori, kdyz ta aplikace pouziva jednoduche konstrukce a je napsana "flat" - a k tomu te primeje Java - nez v aplikaci psane radobyinteligentim koumakem, ktery do ni zasmudrchava jednu radobychytrou konstrukci za druhou, az je z toho gorDonsky uzel - a to nechci videt co by sesmolil ve scale.
			 
			
			- 
				Myslím, že se tu střetávají světy teoretické, které jazyky studují, a praktické, které v nich dodávají složité systémy s dlouhou historií i neustále se měnícími požadavky. Obojí je důležité, např. FP v javě ušetří spoustu času ryzímu praktikovi i ve velikém legacy systému, kdy rychle naráží na omezení a těší se na další verze, kde už snad budou omezení volnější (jo, checked exceptions). Stejně tak by ocenil hodnotové typy, to by zabránilo mrakům hloupých chyb. A reifikovaná generika mohou podstatně zpřehlednit kód, někdy se prostě to instanceof potřebuje. Všeho toho se java dočká http://literatejava.com/java-language/value-types-list-int-coming-java-10/ a hlavně díky světu teoretickému.
Nedávno jsem potřeboval zásadně zrychlit legacy kód se spoustou jednoduchých výpočtů nad velikými kolekcemi (stovky tisíc položek). Smyčky jsem jednoduše přehodil do streamů s lambda filtry a foreach, do nejrozsáhlejších jsem použil paralelní streamy a kolekce zaměnil za concurrent verze. Za necelé dvě hodiny celkem nenáročných úprav se doba výpočtu původně jednovláknového zpracování zkrátila na 8jádře ani ne na desetinu. A produkční server má těch jader 32. Jsem přesvědčený, že bez teoretických pokroků ve FP a jejich následného transferu do praxe v javě by tohle vůbec nebylo možné.
			 
			
			- 
				
Jo to je sice hezke ze mas rad jazyk ve kterem mas volnost, nez budes muset pracovat po programátotech, kteří tu volnost měli taky a obzvláště když jsou z Indie nebo jsou to prOstě jen úplní začátečníci.
To je možné, ale ne každý musí po takových programátorech pracovat.
Pokud si zvolíte jednoduchý jazyk, kde chybí řada abstrakcí, tak i když jste skvělý programátor, snadno skončíte s kódem, který není extra přehledný (protože nemáte k dispozici potřebné abstrakce).
			 
			
			- 
				
To je možné, ale ne každý musí po takových programátorech pracovat.
Bohužel na déle běžících rozsáhlých projektech je to spíše pravidlo, než výjimka.
			 
			
			- 
				Můžu se zeptat, kde jste přišli k tolika informacím o FP? Protože není problém se to naučit, spíše kde to využít? Scala docela frčí i u nás a dají se najít pozice, ale takový záběr, jako máte, není úplně běžný. Když to srovnám s Javou, tak běžný Java vývojář o Javě moc neví, takže úroveň vašich znalostí je dost nad průměrem.
			
 
			
			- 
				Rozhodně to nebyla otázka na mě, ale běžné FP v javě se slušnější vývojář naučí s podporou IDE (idea to rovnou nabízí) za pár použití, není to vůbec nic složitého. A postupně přidává Optional atd. Časem začne prskat, že má legacy kód checked exceptions a nemůže si FP usnadňovat práci. Kód se zkrátí a zrychlí.
Nechápu, jak architekt s tvým záběrem může toto nepoužívat a nevyžadovat. Ono to zřejmě bude všechno trochu jinak....
			 
			
			- 
				Na všechny tady :)
FP je až v 8, takže souhlasím, že naučit se to může i nováček. Problém je s tím, že dřív to tam nebylo a zároveň pokud nemáš základy FP, tak ty konstrukce nejsou moc příjemné. Další věc je, že jsou projekty, kde se jede na 6 a možná se brzy přejde na 7.
Jakože Java architekt bude dávat do projektů Scalu jen tak, aby byl cool? Jazyk je na Javě to méně podstatné. Nástroje a knihovny z toho dělají špičku.
			 
			
			- 
				FP jsme v životě nepoužívali a naučit se to v javě bylo triviální. Už jsem ti to psal několikrát. Obávám se, že je to tím, že to sám neumíš, protože sám nic neprogramuješ.
Náš systém má první commit v r. 2002, 32 tis. commitů, nějakých 10 tis. tříd a udržovat jej upgradovatelný na novou javu je jednou z důležitých priorit. Samozřejmě to obnáší i upgrade používaných knihoven. S každou novou verzí JVM se rychlost původního neupraveného kódu zvedla. Levný zisk. Priority přece ze své pozice určuješ ty, tak proč se oháníš omezeními v tvé pravomoci...
Vývojáři chtějí dělat na moderních technologiích, ne na dinosaurech (stejně jako chtějí dělat na pořádných mašinách a pořádných monitorech). Když už se musí vrtat ve starém kódu (to už tak prostě je), tak jej chtějí posouvat dopředu, aby do něj mohli svůj kód psát moderně a mohlo je to bavit.
			 
			
			- 
				Nevím, jak to může být triviální, když je to jiný přístup k programování :D Právě takové to učení z Idei mi přijde nejhorší. Sice nevím proč, ale udělal jsem to, co mi řekla.
Takže pokud někde mají zaplacený aplikáč, který jede na komerční Javě, tak já jim řeknu, že jsou lopaty a smažu jim ho, ne? :D Samozřejmě tyhle projekty skoro nedělám, ale když prostě někam přijdeš, je to tam a třeba děláš jen nějakou maličkost na pár měsíců, tak proč ne. Ne všude můžeš rozjet projekt na nejnovějším Bootu a 5.
Já znám vývojáře, kteří chtějí dělat na kvalitních věcech a technologie není moc podstatná. Asi každý preferujeme jiné lidi. Starý dobře napsaný kód bude pořád hezký.
			 
			
			- 
				
Nevím, jak to může být triviální, když je to jiný přístup k programování :D
FP v javě využiješ jen v některých situacích, párkrát si to vyzkoušíš a pak už ti samo přijde, kdy by se to ti to hodilo. Typicky krátké kusy kódu, které se dřív řešily pomocnými třídami, často třeba enumy s metodami. Ve streamech je použití taky jednoduché a složitější kód si z lambdy stejně vytáhneš do metody, aby v tom nebyl bordel.
Právě takové to učení z Idei mi přijde nejhorší. Sice nevím proč, ale uděal jsem to, co mi řekla.
Kdyby sis to místo žvanění raději vyzkoušel. Idea ti pomůže hlavně se syntaxí a s maximálním zjednodušením kódu, sama za tebe smyčku do paralelizovatelného streamu neupraví. Ale rovnou ti třeba nabídne referenci na metodu místo ukecanějšího volání.
Takže pokud někde mají zaplacený aplikáč, který jede na komerční Javě, tak já jim řeknu, že jsou lopaty a smažu jim ho, ne? :D Samozřejmě tyhle projekty skoro nedělám, ale když prostě někam přijdeš, je to tam a třeba děláš jen nějakou maličkost na pár měsíců, tak proč ne. Ne všude můžeš rozjet projekt na nejnovějším Bootu a 5.
To je tvůj problém, jakou děláš práci. Já mám projekt své firmy pod plnou kontrolou a mohu si to udělat tak, jak potřebuju. Ale samozřejmě nečekám, že mi někdo bude platit za žvanění na rootu v pracovní době 300 litrů. Také svoje lidi nenazývám lopatami, ani začátečníky. A věř mi, že si hodně vybírám, protože mě s nimi musí bavit dělat. A  baví, hodně.
Starý dobře napsaný kód bude pořád hezký.
To rozhodně. Nicméně když do něj doplníš generika, bude i bezpečnější a příjemnější na používání. A když při jeho úpravách a rozšířeních (nedávno ses tu kasal, že děláš "nové featury") použiješ moderní prostředky, bude rychlejší a možná některé jeho části půjde provozovat i paralelně a využívat tak naplno ty desítky jader v dnešních serverech.
Jenže je otázka, zda tebe úspěch projektů tvých klientů vůbec zajímá. Vykešovat a táhnout dál, za jiným manažerským hejlem, co ti dá za žvanění a vytahování balík, protože sám má za žvanění balík ještě větší.
			 
			
			- 
				Ahaaa, tak to jo. Myslím, že takhle to nefunguje.
Vím, co umí Idea, ale nemám rád lopaty, které říkají, že něco umí a pak z nich vypadne max to napovídání v Idea. Jde o to chápat principy.
Jsem ti jen vysvětlil, že ne všude mají cool Java 8. Demo pro zákazníka také můžu udělat na beta knihovnách a všichni budou koukat. Samozřejmě to nemůžu dát do produkce.
Pokud platíš lopatám málo, tak je jasné, že si musíš dobře vybírat.
Tzv. žvanění je důležité. Alespoň víš, co se dělá. Lopata si 12 hodin něco píše do počítače a nikdo neví.
			 
			
			- 
				
Navic vsechny testy srovnavajici performance ktere jsem videl ukazuji scalu jako pomalejsi nez javu.
V řadě případů však může být situace opačná - např., když vhodně použijete specializaci generik (nebo miniboxing nebo dotty linker). Jiným příkladem je fúze ve streamovacích knihovnách - viz třeba knihovna strymonas (https://github.com/strymonas/strymonas.github.io/raw/master/strymonas.pdf), která je na mikrobenchmarcích až 10x rychlejší než streamy z Javy 8.
			 
			
			- 
				
Si hraju s prekladacem a intepretem jazyka v Haskellu a treba records jsou dost za trest - Haskell nepodporuje (primo) pretezovani funkci, takze v jednom namespacu zadny record (neco jako struct nebo case class) nesmi mit stejne pojmenovane fieldy, protoze pak koliduji jmena getteru (pripadne jmena lens). (Ano, vim, jde pouzit type classy, ale co jsem cetl, tak je to bad practice. Pouzivam kombinaci importu a qualified importu a kvuli tomu pribylo dost boiler platu a navic s kazdym novym record se musi upravovat build file
Recordy v haskellu jsou takové, jaké jsou, protože nikdo neví, jak to udělat líp :( V GHC8 jsou DuplicateRecordFields, ale moc nevím, na co to je, když stejně v jakémkoliv větším projektu začne člověk používat lensy. TypeClass na lensy použít nějak jde, IMO bad practice to ani není, ale když je pak víc recordů přes různé moduly, tak asi ten boilerplate nebude úplně jednoduchý - nějaký TemplateHaskell makro by to asi vyřešlo, ale myslím, že nic takového zatím není. Koukal, jsem, jak to je řešeno v purescriptu a vlastní používání mi připadá ještě horší.
 Navíc typové třídy v Haskellu dovolují (víceméně) pouze jednu instanci typové třídy pro jeden typ (program s více instancemi GHC AFAIK neslinkuje) - implicity ve Scale toto omezení nemají. Někdo sice říká, že toto omezení je výhodné, ale na druhou stranu někdy je užitečné (a přirozené) mít více instancí - například aditivní i multiplikativní monoid.
No já Scalu neumím, takže mi není moc jasné, jak tohle funguje....  E.Kmett to popsal tak, že třeba Set nebo Map díky různým instancím nedokáže garantovat, že se to setřídění nezmění - je to tak, nebo se to v poslední době nějak zlepšilo? 
			 
			
			- 
				
E.Kmett to popsal tak, že třeba Set nebo Map díky různým instancím nedokáže garantovat, že se to setřídění nezmění - je to tak, nebo se to v poslední době nějak zlepšilo?
Nevím, co přesně myslel - samo od sebe se uspořádání nezmění. Problémy mohou nastat, když máte funkci, která pracuje se dvěma množinami a obě mají jiné uspořádání, ale funkce předpokládá, že obě mají stejné (vím, že některé funkce ve standardní knihovně jsou na to ošetřeny, nevím, zda všechny).
Navíc podobná věc se mohla (nevím, zda stále může??) stát i v GHC Haskellu - viz příklad na konci http://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/ - a tam na to funkce nejsou připraveny.
			 
			
			- 
				
Si hraju s prekladacem a intepretem jazyka v Haskellu a treba records jsou dost za trest - Haskell nepodporuje (primo) pretezovani funkci, takze v jednom namespacu zadny record (neco jako struct nebo case class) nesmi mit stejne pojmenovane fieldy, protoze pak koliduji jmena getteru (pripadne jmena lens). (Ano, vim, jde pouzit type classy, ale co jsem cetl, tak je to bad practice. Pouzivam kombinaci importu a qualified importu a kvuli tomu pribylo dost boiler platu a navic s kazdym novym record se musi upravovat build file
Recordy v haskellu jsou takové, jaké jsou, protože nikdo neví, jak to udělat líp :( 
Co takhle je umístit do různých namespace?
			 
			
			- 
				Radku, ty ten výzkum používáš k čemu? Je to třeba normálně v práci a ostatní to ocení? A nebo to máš rád sám, takže třeba v práci bys dělal v jednom FP jazyce a ostatním se věnoval jako hobby?
			
 
			
			- 
				Co se tyce knihoven, tak celkem dost jich lze ve Scale pouzivat normalne jak z Javy. Na ty bezne veci jsou casto knihovny primo pro Scalu, se kterymi se ze Scaly pracuje prijemneji (napr. zadne null, Scali kolekce, DSL atp.). Co jsem se dival a zkousel (a cetl, osobne nevyvijim ve Scale pro penize), tak treba webove veci s Play si lidi pochvalovali, podobne treba DB pristup se Slick, vetsina i Akku. Kdo chce vice hardcore FP tam ten muze sahnout po ScalaZ, Cats, Shapeless atp. Ale nejak do hloubky to zhodnotit nedokazu, pouze muzu rict, ze jsem zatim na to domaci vyvijeni* nenarazil na pripad, ze by Java knihovnu mela a Scala ne (at uz nativni, nebo stejnou Javi, ikdyz ty byvaji celkem otravne na pouzivani, kdyz jste zvykli na lepsi).
*: Normalni veci typu web crawler, multiplatformni GUI klikatko, pristup k souborum, JSON, Android (predevsim libGDX), jednoducha server-client aplikace.
Jak jsem psal vyse, pokud najimate hloupe nebo line vyvojare, nebo je nechcete zaucovat do lepsiho jazyka, ktery v zaveru poskytne nepreberne vyhod (vyssi abstrakce = mene kodu, lepsi citelnost, znovupouzitelnost), tak IMO najimate jen "lopaty" a casem se vam to vymsti. Podobne tragicky to vidim, kdyz se nesmi psat testy (o to horsi, pokud jde o dynamicke jazyky). Ano, muzete prejit na Go a najmout prvni skupinu mladych uchazecu, kteri v tom umi napsat Hello world, ale podle toho pak budou vypadat vase aplikace. Prasit se da ve vsem. Treba nedavno jsem videl kod na zjisteni kolize bodu vuci trojuhelniku v 2D v celych cislech, bylo to tusim v Jave a bylo to resene cykly pres vsechny body trojuhelniku...
Si hraju s prekladacem a intepretem jazyka v Haskellu a treba records jsou dost za trest - Haskell nepodporuje (primo) pretezovani funkci, takze v jednom namespacu zadny record (neco jako struct nebo case class) nesmi mit stejne pojmenovane fieldy, protoze pak koliduji jmena getteru (pripadne jmena lens). (Ano, vim, jde pouzit type classy, ale co jsem cetl, tak je to bad practice. Pouzivam kombinaci importu a qualified importu a kvuli tomu pribylo dost boiler platu a navic s kazdym novym record se musi upravovat build file
Recordy v haskellu jsou takové, jaké jsou, protože nikdo neví, jak to udělat líp :( 
Co takhle je umístit do různých namespace?
No, to ted pouzivam, ale neni to zadna slava:
Pouzivam kombinaci importu a qualified importu a kvuli tomu pribylo dost boiler platu a navic s kazdym novym record se musi upravovat build file
Jsem tak trochu rozmazleny z Java sveta (ve Scale je to stejne), ze pridam soubor a on se sam prida do buildu. Kdyz se pak pracuje s lens (nebo i jen temi "getter" funkcemi), tak se musi pouzivat qualified import na ne a je otravne a IMO celkem neprehledne.
Priklad jak to mam nyni (Orb a Vel jsou qualified imports, IMO to celkem kazi retezeni lens, ktere mohlo byt krasne intuitivni - nyni je tecka oddelovac importu i kompozice funkci):
oldVelX = orb^.Orb.velocity.Vel.x
A jak by to mohlo vypadat, kdyby Haskell umel pretezovani funkci (to by pak ty recordy byly i normalne pouzitelne):
oldVelX = orb^.velocity.x
Pouzivat type classy k tomuto ucelu mi prijde dost neprakticke (navic ani nevim, zda to vyresi problemy s kolizemi jmen auto-generovanych lens, tipl bych, ze spis nevyresi) a jak jsem psal, na vice mistech jsem cetl, ze pouzivat je vylozene k pretezovani funkci je bad practice, tak nevim...
Jako mozna neco delam a/nebo chapu spatne, jsem vecny Haskell zacatecnik, ktery se v tom pro zabavu placa :D.
			 
			
			- 
				
Priklad jak to mam nyni (Orb a Vel jsou qualified imports, IMO to celkem kazi retezeni lens, ktere mohlo byt krasne intuitivni - nyni je tecka oddelovac importu i kompozice funkci):
oldVelX = orb^.Orb.velocity.Vel.x
A jak by to mohlo vypadat, kdyby Haskell umel pretezovani funkci (to by pak ty recordy byly i normalne pouzitelne):
oldVelX = orb^.velocity.x
Haskell se teprve učím, ale měl jsem spíš takovou představu:
oldVelX = orb^.Vel.x
Pleonasmy při programování totiž moc rád nemám a vyhýbám se jim, jak jen to jde.
Otázkou samozřejmě je, zda by to v této podobě fungovalo. Proč oldVelX není součástí modulu Vel? Pak by to bylo jen
oldX = x
			 
			
			- 
				
oldVelX = orb^.Orb.velocity.Vel.x
Haskell se teprve učím, ale měl jsem spíš takovou představu:
oldVelX = orb^.Vel.x
Pleonasmy při programování totiž moc rád nemám a vyhýbám se jim, jak jen to jde.
Otázkou samozřejmě je, zda by to v této podobě fungovalo. Proč oldVelX není součástí modulu Vel? Pak by to bylo jen
oldX = x
Ehm, asi nechapu. Ten zapis nelze zjednodusit (ne bez upravy importu, pripadne modulu s recordy), "Orb.velocity" je lens (https://hackage.haskell.org/package/lens) pro field "velocity" v "OrbState" record a "Vel.x" je lens pro field "x" ve "Velocity" record. Vzhledem k tomu, ze mam vice zaznamu, kde se vyskytuje field "x" (v mem pripade to "x" je lens, ale to je celkem jedno, ikdybych nepouzil lens tak chci "getter" a ten se bude jmenovat stejne), tak nemohu importovat vse z "Velocity" modulu, protoze bych dostal i "x :: Velocity -> Int" a to by kolidovalo s jinou fkci pro ziskani "x" z jineho zaznamu, napr. "x :: FilePos -> Int".
Mozna bych to mohl vysperkovat pouzitim mezer, ale porad je to IMO tezkopadne a hure prehledne.
Verze se zduraznenim, co je get operace a kompozice a co je namespace (ty jsou bez mezer).
oldVelX = orb ^. Orb.velocity . Vel.x
"oldVelX" se pouziva pri vypoctu zmeny stavu interpretu (neni to top level funkce) a tak mi prislo vhodnejsi umistit fci vedle ostatnich funkci interpretu, ktere se take zabyvaji zmenou stavu. A stejne to neresi problem, pokud se v "OrbState" pouziva dalsi zaznam, ktery ma field "x" (nebo jiny kolidujici), akorat jsem problem presunul jinam - z vyssi vrsty do nizsi vrstvy - do modulu s "OrbState" funkcemi.
Mozna se vyjadruju blbe. Jak pisu, taky se to ucim :).
PS: Tady jsou ty importy:
import           Runtime.Data.OrbState              -- pouze typ, aby se nemuselo psat OrbState.OrbState
import qualified Runtime.OrbState            as Orb -- pomocne veci. qualified proto, aby napr. fce "position" nekolidovala s jinou fci pojmenovanou "position"
			 
			
			- 
				Omlouvam se za predchozi off-topic, ted se pokusim o neco vice on-topic.
Funkcionální programování - nevím jestli s příchodem Javy 8 a třídy java.util.Stream to je ještě nějaká výhoda oproti Javě.
Ok, tak napr.: Ma Java nejakou lens knihovnu pro immutable typy? Scala ma treba Monocle (mnoho funkcionality, nejen lenses, ale take narocnejsi na nauceni se) nebo QuickLens (jednoduche, primocare, funkcni).
Immutable typy - taky věc, co se dá udělat i v Javě, prostě budu mít jen konstruktory a žádné metody na modifikaci. 
Jiste, "da" se udelat, asi jako OOP v C, nebo garbage collector pro ASM...
A jak budete resit treba takovou prkotinu jako vytvareni noveho objektu se zmenenym jednim fieldem? Rucne si psat potrebne metody vracejici kopii objektu se zmenou? Ve Scale to za vas udela prekladac copy metodou, kterou navic muzete "zmenit" v kopii vice fieldu. Nebo pouzivat Lombok? Ktery ma nevyhody, jako napr. ze IDE s nim muze mit problemy, nebo ze i pres znacne usnadneni tam stale je boiler-plate (co jsem se dival, tak pro to kopirovani dve volani metody navic).
Actor model - po vzoru Erlangu lze mít objekty, které čekají na zprávy a ty potom zpracovávají. Tipuju, že to bude implementované teda nějak tak, 
že po spuštění aplikace napsané ve Scale tam bude několik vláken, které budou sloužit pro zpracovávání zpráv z front jednotlivých Actorů.
Tohle by mělo být normálně možné udělat i v Javě, není to jakoby  vlastnost, které v Javě nelze docílit. 
<Copy&paste prvni odstavec odpovedi k predchozimu bodu.>
    public static class Greeter extends UntypedActor {
        String greeting = "";
        public void onReceive(Object message) {
            if (message instanceof WhoToGreet)
                greeting = "hello, " + ((WhoToGreet) message).who;
            else if (message instanceof Greet)
                // Send the current greeting back to the sender
                getSender().tell(new Greeting(greeting), getSelf());
            else unhandled(message);
        }
    }class Greeter extends Actor {
  var greeting = ""
  def receive = {
    case WhoToGreet(who) => greeting = s"hello, $who"
    case Greet           => sender ! Greeting(greeting) // Send the current greeting back to the sender
  }
}To vam fakt ta Javi verze prijde hezci a lepe citelna? Me rozhodne ne.
 Klíčové slovo val, kdy pak není možné měnit proměnnou - Java má final
val ve Scale je vychozi a kratke, naopak pokud mame neco jako "Int final a = 4;" tak to final je navic a tudiz vychozi stav je mutable, coz znaci, ze FP je v jazyku neco navic => neni pro FP prizpusoben.
Akademická syntaxe - ta syntaxe je prostě taková, aby to nevypadalo jako Java :)
Ciste subjektivni. Cilem naopak bylo, aby to bylo hodne podobne Jave, coz pri nepouzivani FP a jen OOP celkem funguje (syntaxe je v tom pripade pomalu 1:1). Jako jestli mate problem s tim, ze genercike typy maji parametry v [] misto <>, nevim, pripada mi to jako prkotina. Nepovinne stredniky mi prijde velmi sympaticke v kazdem jazyce. Rozdily na teto nejnizsi urovni jsou opravdu velmi male.
Nechci, aby to vypadalo jako nějaký hejt Scaly
Tak to presne pusobi - vetsina bodu akorat znaci uplnou problematiky a/nebo Scaly.
, ale opravdu by mě zajímalo, proč bych to měl chtít na něco použít místo Javy, když bych si musel zvykat na tu syntaxi. 
To zni jako nejake narky studentika, vzdyt ta zakladni syntaxe je, jak jsem psal, pomalu 1:1 mapovani na Javu. Vetsina (vse?) je akorat kratsi, je mene zavorek, slozenych zavorek, stredniku a dalsi nevyznamove omacky. Jiste, pokud mluvite o implicits, path-depedent typech a dalsi magie s typy, tak tam se to bude lisit, protoze Java nic takoveho nema :).
Samozřejmě můžu dát pročítat články na netu, ale nějaká diskuze nemusí být od věci :).
Doporucil bych si nejdrive precist o zakladech FP, protoze z vaseho prispevku je patrne, ze vam zalostne chybi (ne, pouzivani funkcni/metod nutne neznamena FP pristup). Take bych rad poznamenal, ze FP ve Scale bez dalsich knihoven je myslim spise zakladni (tvurce to zamyslel pro bezne vyvojare, nechtel z toho mit dalsi Haskell). Pokud chcete videt poradne FP, tak se podivejte na ScalaZ ;).
			 
			
			- 
				
Ehm, asi nechapu. Ten zapis nelze zjednodusit (ne bez upravy importu, pripadne modulu s recordy), "Orb.velocity" je lens (https://hackage.haskell.org/package/lens) pro field "velocity" v "OrbState" record a "Vel.x" je lens pro field "x" ve "Velocity" record. Vzhledem k tomu, ze mam vice zaznamu, kde se vyskytuje field "x" (v mem pripade to "x" je lens, ale to je celkem jedno, ikdybych nepouzil lens tak chci "getter" a ten se bude jmenovat stejne), tak nemohu importovat vse z "Velocity" modulu, protoze bych dostal i "x :: Velocity -> Int" a to by kolidovalo s jinou fkci pro ziskani "x" z jineho zaznamu, napr. "x :: FilePos -> Int".
Mozna bych to mohl vysperkovat pouzitim mezer, ale porad je to IMO tezkopadne a hure prehledne.
Verze se zduraznenim, co je get operace a kompozice a co je namespace (ty jsou bez mezer).
oldVelX = orb ^. Orb.velocity . Vel.x
"oldVelX" se pouziva pri vypoctu zmeny stavu interpretu (neni to top level funkce) a tak mi prislo vhodnejsi umistit fci vedle ostatnich funkci interpretu, ktere se take zabyvaji zmenou stavu. A stejne to neresi problem, pokud se v "OrbState" pouziva dalsi zaznam, ktery ma field "x" (nebo jiny kolidujici), akorat jsem problem presunul jinam - z vyssi vrsty do nizsi vrstvy - do modulu s "OrbState" funkcemi.
Proč se ptáš přes jeden modul místo toho, aby ses zeptal přímo modulu Orb?
oldVelX = velocityX orb^
a do modulu Orb dopíšeš funkci velocityX.
			 
			
			- 
				Ale to pak budu ten samy problem s "x" resit v modulu OrbState (je tam "position" a "velocity", oboje maji fieldy "x" a "y"). Navic si takhle budu muset rucne vyrabet getter funkce pro kazdy vnoreny field kazdeho record co OrbState obsahuje? A co pak setter (https://hackage.haskell.org/package/lens-4.15.1/docs/Control-Lens-Setter.html#v:-37--126-) funkce? To uz jsme jak v Jave... K tomu jsou ty lenses, aby se to nemuselo psat rucne. I kdybych pouzil "velocityX" reseni a smiril se s rucnim psanim vsech kombinaci getteru a setteru, tak ani to neni moc slavne reseni, protoze to predpoklada, ze vsude, kde budu pouzivat ten OrbState, tak nebude nic mit jedinny field stejny jako v OrbState (napr. Velocity), protoze pak by jmeno rucne vytvoreneho getteru (napr. "velocityX") samozrejmne kolidovalo s getterem toho druheho zaznamu pro jeho x ve velocity...
Ta ^. (http://hackage.haskell.org/package/lens-4.15.1/docs/Control-Lens-Getter.html#v:-94-.) je jeden operator (getter), jmeno promenne je orb. To "Orb.velocity . Vel.x" znaci skladani lens, tj. z "OrbState" se zamer na "velocity" field a v nem na "x" field.
Jeste to zkusim pogooglit, jestli neco nenajdu. Posledne kdyz jsem to resil, tak jsem akorat nasel reseni prefixovat si vsechny fieldy jmenem recordu, coz me prijde hnusne a v podstate stejne, jako druhe reseni, tj. qualified importy. Bych prisahal, ze jsem nekde videl nejake reseni, ktere me ale dost desilo, protoze zapinalo dost lang. features a ja se v nich zatim nevyznam a nektere mohou vest k celkem velkym problemum (zmeni se semantika a/nebo syntaxe jazyka).
			 
			
			- 
				samozrejme sa to stale nevyrovna scale, ale pomocou http://www.javaslang.io/ a https://immutables.github.io/ sa da aj v jave vela biolerplate kodu vyhnut.
			
 
			
			- 
				Wow, dik za tip, to vypada dost dobre. Se moc v Java knihovnach neorientuju (uz vubec ne v tech, co maji stejnou funkcionalitu jako Scala), ale obe knihovny vypadaji solidne. Pokud nekdy budu donucen delat v Jave, tak alespon vim, po cem sahnout ;D.
			
 
			
			- 
				
Ale to pak budu ten samy problem s "x" resit v modulu OrbState (je tam "position" a "velocity", oboje maji fieldy "x" a "y").
Ještě jsem přišel na jedno možné řešení:
oldVelX = Vector.x $ Orb.velocity $ orb
Je to bez dalších getterů - stačí deriving (Show). Je možné s tím jít do libovolné úrovně zanoření - pouze se tím prodlouží zápis. Zároveň se sloučí Pos a Vel do jednoho modulu Vector. Oba mají stejné fieldy, tak proč je oddělovat?
Trochu je mi záhadou, k čemu jsou ve FP settery. Také je mi divné, že potřebuješ souřadnici X a neptáš se po Y. Funkcionalita by se pak dala schovat do modulu Vector. Nemusel by ses v tomto modulu pachtit s komponentami X a Y, prostě bys pracoval s vektory.
			 
			
			- 
				
Nevím, co přesně myslel - samo od sebe se uspořádání nezmění. Problémy mohou nastat, když máte funkci, která pracuje se dvěma množinami a obě mají jiné uspořádání, ale funkce předpokládá, že obě mají stejné (vím, že některé funkce ve standardní knihovně jsou na to ošetřeny, nevím, zda všechny).
Navíc podobná věc se mohla (nevím, zda stále může??) stát i v GHC Haskellu - viz příklad na konci http://blog.ezyang.com/2014/07/type-classes-confluence-coherence-global-uniqueness/ - a tam na to funkce nejsou připraveny.
Jojo, IMO myslel přesně tohle - a tohle je teda v GHC bug - tohle by tam jít nemělo. On to taky typechecker nebo linker chytí, ale jak je vidět, tak ne vždycky. A bohužel v GHC8 se to zkompiluje, a to i jako knihovna :( Naštěstí je to hodně výjimečná situace (je potřeba se dost snažit, aby se to povedlo), a i trochu proti best practice, ale zkompilovat by se to teda nemělo. Otázka je, jestli s backpackem k tomu nemůže docházet častěji.
Pouzivat type classy k tomuto ucelu mi prijde dost neprakticke (navic ani nevim, zda to vyresi problemy s kolizemi jmen auto-generovanych lens, tipl bych, ze spis nevyresi) a jak jsem psal, na vice mistech jsem cetl, ze pouzivat je vylozene k pretezovani funkci je bad practice, tak nevim...
Tak jsem se na to podíval - je na to makro makeFields, viz http://stackoverflow.com/questions/34617973/make-lenses-th-with-the-same-field-name-using-makeclassy (http://stackoverflow.com/questions/34617973/make-lenses-th-with-the-same-field-name-using-makeclassy). Tohle problém vyřeší a není to "bad practice" :)
Trochu je mi záhadou, k čemu jsou ve FP settery. Také je mi divné, že potřebuješ souřadnici X a neptáš se po Y. Funkcionalita by se pak dala schovat do modulu Vector. Nemusel by ses v tomto modulu pachtit s komponentami X a Y, prostě bys pracoval s vektory.
Lens jsou něco jako XPath, ale nad interními strukturami - které jsou v FP všechny immutable. Takž lens teda částečně řeší problém, který mimo FP nemusí řešit - tzn. modifikaci vnořených struktur. Ale z druhé strany je to neuvěřitelně flexibilní záležitost, speciálně s různým Travsersable, index lens apod. Navíc nejde jen o setter, ale je to FP - tak tam máš i "over". Tohle je trochu vycucané z prstu, ale máš třeba:
data A { _cislo :: Int, _...}
cache :: Map T.Text (Maybe A)
-- Přičti ke všem A._cislo v cache (tzn. Just hodnotám) jedničku
let res = cache & traverse . _Just . cislo %~ (+1)
Nedávno jsem řešil třeba modifikaci nějakého XMLka. Potřeboval jsem nastavit nějakou option - přidat do toho stromu na určité místo nějakou XML podstrukturu. Tohle vypadá dost hrozně..ale zkus si představit, jak bys to dělal v non-FP jazyce - tohle vypadá dost mutable díky State monadu - a "zoom" je nádstavba mimo jiné nad settery:
-- | Najde Phase konkretniho jmena
phaseWithName pname = svcPhases . traverse . phaseXml . nodes . filtered (\phase -> phase ^? tel "name" . text == Just pname)
-- | Najde konkretni option ve fazi
phaseOption optname = tel "options" . nodes . doption optname
... atd.
addMountConfig (Just (CopyMountParameters {..})) = do
      zoom (phaseWithName "Recover-Copy") $ do
        enabled .= "true"
        phaseOption "recoveryInstance" .= Just _cpInstance
        phaseOption "recoveryType" .= Just "recovery"
        phaseOption "dbRenameSuffix" .= Just _cpSuffix
      zoom (phaseWithName "Mount-Copy") $ do
        enabled .= "true"
        phaseOption "mountpath" .= Just _cpMountPath
        phaseOption "copyMetadataPath" .= Just _cpMountPath
        phaseOption "mounthost" .= Just _cpHost
        phaseOption "accesstype" .= Just "read-write"
			 
			
			- 
				A co andy, ty to děláš kde a proč? Vypadá to, že se o to také dost zajímáš. Děláš to v práci?
			
 
			
			- 
				
Nedávno jsem řešil třeba modifikaci nějakého XMLka. Potřeboval jsem nastavit nějakou option - přidat do toho stromu na určité místo nějakou XML podstrukturu. Tohle vypadá dost hrozně..ale zkus si představit, jak bys to dělal v non-FP jazyce 
V PHP to dělám zcela běžně a vypadá to mnohem jednodušeji. Je fakt, že i ve FP se s tímto požadavkem musí nějak poprat.
			 
			
			- 
				
Nedávno jsem řešil třeba modifikaci nějakého XMLka. Potřeboval jsem nastavit nějakou option - přidat do toho stromu na určité místo nějakou XML podstrukturu. Tohle vypadá dost hrozně..ale zkus si představit, jak bys to dělal v non-FP jazyce 
V PHP to dělám zcela běžně a vypadá to mnohem jednodušeji. Je fakt, že i ve FP se s tímto požadavkem musí nějak poprat.
Ukaž kód. ;-)
			 
			
			- 
				Pro duplicitní jména v rekordech haskellu jsem našel https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields. Přišlo mi, že to je přesně to, co chci příště použít, až s nimi budu mít problém. Má použití lens pro tento případ nějaké výhody?
			
 
			
			- 
				
Nedávno jsem řešil třeba modifikaci nějakého XMLka. Potřeboval jsem nastavit nějakou option - přidat do toho stromu na určité místo nějakou XML podstrukturu. Tohle vypadá dost hrozně..ale zkus si představit, jak bys to dělal v non-FP jazyce 
V PHP to dělám zcela běžně a vypadá to mnohem jednodušeji. Je fakt, že i ve FP se s tímto požadavkem musí nějak poprat.
Ukaž kód. ;-)
Však se podívej na dokumentaci třídy DomDocument, tam najdeš vše potřebné.
			 
			
			- 
				
V PHP to dělám zcela běžně a vypadá to mnohem jednodušeji. Je fakt, že i ve FP se s tímto požadavkem musí nějak poprat.
Jak by to vypadalo v PHP? Já si to totiž třeba v pythonu představit umím, a rozhodně by to jednodušejce nevypadalo (i.e. to raw XMLko začíná až na phaseXml a ten zápis "phaseOption "recoveryInstance" .= Just _cpInstance" přidá/nahradí celou podstrukturu typu '<option><name>recoveryInstance</name><value>...</value></option>).
A co andy, ty to děláš kde a proč? Vypadá to, že se o to také dost zajímáš. Děláš to v práci?
Taky - proč? Protože to umožňuje výrazně efektivnější práci. Ale zas jsou větší požadavky na hlavu programátora :)
Pro duplicitní jména v rekordech haskellu jsem našel https://ghc.haskell.org/trac/ghc/wiki/Records/OverloadedRecordFields/DuplicateRecordFields. Přišlo mi, že to je přesně to, co chci příště použít, až s nimi budu mít problém. Má použití lens pro tento případ nějaké výhody?
Jo, protože lens jsou composable, zatímco ty record fields ne. Ono v jakkoliv složitějším programu v podstatě rychle přejdeš na lens, protože jiný způsob updatu vnořených struktur je silně nepraktický.
			 
			
			- 
				
A co andy, ty to děláš kde a proč? Vypadá to, že se o to také dost zajímáš. Děláš to v práci?
Taky - proč? Protože to umožňuje výrazně efektivnější práci. Ale zas jsou větší požadavky na hlavu programátora :)
Je radost vidět lidi, kteří se o vývoj zajímají víc. To víš, z práce znám lopaty, které toho moc neumí. Takže to máš jako hlavní práci a nebo pro vylepšení práce? Jak jsem tu psal, Scala se dá najít docela jednoduše, ale asi žádná pecka práce to nebude. Ale třeba Haskell má využití kde? Dovedu si to představit třeba pro administrátora, protože on má volnost v jazycích. U vývojáře je to složitější.
			 
			
			- 
				
A co andy, ty to děláš kde a proč? Vypadá to, že se o to také dost zajímáš. Děláš to v práci?
Taky - proč? Protože to umožňuje výrazně efektivnější práci. Ale zas jsou větší požadavky na hlavu programátora :)
Je radost vidět lidi, kteří se o vývoj zajímají víc. To víš, z práce znám lopaty, které toho moc neumí. Takže to máš jako hlavní práci a nebo pro vylepšení práce? Jak jsem tu psal, Scala se dá najít docela jednoduše, ale asi žádná pecka práce to nebude. Ale třeba Haskell má využití kde? Dovedu si to představit třeba pro administrátora, protože on má volnost v jazycích. U vývojáře je to složitější.
Javamane kdybys nebyl lopata tak by ses podival na web Haskellu kde je to uvedeno. Nicmene pro lopaty to sem napisu. Jednak je to seznam uvedeny v https://wiki.haskell.org/Haskell_in_industry a taky https://www.quora.com/Which-companies-use-Haskell
			 
			
			- 
				
A co andy, ty to děláš kde a proč? Vypadá to, že se o to také dost zajímáš. Děláš to v práci?
Taky - proč? Protože to umožňuje výrazně efektivnější práci. Ale zas jsou větší požadavky na hlavu programátora :)
Je radost vidět lidi, kteří se o vývoj zajímají víc. To víš, z práce znám lopaty, které toho moc neumí. Takže to máš jako hlavní práci a nebo pro vylepšení práce? Jak jsem tu psal, Scala se dá najít docela jednoduše, ale asi žádná pecka práce to nebude. Ale třeba Haskell má využití kde? Dovedu si to představit třeba pro administrátora, protože on má volnost v jazycích. U vývojáře je to složitější.
Javamane kdybys nebyl lopata tak by ses podival na web Haskellu kde je to uvedeno. Nicmene pro lopaty to sem napisu. Jednak je to seznam uvedeny v https://wiki.haskell.org/Haskell_in_industry a taky https://www.quora.com/Which-companies-use-Haskell
Kdybys nebyl lopata, tak bys chápal, na co jsem se ptal.
			 
			
			- 
				
Tak jsem se na to podíval - je na to makro makeFields, viz http://stackoverflow.com/questions/34617973/make-lenses-th-with-the-same-field-name-using-makeclassy (http://stackoverflow.com/questions/34617973/make-lenses-th-with-the-same-field-name-using-makeclassy). Tohle problém vyřeší a není to "bad practice" :)
Jj, po predchozich postech jsem to taky nasel a zacal na to prechazet. Je to lepsi, nez tuna qualified importu a neprehledny zapis kompozice lens, ale zase takova vyhra to taky neni. Je treba skarede pojmenovavat fieldy recordu (prefixovat jmenem recordu), takze kdyz se to vytvari pres record syntax, tak je to pekne ukecane (co teprv, kdyz se jmeno recordu sklada z nekolika slov, fuj). Dalsi nevyhoda je, ze si to samo nehlida, zda uz to v projektu danou type classu nevytvorilo, kontroluje se jen aktualni soubor, takze pak dochazi k takovym podivnostem, jakoze musim importovat do modulu s velocity modul s position, prestoze z nej nic "viditelne" nepouzivam, protoze oba pouzivaji stejny field a jinak se vytvori type class dvakrat a samozrejmne to umre. Stale mi to pripada spise jako hack, ale je to rozhodne pouzitelnejsi, protoze lens pouzivam casteji nez vytvareni noveho zaznamu.
			 
			
			- 
				
Takže to máš jako hlavní práci a nebo pro vylepšení práce? Jak jsem tu psal, Scala se dá najít docela jednoduše, ale asi žádná pecka práce to nebude. Ale třeba Haskell má využití kde? Dovedu si to představit třeba pro administrátora, protože on má volnost v jazycích. U vývojáře je to složitější.
Haskell má využití kdekoliv. Je to supr jazyk na psaní webových backendů, které dělají vcelku cokoliv - za posledních pár let se objevilo obrovské množství knihoven na tyhle věci. Teď nedávno jsem potřeboval zpracovat rychle nějaký data - normálně jsem to dělával pythonem, krátký skriptík - zkusil jsem použít haskell a překvapivě to bylo vlastně stejně rychlé. Člověk je výrazně efektivnější než lidi píšící v jiných jazycích (je to trošku výběrový efekt, ale ten vývoj je fakt výrazně lepší). Ale je pravda, že v Čechách to moc neletí...
			 
			
			- 
				
Je treba skarede pojmenovavat fieldy recordu (prefixovat jmenem recordu), takze kdyz se to vytvari pres record syntax, tak je to pekne ukecane (co teprv, kdyz se jmeno recordu sklada z nekolika slov, fuj).
Já jsem na to tak detailně nekoukal, ale prefixovat by to asi mohlo jít čímkoliv, ne? A nebo si to makro upravit.. Před dvěma týdny jsem napsal úplně stejný makro do jiného projektu.... no jo, byl jsem líný si přečíst dokumentaci :) Ale je to překvapivě docela jednoduché.
			 
			
			- 
				Super, díky za info. Proti Pythonu to celkově vypadá jako jiná liga. Hlavně výkonem by to mělo být daleko lepší. Na skriptíky bych vůbec neváhal, jen zrovna žádné nedělám :D Zase Scala mi připadá jako moc malý skok od Javy, protože běží nad JVM, ale při nejhorším je to super kopromis. Vím, že Scala má zase asi jiné cool funkce, no.
			
 
			
			- 
				
Je treba skarede pojmenovavat fieldy recordu (prefixovat jmenem recordu), takze kdyz se to vytvari pres record syntax, tak je to pekne ukecane (co teprv, kdyz se jmeno recordu sklada z nekolika slov, fuj).
Ten prefix si můžeš zkrátit až na jedno písmenko (zde jsme použili tři). Za prefix dáš místo podtržítka tečku a vypadá to i docela elegantně, skoro jako v OOP. Namespace je náš kamarád.
Dalsi nevyhoda je, ze si to samo nehlida, zda uz to v projektu danou type classu nevytvorilo, kontroluje se jen aktualni soubor, takze pak dochazi k takovym podivnostem, jakoze musim importovat do modulu s velocity modul s position, prestoze z nej nic "viditelne" nepouzivam, protoze oba pouzivaji stejny field a jinak se vytvori type class dvakrat a samozrejmne to umre.
Však jsem psal, že si vytvoříš modul Vector, ze kterého odvodíš position i velocity. Pozici pak měníš pouhým přičítáním velocity k position a nemusí tě trápit, zda je to ve 2D či 3D. Místo X a Y může být výhodnější [x,y]. Nebojuj s jazykem, využívej ho.
			 
			
			- 
				
Člověk je výrazně efektivnější než lidi píšící v jiných jazycích (je to trošku výběrový efekt, ale ten vývoj je fakt výrazně lepší). Ale je pravda, že v Čechách to moc neletí...
Docela by mne zajímalo, pro jaké lidi/týmy to platí a čím je to podložené. A také, zda to platí pouze pro vývoj nebo i pro údržbu.
Už jsme to tu řešili dříve a myslím si, že je to stále obrovský problém GHC - a sice snadné uvažování o rychlosti programu a určitá garance, že se rychlost prudce nezhorší při přechodu na novější verzi GHC nebo při malé změně v programu - viz třeba https://mail.haskell.org/pipermail/haskell-cafe/2016-July/124324.html:
The compilation method (and resulting runtime performance) depends on the GHC simplifier acting in a certain way — yet there is no specification of exactly what the simplifier should do, and no easy way to check that it did what was expected other than eyeballing the intermediate code. 
			 
			
			- 
				
Teď nedávno jsem potřeboval zpracovat rychle nějaký data - normálně jsem to dělával pythonem, krátký skriptík - zkusil jsem použít haskell a překvapivě to bylo vlastně stejně rychlé.
Docela by mě zajímalo, jak se v haskellu zpracovávají "nějaká data". Jak bys například přepsal tohle?
import requests
ua = requests.get(r'http://headers.jsontest.com/').json().get('User-Agent', '')
			 
			
			- 
				
Člověk je výrazně efektivnější než lidi píšící v jiných jazycích (je to trošku výběrový efekt, ale ten vývoj je fakt výrazně lepší). Ale je pravda, že v Čechách to moc neletí...
Docela by mne zajímalo, pro jaké lidi/týmy to platí a čím je to podložené. A také, zda to platí pouze pro vývoj nebo i pro údržbu.
Mě taky :) Pro údržbu tohle platí mnohem víc než jenom pro vývoj. Refaktoring v Haskellu je díky silným typům překvapivě záležitost, při které nevzniká mnoho chyb. 
Už jsme to tu řešili dříve a myslím si, že je to stále obrovský problém GHC - a sice snadné uvažování o rychlosti programu a určitá garance, že se rychlost prudce nezhorší při přechodu na novější verzi GHC nebo při malé změně v programu - viz třeba https://mail.haskell.org/pipermail/haskell-cafe/2016-July/124324.html:
The compilation method (and resulting runtime performance) depends on the GHC simplifier acting in a certain way — yet there is no specification of exactly what the simplifier should do, and no easy way to check that it did what was expected other than eyeballing the intermediate code. 
Ano - pokud máte hodně high-level jazyk, tak se holt dost špatně "jen tak" odhaduje, jak se to vlastně low-level bude chovat. Pro real-time aplikace to není (na druhou stranu existují projekty, kdy v haskellu píšete generátor kódu pro real-time), mimo jiné třeba i z důvodu GC. Ale připadá mi, že pro hodně projektů je korektnost kódu mnohem důležitější, než to, zda z HW vyždímete co nejvíc - a tragicky pomalé to rozhodně není (popravdě, je to v zásadě docela rychlé..)
			 
			
			- 
				
Docela by mě zajímalo, jak se v haskellu zpracovávají "nějaká data". Jak bys například přepsal tohle?
import requests
ua = requests.get(r'http://headers.jsontest.com/').json().get('User-Agent', '')
{-# LANGUAGE OverloadedStrings #-}
import Network.Wreq (get, responseBody)
import Control.Lens ((^?), (<&>), preview)
import Data.Aeson.Lens (key)
main = do
  r <- get "http://headers.jsontest.com"
  let ua = r ^? responseBody . key "User-Agent"
  print r
Takhle to kompletně funguje a takhle bych to napsal. Kromě těch importů v podstatě totéž.
Aby to byl one-liner, tak se to dá pořešit třeba tímhle:
  r <- get "http://headers.jsontest.com" <&> preview (responseBody . key "User-Agent")
A výstup:
Just (String "haskell wreq-0.4.1.0")
Pokud by došlo k chybě dekódování nebo tam ten klíč chyběl, tak by z toho vypadlo Nothing. Pokud bys vyloženě chtěl, aby tam byl prázdný string, tak by se přidalo (<&> fromMaybe ""). 
BTW: responseBody ukazuje na ByteString, "key" je polymorfní lens, která na bytestringu funguje tak, že rovnou provede JSON dekódování; někdo se tu ptal, jak funguje setter - tak vzhledem k tomu, že tohle je lens, tak je možné provádět i updaty:
>  "[1,2,3]" & val . _Number %~ (+1)
"[2,3,4]"
> "[1,2,3]" & nth 1 . _Number %~ (+10)
"[1,12,3]"
Tzn. automaticky se to překonvertuje zpátky do stringu. Jako tohle v praxi asi moc užitečné není, ale je to docela zajímavé, co všechno je možné zrovna s lensama dělat :)
			 
			
			- 
				Errata:
print uaa na konci:
>  "[1,2,3]" & values . _Number %~ (+1)
Kdyby to někdo zkoušel....
			 
			
			- 
				
Docela by mě zajímalo, jak se v haskellu zpracovávají "nějaká data". Jak bys například přepsal tohle?
import requests
ua = requests.get(r'http://headers.jsontest.com/').json().get('User-Agent', '')
{-# LANGUAGE OverloadedStrings #-}
import Network.Wreq (get, responseBody)
import Control.Lens ((^?), (<&>), preview)
import Data.Aeson.Lens (key)
main = do
  r <- get "http://headers.jsontest.com"
  let ua = r ^? responseBody . key "User-Agent"
  print r
Takhle to kompletně funguje a takhle bych to napsal. Kromě těch importů v podstatě totéž.
Jednodušeji by to nešlo? Pomocí manuálů jsem se propracoval k tomuto:
import  Network.HTTP
resp = simpleHTTP(getRequest "http://headers.jsontest.com/")
main = do
    body <- resp >>= getResponseBody
    print body
Evidentně tomu ještě kousek chybí, ale určitě to nebude víc než jeden řádek.
			 
			
			- 
				
Jednodušeji by to nešlo? Pomocí manuálů jsem se propracoval k tomuto:
Tak na počet znaků je to - kromě importů - identické. A ty importy znamenají: Web requesty (to je stejné), Json (u haskellu web request nic o jsonu neví), Lens (to python nemá) a OverloadedStrings je extension, protože v Haskellu se rozlišují různé typy stringů. Pak by ještě měl být import asi na to fromMaybe.
import  Network.HTTP
resp = simpleHTTP(getRequest "http://headers.jsontest.com/")
main = do
    body <- resp >>= getResponseBody
    print body
Evidentně tomu ještě kousek chybí, ale určitě to nebude víc než jeden řádek.
Chybí dekódování JSONu. Tzn. v podstatě ty zbývající importy a
print $ fromMaybe "" (body ^? key "User-Agent")
... což je totéž, co jsem napsal... Chtěl bych říct, že ty importy za tebe pořeší IDE, ale bohužel zatím ne.
			 
			
			- 
				
Jednodušeji by to nešlo? Pomocí manuálů jsem se propracoval k tomuto:
Tak na počet znaků je to - kromě importů - identické.
Identické to být nemůže, dělal jsem to samostatně. Kromě toho se chci vyhnout použití Lens.
Chybí dekódování JSONu. Tzn. v podstatě ty zbývající importy a
print $ fromMaybe "" (body ^? key "User-Agent")
... což je totéž, co jsem napsal... Chtěl bych říct, že ty importy za tebe pořeší IDE, ale bohužel zatím ne.
Nerozumím symbolu "^?", v manuálu Haskellu jsem ho zatím nenašel. Zato jsem tam našel HdrUserAgent, který by měl dělat totéž, co key "User-Agent".
Na parsování JSONu jsem našel Data.Aeson.
			 
			
			- 
				
Nerozumím symbolu "^?", v manuálu Haskellu jsem ho zatím nenašel.
http://hoogle.haskell.org/?hoogle=%5E%3F (http://hoogle.haskell.org/?hoogle=%5E%3F)
To jsou lensy (návod z Microlens je trošku čitelnější); tohle konkrétně je operátor, který vrací hodnotu, na kterou by mohla ukazovat lens (tzn. ta hodnota tam být nemusí). Kdyby v pythonu bylo:
obj.x.y.get('z', None)Tak tady by to bylo:
obj ^? x . y . key "z"
 Zato jsem tam našel HdrUserAgent, který by měl dělat totéž, co key "User-Agent".
V tom původním příkladu se měla rozebrat JSON odpověd toho web serveru, ne hlavičky.
Na parsování JSONu jsem našel Data.Aeson.
To jo, ale to ti naparsuje JSON buď do tvého custom datového typu, nebo do "univerzální" struktury "Value". Ta lensa "key" je interně postavená na aesonu, ale zjednodušuje to kroky, které bys musel provést. Pokud víš co ti server vrátí, tak by ten kód pak vypadal třeba takhle (a v produkci by tak asi i možná skoro vypadal):
data ServerResponse = ServerResponse {
  userAgent :: Text
}
instance FromJSON ServerResponse where
   parseJSON = withObject "response" $ \o -> ServerResponse <$> o .: "User-Agent"
...
main = do
   ...
   case decode bodyResponse of
      Just resp -> print (userAgent resp)
      Nothing -> print "Chyba pri dekodovani"
Ale tady byla otázka "rychle prohledat nějaký JSON, který možná obsahuje klíč user-agent" - tak kvůli tomu asi nemá smysl vyrábět nový datový typ. Jinak aeson samozřejmě podporuje automatické generování (de)serializačního kódu.
			 
			
			- 
				
...
Ale tady byla otázka "rychle prohledat nějaký JSON, který možná obsahuje klíč user-agent" - tak kvůli tomu asi nemá smysl vyrábět nový datový typ. Jinak aeson samozřejmě podporuje automatické generování (de)serializačního kódu.
Mně ani tak nešlo o to, jak rychle dospět k nějakému cíli, ale jak pochopit Haskell jako jazyk. Samozřejmě se nechci vyhýbat Network.HTTP nebo Data.Aeson, ale třeba Lens mi už připadá jako zbytečnost navíc. Tedy zatím.
			 
			
			- 
				K tomu vyjadreni position i velocity jako vector - moc se mi to nelibi, uz jen proto, ze pak je validni priradit postion do velocity. Navic v tom mem projektu (ktery neni modelovani realneho sveta), je dost mozne, ze dospeju do stavu, kdy position bude nad celymi cisly, ale velocity ne. Pripadne position dostane dalsi field (napr. level ci dimension).
...
Ale tady byla otázka "rychle prohledat nějaký JSON, který možná obsahuje klíč user-agent" - tak kvůli tomu asi nemá smysl vyrábět nový datový typ. Jinak aeson samozřejmě podporuje automatické generování (de)serializačního kódu.
Mně ani tak nešlo o to, jak rychle dospět k nějakému cíli, ale jak pochopit Haskell jako jazyk. Samozřejmě se nechci vyhýbat Network.HTTP nebo Data.Aeson, ale třeba Lens mi už připadá jako zbytečnost navíc. Tedy zatím.
IMO pokud to myslite s FP vazne, tak se lens nevyhnete, protoze jinak musite psat a udrzovat haldy boilerplate kodu. Proto jsem se se ptal, jestli pro Javu nejaka lens knihovna existuje, protoze bez toho si FP nedovedu moc predstavit. Pro Scalu jsem priklady uvedl - obe knihovny umi i autogenerovani, takze kodu navic je minimum.
			 
			
			- 
				
K tomu vyjadreni position i velocity jako vector - moc se mi to nelibi, uz jen proto, ze pak je validni priradit postion do velocity. Navic v tom mem projektu (ktery neni modelovani realneho sveta), je dost mozne, ze dospeju do stavu, kdy position bude nad celymi cisly, ale velocity ne. Pripadne position dostane dalsi field (napr. level ci dimension).
Uvedl jsem to jen jako možnost. Nic nebrání rozdělení podle sémantiky.
IMO pokud to myslite s FP vazne, tak se lens nevyhnete, protoze jinak musite psat a udrzovat haldy boilerplate kodu. Proto jsem se se ptal, jestli pro Javu nejaka lens knihovna existuje, protoze bez toho si FP nedovedu moc predstavit. Pro Scalu jsem priklady uvedl - obe knihovny umi i autogenerovani, takze kodu navic je minimum.
V OOP se obejdu bez getterů, setterů a veřejných atributů. Ve FP se určitě obejdu bez lens, aniž bych musel psát boilerplates. Přinejhorším si je nechám vygenerovat editorem a upravím na přesnou míru.
			 
			
			- 
				
V OOP se obejdu bez getterů, setterů a veřejných atributů. Ve FP se určitě obejdu bez lens, aniž bych musel psát boilerplates. Přinejhorším si je nechám vygenerovat editorem a upravím na přesnou míru.
Tak pro začátek určitě ano - dokud člověk nezačne nějak víc pracovat s vnořenými strukturami, tak se fakt bez Lens obejde; a ony ty vnořené struktury až tak časté v kódu nejsou. Ostatně i ten příklad s user-agentem - pokud by to byla nějaká REST služba, tak bude mít asi definovaný nějaký interface, takže se k tomu udělají odpovídající struktury v programu a vygeneruje se serializace/deserializace. Ono je docela rozumné, když člověk ví aspoň rámcově, co to dělá, a lensy jsou fakt magie. Na druhou stranu při práci s vnořenými strukturami - a to třeba "generický" json je - je to bez lens silně nepohodlné.
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky. Takže když v pythonu napíšu:
someJson['key'][3]['nextkey'] + 1Tak to může vyhodit výjimku tak zhruba tak ze 7mi důvodů (cca. 3 různé výjimky v pythonu). No a FP programátor sice nutně neprahne po tom každou výjimku ošetřovat, ale docela by rád, aby ta funkce byla "totální" - tzn. pro jakýkoliv vstup to "skončí" (tzn. nevyhodí výjimku, ale něco vrátí). No a kombinace lens a Maybe Monad pak umožňuje tu funkci napsat jako:
f someJson = do
   num <- someJson ^? key "key" . nth 3 . key "nextkey"
   return (num + 1)
a ač to na první pohled nevypadá, tak tahle funkce je totální a vrátí buď výsledek nebo Nothing a nevyhodí výjimku (pokud to nevyhodí (+)). Bez lens by to asi nějak šlo, kdyby si člověk napsal vhodné funkce, tak by to mohlo i vypadat:
f someJson = do
   num <- getKey "key" someJson >>= getNth 3 >>= getKey "nextKey"
   return (num + 1)
Ale už to není tak elegantní a hlavně jakákoliv modifikace té vnořené struktury by už fakt byla problém.
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Ani jeden z uvedených kódů (včetně toho pythoního) pro mne není dost "pure", takže to zřejmě ani nebudu muset řešit.
Však uvidím časem.
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky. Takže když v pythonu napíšu:
someJson['key'][3]['nextkey'] + 1Tak to může vyhodit výjimku tak zhruba tak ze 7mi důvodů (cca. 3 různé výjimky v pythonu).
Tak to je jen o přístupu Pythonu. V Perlu 
perl6 -e 'my $someJSON; say $someJSON<key>[3]<nextkey> + 1;'vyhodí varovaní taky až to plus a vytiskne to 1.
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky. Takže když v pythonu napíšu:
someJson['key'][3]['nextkey'] + 1Tak to může vyhodit výjimku tak zhruba tak ze 7mi důvodů (cca. 3 různé výjimky v pythonu).
Tak to je jen o přístupu Pythonu. V Perlu 
perl6 -e 'my $someJSON; say $someJSON<key>[3]<nextkey> + 1;'vyhodí varovaní taky až to plus a vytiskne to 1.
Jo, to je přesně o tom přístupu - perl vytiskne 1, python vyhodí výjimku a haskell vrátí Nothing.
Tohle je mimo jiné jedna z odpovědí pro Radka Míčka: napsat stejný kód v haskellu typicky trvá trošku déle (ne o moc), ale když člověk skončí, tak má obvykle kód, který řeší všechny okrajové stavy, zatímco v mnoha jiných jazycích má prototyp...
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Ani jeden z uvedených kódů (včetně toho pythoního) pro mne není dost "pure", takže to zřejmě ani nebudu muset řešit.
Však uvidím časem.
Jak by to pro tebe vypadalo dost pure? Jen mě to zajímá :)
			 
			
			- 
				Se chytáš do jeho sítí. On totiž nikde nedefinoval, co pro něj pure znamená  a samozřejmě to bude zase nějaký nesmysl. Bez setterů a komentářů ;D
			
 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Ani jeden z uvedených kódů (včetně toho pythoního) pro mne není dost "pure", takže to zřejmě ani nebudu muset řešit.
Však uvidím časem.
Jak by to pro tebe vypadalo dost pure? Jen mě to zajímá :)
S Haskellem teprve začínám, tlačí mě do něj pouze zvědavost. Chci na něm vyzkoušet pár svých sémantických pravidel, která používám v OOP. Nejprve se chci poctivě naučit základy, ke kterým mi pomohou adaptéry na externí datové zdroje, aby to bylo na čem zkoušet a tedy generovat nějaké výsledky. Tyto adaptéry (JSON, XML, HTTP,...) už někdo udělal přede mnou a v tuto chvíli nemám důvod na nich nic měnit. Budu jimi importovat vstupy a exportovat výstupy, což mi jistě umožní některé z prototypů nasadit přímo do ostrého provozu.
Zbývá tedy jádro (resp. jádra) aplikace ve stylu hexagonální architektury s poměrně volnou vazbou na okolní jádra. Jádro bude jeden modul/monáda. Každé z těchto jader bude moci komunikovat pouze se svým sousedem přes funkcionální adaptéry. Mám takové tušení, že lens by mi to místo usnadnění mohl zkomplikovat, proto se jím zatím nechci zabývat.
Nemám tedy pevně stanovený cíl, ale spíš cestu. Slibuji si od toho rozříření obzoru podobně, jak mi to kdysi udělal Lisp.
			 
			
			- 
				
Člověk je výrazně efektivnější než lidi píšící v jiných jazycích (je to trošku výběrový efekt, ale ten vývoj je fakt výrazně lepší). Ale je pravda, že v Čechách to moc neletí...
Refaktoring v Haskellu je díky silným typům překvapivě záležitost, při které nevzniká mnoho chyb. 
Když máte štěstí a nesnažíte se zakódovat (složitější) vlastnosti funkcí do typů (což je vidět na jazycích se závislými typy, kde malá změna může znamenat přepsání celého programu).
A i v Haskellu je kolikrát malá změna velký problém - stačí po funkci, která není v IO chtít něco vyprintit a musíte si pomoci ošklivým trikem nebo změnit i mnoho jiných funkcí, z nichž je tato funkce volána (aby všechny byly v IO).
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Což se ale v Haskellu děje celkem často [] !! 1, head [], 1`div`0 + řada případů, kdy něco vyhazuje Stack overflow, protože někdo někde nepoužil seq (třeba foldl (+) 0 [1..1000000]) nebo kompilátoru něco nedošlo.
			 
			
			- 
				
Když máte štěstí a nesnažíte se zakódovat (složitější) vlastnosti funkcí do typů (což je vidět na jazycích se závislými typy, kde malá změna může znamenat přepsání celého programu).
No haskell zatím dependent typy ještě nemá, ale tak nějak vlastně nerozumím - ano, při refaktoringu člověk občas provede změny, které znamenají, že toho musí přepsat poměrně hodně, ale zatím když se mi to nakonec po přepsání podařilo přeložit, tak to typicky fungovalo...
A i v Haskellu je kolikrát malá změna velký problém - stačí po funkci, která není v IO chtít něco vyprintit a musíte si pomoci ošklivým trikem nebo změnit i mnoho jiných funkcí, z nichž je tato funkce volána (aby všechny byly v IO).
Ošklivým unsafe trikem si rozhodně nepomáhám, ale já nějak nikdy s tímhle problém neměl. Když něco počítám, zajímá mě výsledek. Spíš je problém při debugování, ale tam se tohle toleruje :)
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Což se ale v Haskellu děje celkem často [] !! 1, head [], 1`div`0 + řada případů, kdy něco vyhazuje Stack overflow, protože někdo někde nepoužil seq (třeba foldl (+) 0 [1..1000000]) nebo kompilátoru něco nedošlo.
[/quote]No a právě pro to lidi, co v haskellu programují  [] !! 1, head [] prakticky nepoužívají. Někdy si lidi do projektů importují vlastní Prelude, kde jsou všechny tyhle funkce vynechané a konstantně se vede diskuze, jestli to nevyhodit i z oficiálního Preludu (jenomže učte pak začátečníky....). Teď jsem se zoufale snažil přivést ghci ke stackoverflow pomocí foldl a nezdařilo se; mimochodem, to mě docela překvapilo - když se to kompiluje se zapnutou optimalizací, tak se (konkrétně tenhle) foldl zfůzuje a funguje to úplně v pohodě...ale jasně tyhle věci se dějí, ale stalo se mi to snad jednou. Takže v podstatě zbývá to dělení nulou.
Jasně, že to není úplně dokonalé - ale přece jen je trošku rozdíl mezi tím Perlovým kódem, který v klidu vydá "nějaký výsledek", pythoním kódem, který aspoň vyhodí výjimky a Haskellovým kódem, kde konstantně překladač upozorňuje, který že krajní případ programátor zapomněl vyhodnotit.... :)
			 
			
			- 
				
Jasně, že to není úplně dokonalé - ale přece jen je trošku rozdíl mezi tím Perlovým kódem, který v klidu vydá "nějaký výsledek", pythoním kódem, který aspoň vyhodí výjimky a Haskellovým kódem, kde konstantně překladač upozorňuje, který že krajní případ programátor zapomněl vyhodnotit.... :)
Teď to nějak nechápu, co je zázračného na tom, když Haskell vrátí Nothing oproti 1, nebo vyhození výjimky?
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky. Takže když v pythonu napíšu:
someJson['key'][3]['nextkey'] + 1Tak to může vyhodit výjimku tak zhruba tak ze 7mi důvodů (cca. 3 různé výjimky v pythonu).
Tak to je jen o přístupu Pythonu. V Perlu 
perl6 -e 'my $someJSON; say $someJSON<key>[3]<nextkey> + 1;'vyhodí varovaní taky až to plus a vytiskne to 1.
Jo, to je přesně o tom přístupu - perl vytiskne 1, python vyhodí výjimku a haskell vrátí Nothing.
Tohle je mimo jiné jedna z odpovědí pro Radka Míčka: napsat stejný kód v haskellu typicky trvá trošku déle (ne o moc), ale když člověk skončí, tak má obvykle kód, který řeší všechny okrajové stavy, zatímco v mnoha jiných jazycích má prototyp...
V pythonu se dá použít get('key', {}) nebo se dá použít rekurzivní defaultdict jako objecthook
def mydict(d={}):
    return defaultdict(mydict,d)
some_json = json.loads(jsonstring, object_hook=mydict) 
Neřeší to překročení indexu u listů.
			 
			
			- 
				
Teď jsem se zoufale snažil přivést ghci ke stackoverflow pomocí foldl a nezdařilo se; mimochodem, to mě docela překvapilo - když se to kompiluje se zapnutou optimalizací, tak se (konkrétně tenhle) foldl zfůzuje a funguje to úplně v pohodě...
A tohle má být dobrá nebo špatná vlastnost? Protože tenhle kód:
foldl (+) 0 [1..1000000]
S O2 projde, ale bez optimalizací:
Stack space overflow: current size 8388608 bytes.
Musím říct, že tohle mě na Haskellu hodně děsí. Zapnutí optimalizací úplně změní sémantiku vyhodnocování kódu. Pro mě má takový kód undefined behavior a že funguje je jenom náhoda. Co kdy někdo do produkce nasadí kód s vypnutými optimalizacemi? Co když se něco v nové verzi GHC změní a začne to fungovat jinak? Ono se to nemusí projevit hned, ale až tehdy, když se začnou zpracovávat dostatečně velká data, pro malá data může stack stačit.
			 
			
			- 
				
Jasně, že to není úplně dokonalé - ale přece jen je trošku rozdíl mezi tím Perlovým kódem, který v klidu vydá "nějaký výsledek", pythoním kódem, který aspoň vyhodí výjimky a Haskellovým kódem, kde konstantně překladač upozorňuje, který že krajní případ programátor zapomněl vyhodnotit.... :)
Teď to nějak nechápu, co je zázračného na tom, když Haskell vrátí Nothing oproti 1, nebo vyhození výjimky?
Oproti 1 to docela zázračné je, protože to negeneruje "nějaký" výsledek na základě nekorektních vstupních dat. Oproti vyhození výjimky to má tu výhodu, že se to lépe používá. Např. řekněme, že parsuju nějaký seznam:
seznamJsonu = [...]
f :: ByteString -> Maybe Neco -- Naparsuje bytestring, vytáhne z něj Neco
vysledek = traverse f seznamJsonu -- Buď bude Just [Neco, Neco..], nebo Nothing, pokud selhal kterýkoliv parse
vysledek = mapMaybe f seznamJsonu -- Výsledek bude [Neco, Neco] pro ty, ktere se naparsovaly korektne
Ale především - v jiných jazycích se výjimky používají, protože se s tou návratovou hodnotou špatně pracuje. Tohle je typický příklad - tady třeba z Go:
f, err := os.Open("filename.ext")
if err != nil {
    log.Fatal(err)
}Jenomže v Haskellu se naopak s návratovou hodnotou pracuje dobře:
parsujNekolikJsonu js1 js2 js3 = do
   v1 <- decode js1
   v2 <- decode js2
   v3 <- decode js3
   return (nejakFce v1 + jinaFce v2 * jesteJinaFce v3)
Pokud kterýkoliv z "decode" vrátí Nothing, tak celá funkce vrátí Nothing. 
			 
			
			- 
				
A tohle má být dobrá nebo špatná vlastnost? Protože tenhle kód:
foldl (+) 0 [1..1000000]
S O2 projde, ale bez optimalizací:
Stack space overflow: current size 8388608 bytes.
To byla jen poznámka na okraj, protože mě překvapilo, že v základní knihovně se nechává foldl, protože je schopen dobře fůzovat... přišlo mi to zajímavé :)
Musím říct, že tohle mě na Haskellu hodně děsí. Zapnutí optimalizací úplně změní sémantiku vyhodnocování kódu. Pro mě má takový kód undefined behavior a že funguje je jenom náhoda. 
Teď nerozumím - tohle je příklad kódu, u kterého máš v každé učebnici napsané "nedělej to". Přesto má Haskell tak dobrou optimalizaci, že je schopen spoustu tohoto špatně napsaného kódu převést na normálně fungující kód. To je špatně?
Když napíšeš v mnoha jinách jazycích brutálně rekurzivní kód, tak ti to taky časem upadne na stack overflow. Když změníš nastavení velikost stacku, tak se ti to taky bude chovat jinak. Co z toho mám vyvozovat?
Co kdy někdo do produkce nasadí kód s vypnutými optimalizacemi?
Tak si to taky vyžere. Funkcionální jazyky závisí na tail-call optimalizaci, když ji vypneš, tak ti toho přestane fungovat docela hodně. Mimochodem, stack overflow s vypnutými optimalizacema vyrobíš, pokud vím, i v překladačích C, protože ty to umí taky.
Co když se něco v nové verzi GHC změní a začne to fungovat jinak? Ono se to nemusí projevit hned, ale až tehdy, když se začnou zpracovávat dostatečně velká data, pro malá data může stack stačit.
Takže se Haskell nemá snažit tyhle věci optimalizovat? Navíc pokud děláš tyhle výpočty, tak na to jsou direktivy "Strict" a "StrictData", které tě těchto problémů v podstatě zbaví.
Že nemáš používat foldl je napsané prakticky v každém učebnici Haskellu. Šlo by dávat příklady toho, jak je ten jazyk špatný, z jiné kapitoly než z té, jejíž téma je "jak se vykonává haskellový kód a na co si dát pozor"?
			 
			
			- 
				
Teď nerozumím - tohle je příklad kódu, u kterého máš v každé učebnici napsané "nedělej to". Přesto má Haskell tak dobrou optimalizaci, že je schopen spoustu tohoto špatně napsaného kódu převést na normálně fungující kód. To je špatně?
Dobře, tak jiný kód:
fac x = fac' x 1 where
    fac' 1 y = y
    fac' x y = fac' (x-1) (x*y) 
main = print (fac(1000000))
Tohle bez optimalizací spadne na stack overflow, protože Haskell neudělá tail-recursive optimalizaci. Takže jinými slovy Haskell mě nutí, abych veškerý kód používal za všech okolností s O2 optimalizací, jinak není nic zaručeno.
Když napíšeš v mnoha jinách jazycích brutálně rekurzivní kód, tak ti to taky časem upadne na stack overflow. Když změníš nastavení velikost stacku, tak se ti to taky bude chovat jinak. Co z toho mám vyvozovat?
To je právě ono, v imperativních jazycích žádný brutálně rekurzivní kód nenapíšeš, proč bys to dělal? Napíšeš cyklus. Ve funcionálních jazycích je rekurze naprosto typický design pattern, jinak se v tom v podstatě programovat nedá. Jenže v Haskellu to bez O2 nefunguje.
Co kdy někdo do produkce nasadí kód s vypnutými optimalizacemi?
Tak si to taky vyžere. Funkcionální jazyky závisí na tail-call optimalizaci, když ji vypneš, tak ti toho přestane fungovat docela hodně. 
Což je dost hrozné, proč se to nedá používat normálně i s vypnutými optimalizacemi? Nebo jinak, proč vůbec jdou ty optimalizace vypnout, když bez nich pořádně nic nefunguje?
Mimochodem, stack overflow s vypnutými optimalizacema vyrobíš, pokud vím, i v překladačích C, protože ty to umí taky.
Vyrobíš, ale musíš se hodně snažit, aby se ti to povedlo, typicky to nenastává. Haskell se s vypnutými optimalizacemi prakticky nedá používat.
			 
			
			- 
				
Oproti 1 to docela zázračné je, protože to negeneruje "nějaký" výsledek na základě nekorektních vstupních dat. Oproti vyhození výjimky to má tu výhodu, že se to lépe používá. 
Proč nekorektní? Když se nedefinovaná hodnota bere jako 0, tak je to sice nezvyklé, ale ne nekorektní. Stejně tak se někomu může zdát nekorektní agresivní chování Nothink. Někdy se může hodit to jindy ono.
Tohle
 perl6  -e 'for lines() { say join ";\t", ++$, $_, ++(%){ .split(":")[*-1] } }' /etc/passwd vepředu očísluje řádky a na konci je očísluje zvlášť pro každý shell. Kdybych výše zmíněného chování nevyužil, tak bych pro každý klíč (shell) musel testovat jestli už je definován.
Jak se chová v Haskelu např. "+" v následujícím případě?  perl6 -e 'say "12" + 1' #13 
			 
			
			- 
				
Tohle bez optimalizací spadne na stack overflow, protože Haskell neudělá tail-recursive optimalizaci. Takže jinými slovy Haskell mě nutí, abych veškerý kód používal za všech okolností s O2 optimalizací, jinak není nic zaručeno.
Ne, musíš to kompilovat s -O, což je ale standardní režim kompilace pro veškeré cabal projekty. Naopak, když to chceš kompilovat bez optimalizací, musíš to kompilovat s -O0. Tys to asi kompiloval přímo s GHC, to to má možná defaultně vypnuté, ale takhle se nic nevyvíjí. Dneska se docela často na vývoj používá stack (https://docs.haskellstack.org/en/stable/README/).
To je právě ono, v imperativních jazycích žádný brutálně rekurzivní kód nenapíšeš, proč bys to dělal? Napíšeš cyklus. Ve funcionálních jazycích je rekurze naprosto typický design pattern, jinak se v tom v podstatě programovat nedá. Jenže v Haskellu to bez O2 nefunguje.
Protože spousta algoritmů je moc hezky popsána rekurzivně - tak proč to tak nepsat.
Mimochodem, v Haskellu není rekurze úplně typický design pattern. Typický design pattern je používat právě ty funkce typu "fold" - proto je u toho "foldl" všude ten velký vykřičník, protože to je typický design pattern (a typický výjimka z něho).
Což je dost hrozné, proč se to nedá používat normálně i s vypnutými optimalizacemi? Nebo jinak, proč vůbec jdou ty optimalizace vypnout, když bez nich pořádně nic nefunguje?
A proč by to nemělo jít vypnout? Když už se v tomhle hrabeš, tak se tak nějak předpokládá, že víš, co děláš. Ona mimochodem ta optimalizace se dá trošku řídit (Rewrite rules) a když v tom třeba hledáš chybu, tak jsi docela rád, že se dá s těma optimalizacema štelovat. Další věc je, že ten překladač se velmi zajímavě vyvíjí a sem tam někdo na světě narazí na něco, co se třeba nepřeložilo dobře - tak je dobré mít způsob, jak ten problém vůbec najít.
Mimochodem, Scala pokud vím tail-call optimalizaci má dost problematickou, protože JRE to neumí - a to je pak trošku větší problém.
			 
			
			- 
				
Protože spousta algoritmů je moc hezky popsána rekurzivně - tak proč to tak nepsat.
Pomocí tail-call optimalizovatelné rekurze zapíšete jen algoritmy, které se dají snadno zapsat smyčkou.
			 
			
			- 
				
Oproti 1 to docela zázračné je, protože to negeneruje "nějaký" výsledek na základě nekorektních vstupních dat. Oproti vyhození výjimky to má tu výhodu, že se to lépe používá. 
Proč nekorektní? Když se nedefinovaná hodnota bere jako 0, tak je to sice nezvyklé, ale ne nekorektní. Stejně tak se někomu může zdát nekorektní agresivní chování Nothink. Někdy se může hodit to jindy ono.
Agresivní :) Když chceš převést Nothing na 0, tak napíšeš "fromMaybe 0 x" a je to. Ale tohle je spíš taková všeobecná otázka - jak psát kód. A mně se třeba líbí, že mě Haskell donutí explicitně ošetřit drtivou většinu hraničních stavů. Když něco neošetřím, tak se to typicky nezkompiluje, nebo vyskáčou warningy. Ty nástroje na ošetření těch stavů jsou dost propracované, takže to fakt není to typické "pokud chyba, tak..". Ono pak se ti prakticky nestane, že někde něco zapomeneš ošetřit a vzniká daleko menší prostor pro to, aby ti třeba nějaký hacker zatopil....
Tohle
 perl6  -e 'for lines() { say join ";\t", ++$, $_, ++(%){ .split(":")[*-1] } }' /etc/passwd vepředu očísluje řádky a na konci je očísluje zvlášť pro každý shell. Kdybych výše zmíněného chování nevyužil, tak bych pro každý klíč (shell) musel testovat jestli už je definován.
...write-only kód? Aneb aby ten, kdo to čte, byl zhruba 2x geniálnější než ten, kdo to píše...fakt netuším, co to dělá a to teda ani náznakem.
Jak se chová v Haskelu např. "+" v následujícím případě?  perl6 -e 'say "12" + 1' #13 
Nepřeloží se to. Bůhví, co programátor pil, když chce po počítači sečíst řetězec a číslo.
			 
			
			- 
				
Protože spousta algoritmů je moc hezky popsána rekurzivně - tak proč to tak nepsat.
Pomocí tail-call optimalizovatelné rekurze zapíšete jen algoritmy, které se dají snadno zapsat smyčkou.
Ta funkce nemusí volat jenom sama sebe.
			 
			
			- 
				
Tohle
 perl6  -e 'for lines() { say join ";\t", ++$, $_, ++(%){ .split(":")[*-1] } }' /etc/passwd vepředu očísluje řádky a na konci je očísluje zvlášť pro každý shell. Kdybych výše zmíněného chování nevyužil, tak bych pro každý klíč (shell) musel testovat jestli už je definován.
...write-only kód? Aneb aby ten, kdo to čte, byl zhruba 2x geniálnější než ten, kdo to píše...fakt netuším, co to dělá a to teda ani náznakem.
To stejné můžete říct o každém jazyce, o kterém jste si nic nepřečetl.
https://docs.perl6.org/language/variables#The_%_Variable (https://docs.perl6.org/language/variables#The_%_Variable)
https://docs.perl6.org/language/variables#The_$_Variable (https://docs.perl6.org/language/variables#The_$_Variable)
https://docs.perl6.org/language/variables#The_$__Variable (https://docs.perl6.org/language/variables#The_$__Variable)
			 
			
			- 
				
To stejné můžete říct o každém jazyce, o kterém jste si nic nepřečetl.
Až na to, že jsem před docela mnoha lety s Perlem strávil docela dost času. Napsal jsem v tom takový větší program, vrátil jsem se k tomu za 3 měsíce vůbec jsem netušil, co to dělá. Takhle extrémně se mi to nikdy předtím ani potom nestalo. Mně to fakt připadá jako "executable line-noise", protože si to kvantum paznaků fakt zapamatovat nedokážu. Ale dobře, asi tuším.....jak moc si jste jistý, když něco takového napíšete, že v tom není chyba?
Jinak tohle je pěkný příklad kódu, který se zrovna v haskellu takhle krátce fakt nenapíše - silně mutable a "protkaný" efekty. Na takovéhle hacky to fakt není :)
			 
			
			- 
				
A mně se třeba líbí, že mě Haskell donutí explicitně ošetřit drtivou většinu hraničních stavů. Když něco neošetřím, tak se to typicky nezkompiluje, nebo vyskáčou warningy.
A před chvílí jste vyčítal Pythonu to, že vyhodí výjimku, a teď si v tom libujete. Opět je to o přístupu.
 perl6 -e 'for lines() { say join ";\t",++$,$_, ++(%){ .split(":")[*-1] } }' /etc/passwd ...write-only kód? Aneb aby ten, kdo to čte, byl zhruba 2x geniálnější než ten, kdo to píše...fakt netuším, co to dělá a to teda ani náznakem.
Ano, je to nečitelné, ale jednak one-liner to snese a  je to úplný příklad, který si lze ozkoušet. Nedělejte si iluze, že vaše příklady v Haskellu jsou všem srozumitelné.
Jak se chová v Haskelu např. "+" v následujícím případě?  perl6 -e 'say "12" + 1' #13 
Nepřeloží se to. Bůhví, co programátor pil, když chce po počítači sečíst řetězec a číslo.
Takže sečítat Nothink s číslem je v pořádku, ale řetězec obsahující číslo s číslem už ne?
Využítí viz
perl6 -e 'my $text="2 8 4 7"; put $text.words.map: * + 1' #3 9 5 8   
			 
			
			- 
				
...
Takže sečítat Nothink s číslem je v pořádku, ale řetězec obsahující číslo s číslem už ne?
Nothing se nikde s cislem nesecita :D. Operator "<-" (prepise se na operaci bind) to z Maybe monady "vybali" a scita se cislo s cislem.
			 
			
			- 
				
[quote]
perl6 -e 'my $text="2 8 4 7"; put $text.words.map: * + 1' #3 9 5 8 
[/quote]
perl6 -e 'my $text="2 ? 4 7"; put $text.words.map: * + 1' #3 9 5 8
Cannot convert string to number: base-10 number must begin with valid digits or '.' in '⏏?' (indicated by ⏏)
  in block <unit> at -e:1
Actually thrown at:
  in block <unit> at -e:1
pro srovnání:
Prelude> import Text.Read
Prelude Text.Read> fmap (fmap (+(1::Int))) $ fmap readMaybe $ words "2 ? 4 7"
[Just 3,Nothing,Just 5,Just 8]
			 
			
			- 
				
A mně se třeba líbí, že mě Haskell donutí explicitně ošetřit drtivou většinu hraničních stavů. Když něco neošetřím, tak se to typicky nezkompiluje, nebo vyskáčou warningy.
A před chvílí jste vyčítal Pythonu to, že vyhodí výjimku, a teď si v tom libujete. Opět je to o přístupu.
Já to pythonu nevyčítal - IMO to je výrazně lepší přístup než v Perlu. Psal jsem, že s tou návratovou hodnotou se lépe pracuje. Třeba konkrétně víte, co vám funkce vrátí. Python checked exceptions nemá, takže to netušíte. Java je třeba má, ale ta práce s nimi taky není zrovna pohodlná - viz příklad od "v".
příklady v Haskellu jsou všem srozumitelné.
To si nedělám - protože ten jazyk je úplně jiný, než imperativní jazyky. Ale když se na svůj kód podívám po roce, tak mu aspoň sám kupodivu rozumím. Ale tohle není o jazyce - ona je to hezká soutěž snažit se napsat všechno na jednom řádku - v FP se něčemu podobnému říká point-free style. Akorát že když se to přežene, tak z toho fakt není poznat, co to vlastně dělá - proto to normální lidi používají dost střídmě.
f = (1 +) . ap ((+) . join (*)) (2 *) -- totéž jako: f x = x*x + 2*x + 1
Akorát, že Perlisti se v tom evidentně vyžívají a psaní write-only kódu považují za výhodu....
perl6 -e 'my $text="2 8 4 7"; put $text.words.map: * + 1' #3 9 5 8
Ono řešit, jestli jsou na vstupu vůbec korektní data, není dneska zrovna v módě....že někde za běhu vyskakují warningy je opravdu zajímavé - kdo je čte?
			 
			
			- 
				
FP programátoři jsou totiž docela neradi, když jim "pure" kód vyhazuje výjimky.
Což se ale v Haskellu děje celkem často [] !! 1, head [], 1`div`0 + řada případů, kdy něco vyhazuje Stack overflow, protože někdo někde nepoužil seq (třeba foldl (+) 0 [1..1000000]) nebo kompilátoru něco nedošlo.
No a právě pro to lidi, co v haskellu programují  [] !! 1, head [] prakticky nepoužívají. Někdy si lidi do projektů importují vlastní Prelude, kde jsou všechny tyhle funkce vynechané a konstantně se vede diskuze, jestli to nevyhodit i z oficiálního Preludu (jenomže učte pak začátečníky....). Teď jsem se zoufale snažil přivést ghci ke stackoverflow pomocí foldl a nezdařilo se; mimochodem, to mě docela překvapilo - když se to kompiluje se zapnutou optimalizací, tak se (konkrétně tenhle) foldl zfůzuje a funguje to úplně v pohodě...ale jasně tyhle věci se dějí, ale stalo se mi to snad jednou. Takže v podstatě zbývá to dělení nulou.
Nemám vyzkoušeno, ale myslím, že na stack overflow budou padat např. implementace Eq a Ord vygenerované pomocí deriving pro stromové struktury, které mají alespoň 2 větve (např. binární stromy). Konkrétně, když budou porovnávané struktury hlubší (např. 10 milionů nebo 100 milionů vnoření) ve více větvích. Ale to se děje prakticky ve všech populárních funkcionálních jazycích.
když se to kompiluje se zapnutou optimalizací, tak se (konkrétně tenhle) foldl zfůzuje a funguje to úplně v pohodě...ale jasně tyhle věci se dějí
Je otázka, zda není špatně, že optimalizace udělá z nefunkčnícho programu program funkční. Navíc je otázkou, jak jsou takové optimalizace robustní - jestli malá změna v programu na jiném místě nezpůsobí nečekané vypnutí této optimalizace a program pak přestane pracovat správně.
			 
			
			- 
				
Je otázka, zda není špatně, že optimalizace udělá z nefunkčnícho programu program funkční. Navíc je otázkou, jak jsou takové optimalizace robustní - jestli malá změna v programu na jiném místě nezpůsobí nečekané vypnutí této optimalizace a program pak přestane pracovat správně.
Špatně je, pokud je program postavený na tom, že to takhle funguje... Ale teď jsem někde zahlédl supr příklad (z hlavy, nezkoušel jsem):
import Data.Vector as V
take 5 $ V.toList $ V.fromList [1..]
Když se to korektně zfůzuje, tak ten kód skončí. Ale fakt nejsem schopen odpovědět na otázku, jestli je to dobře nebo špatně, protože když už to ten výsledek vrátí, tak je vlastně korektní.....