Fórum Root.cz
Hlavní témata => Vývoj => Téma založeno: Mirek Prýmek 22. 03. 2016, 22:36:40
-
Zdar vespolek,
chtěl bych se zeptat na vaše názory a zkušenosti s funkcionálními jazyky/frameworky na webovém frontendu. Konkrétně mě zajímá, jak vidíte zralost, použitelnost a přínosnost jednotlivých řešení, která se poslední dobou vynořují. ...a taky, jakou cestou podle vás má smysl v současné době jít pro jaký usecase a míru odvahy ;) Weby mě neživí, dělám je jenom pro interní potřebu, takže tu oblast úplně detailně nesleduju a budu rád za postřehy vás, kteří se v tom pohybujete víc a máte smysl pro FP.
Obecně mě zaujala myšlenka virtuálního DOMu, kompletní umístění view logiky na frontend (konec dvoukolejnosti) a její znovupoužitelnost a možnost nepřepínání se z funkcionálního světa (v mém případě http://www.phoenixframework.org/) do [doplňte sami] javascriptu.
Co jsem tak koukal, mám dojem, že jsou dvě základní možnosti:
- buď nějaký javascriptový framework, který FP principy aspoň trochu ctí a využívá (React, Flux? Hodně mě zaujal Cycle.js a ještě víc jeho úspornější varianta Motorcycle)
- nebo plnotučný jazyk překládaný do JS: Elm, Purescript
Víc mě láká druhá varianta, protože bych rád z JS světa utekl, ale nejsem si jistý, jak zralé ty věci jsou (pro ne úplně kritické nasazení, ale i tak chce člověk rozumnou zralost minimálně aby se to dobře používalo a nemusel řešit koniny) a taky si nejsem jistý, jestli se výhoda striktně čistého haskelloidního FP neprojeví spíš na větším projektu. Prostě, lidově řečeno, jestli si u menšího projektu člověk trochu nenaběhne na vidle - propojit pár tlačítek a WS událostí s nějakou víceméně jednoduchou akcí může být příjemnější pár řádky JS (?), ne-čistý jazyk umožňuje pohodlně si někam přidat ladící výpis, rychle drobně doladit logiku a neřešit změnu typu v půlce kódu...
Prostě, sečteno a podtrženo, docela mě ta představa láká, ale je to dost velká investice a nejsem si jistej, jestli to dává racionálně smysl. V současnosti jsem nejvíc nakloněnej Elmu, ale nechám si poradit :)
Dík za vaše zkušenosti a názory. Hlavně těm, kdo s něčím z popsanýho mají větší reálné zkušenosti.
EDIT: jo, ještě jsem zapomněl důležitou poznámku: SPAs mě nezajímají, dělám klasické "stránkové" aplikace, i když třeba s dynamickým obsahem ládovaným pomocí WS.
-
Uvazoval jsi o ClojureScriptu? Celkem se to rozjizdi a lidi si nejvic povazuji stejny jazyk na frontendu a backendu (JS jde na to stejny z druhe strany :-)
-
Uvazoval jsi o ClojureScriptu?
Ne, protože LISP-like jazyky nějak nejsem schopnej překousnout :) Je v Clojure-světě nějaký vyloženě famózní framework, který by stál za to se kousnout a tu nechuť překonat?
Tak mě napadá, nerozhlížel jsem se ani v F# světě, jestli něco nemají. Nebo že by OCamláři? ;)
-
Uvazoval jsi o ClojureScriptu?
Ne, protože LISP-like jazyky nějak nejsem schopnej překousnout :) Je v Clojure-světě nějaký vyloženě famózní framework, který by stál za to se kousnout a tu nechuť překonat?
jj chápu, může to být nezvyk. Nějaký úplně skvělý framework, okolo kterého by byl hype jako v dobách RoR, tady asi (pro CljS) není. Spíš to jsou jednotlivé knihovny, které si člověk sám poskládá dohromady přesně tak, jak potřebuje. Takže možná to F#.
-
Nějaký úplně skvělý framework, okolo kterého by byl hype jako v dobách RoR, tady asi (pro CljS) není. Spíš to jsou jednotlivé knihovny, které si člověk sám poskládá dohromady přesně tak, jak potřebuje. Takže možná to F#.
Tak to by nebylo nic pro mě, to mi za prošoupané klávesy se závorkami nestojí ;))
-
Mám dobrou zkušenost s F# a frameworkem WebSharper. HTML však renderuji pomocí Reactu.
Obdobně dobrou zkušenost mám se Scalou a ScalaJS. Navíc ScalaJS má binding pro React (osobně jsem ho však nezkoušel, když jsem to používal, tak ještě neexistoval).
nebo plnotučný jazyk překládaný do JS: Elm, Purescript
V těchto jazycích ale nejde napsat serverovou část, nebo ano? Navíc budou mít menší komunitu než F# a Scala.
Nebo že by OCamláři?
AFAIK tam žádný rozumný framework není, akorát existuje pár bindingů pro js_of_ocaml.
-
Mám dobrou zkušenost s F# a frameworkem WebSharper. HTML však renderuji pomocí Reactu.
Matně si vzpomínám, že jsem o WebSharperu něco někdy slyšel. Díky za tip, kouknu. Jak je to ale s praktickým používáním? Vidím tam VisualStudio, NuGet... to jsou vody, do kterých bych se nerad namočil jenom kvůli frontendu ;)
A jaký je ten React? Pracuje se s tím dobře, je to dobře navržené? Četl jsem tak porůznu všelijaké poznámky, že si to na FRP jenom hraje...
Obdobně dobrou zkušenost mám se Scalou a ScalaJS. Navíc ScalaJS má binding pro React (osobně jsem ho však nezkoušel, když jsem to používal, tak ještě neexistoval).
Díky, to jsem taky nezkoumal.
V těchto jazycích ale nejde napsat serverovou část, nebo ano?
Nejde mi o sjednocení frontendu a backendu (možná jsem to napsal trochu nesrozumitelně). S Phoenixem jsem extrémně spokojenej a nedám ho ani za nic :) Hlavní motivace, proč uvažuju o změně, jsou asi tyhle:
- činí mi utrpení se neustále přepínat z funkcionálního (Elixir) módu myšlení do JS
- JS celkově nemám rád (ES6 je výrazně stravitelnější, ale pořád nepříjemný)
- nebaví mě řešit neustále boilerplate kolem komunikace tam a zpátky
- doteď jsem si docela vystačil s vlastním JS kódem+jquery, ale jakmile věci trochu narostou, je to utrpení
ad 1 - celkem bych byl ochotnej akceptovat i JS framework, který je napsaný funkcionálním stylem. Ten Cycle.js mi přijde v pohodě. Opravdu funkcionální jazyk je spíš takový trochu bonus navíc, úplně nutně na tom netrvám.
ad 4 - teď řeším view převážně templatama ve Phoenixu, s tím, že když potom chci něco udělat dynamičtější, tak k tomu napíšu nějaké ty transformace v jquery. Vede to ale k tomu, že ty věci pak píšu dvakrát, někdy i třikrát. Chtěl bych nějakou modularitu, nějaké komponenty, ale zase ne šílenou jadernou elektrárnu. Proto mi přijde, že funkcionální framework by byl prima - hodím mu data, vykreslí HTML. Snadným, předvídatelným, srozumitelným způsobem. Žádné tisíce monkeypatchovaných JS objektů dělajících kdovíco kdovíkde...
Navíc budou mít menší komunitu než F# a Scala.
To rozhodně - předpokládám, že o několik řádů :)
-
FP na webu? Javascript. A každý jazyk nakonec dopadne jako JS. Další verze jeho funkcionální povahu budou postupně oslabovat.
-
Mám dobrou zkušenost s F# a frameworkem WebSharper. HTML však renderuji pomocí Reactu.
Vidím tam VisualStudio, NuGet... to jsou vody, do kterých bych se nerad namočil jenom kvůli frontendu ;)
...
Nejde mi o sjednocení frontendu a backendu (možná jsem to napsal trochu nesrozumitelně).
Aha, pak ten F# a WebSharper nemá asi cenu zkoušet. Osobně se mi na něm líbí, jak jednoduché je volat serverové funkce z klienta (funkci na serveru stačí označit atributem Remote a WebSharper se o zbytek postará - např. při kompilaci klientského kódu zkontroluje, že serverová funkce existuje a má správný typ), nebo raději spravuji stav klientské části aplikace v F# než v JavaScriptu (F# má například algebraické datové typy).
A jaký je ten React? Pracuje se s tím dobře, je to dobře navržené?
Ano, pracuje se s ním dobře. Nicméně idea, že UI je čistou funkcí stavu, jenž je uložen na jednom místě a spravujete jej např. v F# nebo Scale, v praxi IMO úplně neplatí - některé komponenty si drží vlastní stav (např. kde je posuvník nebo stav týkající se animace). V té Scalovské aplikaci jsme měli problémy s výkonem (stav UI se měnil příliš často a přerenderování celého UI bylo příliš pomalé), ale podařilo se je snadno vyřešit pomocí shouldComponentUpdate (jednoduše jsme ve Scale porovnali části stavu, na nichž daná komponenta závisí).
Četl jsem tak porůznu všelijaké poznámky, že si to na FRP jenom hraje
Osobně FRP chápu jako programování se signály, jenž se mění (mění svou hodnotu) v čase. V tomto ohledu React skutečně není FRP.
-
A jaký je ten React?
Hlavní výhodou Reactu a podobných frameworků je, že stačí napsat kód pro vytvoření UI, ale nemusíte psát kód pro jeho aktualizaci (např. když nastane nějaká událost), což u složitějších UI výrazně zjednodušuje práci. Proto s WebSharperem používám React a nepoužívám Formlety, Piglety a jiné nástroje pro tvorbu klientského UI, jenž jsou přímo součástí WebSharperu.
-
možnost nepřepínání se z funkcionálního světa do javascriptu.
Tomuhle nerozumím. Vždyť JavaScript je také funkcionální. Chcete jazyk, který bude jen funkcionální a nebude podporovat jiná paradigmata?
-
možnost nepřepínání se z funkcionálního světa do javascriptu.
Tomuhle nerozumím. Vždyť JavaScript je také funkcionální. Chcete jazyk, který bude jen funkcionální a nebude podporovat jiná paradigmata?
Programovat funkcionálně lze v každém jazyku. Je to jen věc vnitřní disciplíny, která patří k mistrovství v každém oboru.
-
Tomuhle nerozumím. Vždyť JavaScript je také funkcionální. Chcete jazyk, který bude jen funkcionální a nebude podporovat jiná paradigmata?
V JS se dají používat některé FP patterny. Napsal jsem, že bych byl ochotný používat framework, založený jenom na nich (jako je např. ten cycle.js - viz http://cycle.js.org/ ) a pro moje účely by to možná bylo i racionálnější než čistě funkcionální jazyk.
-
Obecně mě zaujala myšlenka virtuálního DOMu, kompletní umístění view logiky na frontend (konec dvoukolejnosti) a její znovupoužitelnost
EDIT: jo, ještě jsem zapomněl důležitou poznámku: SPAs mě nezajímají, dělám klasické "stránkové" aplikace, i když třeba s dynamickým obsahem ládovaným pomocí WS.
S umístění view logiky na frontend jsem začal s Angularem - a v momentě, kdy to uděláš, tak na backendu v podstatě nepotřebuješ framework a vznikne ti SPA. Následně jsem zjistil (možná to jiní budou mít jinak), že už nikdy žádný backendový framework nechci potkat. Je to trošku syndrom "když máš kladivo, je všechno pro tebe hřebík", ale psaní aplikací tímhle způsobem je prostě komfortní a hlavně z ničeho nic můžeš mít naprosto "normální" backend psaný v "normálním" jazyce bez nějakých frameworkových vymyšleností (nemám zkušenosti s tím, jak frameworky "pomáhají" řešení autorizace, nevím, nakolik to u REST API jde principiálně zjednodušit). Mám trochu pocit, že SPA a "view logika na frontendu" je v podstatě totéž (protože když už tu view logiku děláš na frontendu, tak mi trochu nedává smysl dělat ovládání toho view na backendu).
Mám trochu zkušenosti s GHCJS.
+ Sdílení kódu s backendem
+ Prakticky neřešíš API mezi backendem a frontendem - stačí mít serializační instance pro data (auto-generované), která si posíláš, "a je to". Když v API něco změníš, kompilátor ti pohlídá, že ti to na frontendu i backendu souhlasí
+ Normální (i nenormální - s extensionama) haskell
- Pokud knihovna používá nějaké C FFI, tak to nemusí fungovat - ale většina běžných knihoven funguje, je možnost to doplnit přes "JS shims"
- V angularu jsem byl zvyklý používat angular-bootstrap jako UI knihovnu - v ghcjs (resp. reflex) to není, a je to potřeba napsat (možná časem něco zveřejním)
- Reflex (FRP)....je trochu zvláštní. Když máš stránku, kde na sobě navzájem závisí několik různých prvků, tak skončíš s "pavučinou" napsanou v RecursiveDo. Zatím mi to nepřipadá úplně "skvělé a úžasné", na druhou stranu nevím, jestli principiálně existuje možnost to zjednodušit, protože na té stránce skutečně ty prvky mezi sebou mají pavučinu závislostí. Asi se časem poohlédnu po alternativách - existují bindingy React, možná se s tím bude psát lépe? Když v jQuery člověk napíše nějaký selector, tak je to vlastně strašně silný nástroj, jenže bez typové kontroly....
- Zkompilovaný js je VELKÝ (1MB+)
- Rychlost - není to úplná tragédie, zas to není nějaká extra výhra. Ono se to tak trochu renderuje "postupně" ("Dynamic v Dynamicu") a pokud je nějaká výrazně dynamičtější stránka (generovaná stylem dynamic v dynamicu), tak to je vidět
* kupodivu to funguje jak má - ne že by člověk nenarazil občas na chybu, ale zatím nic zákeřného
Alternativa je Haste, který by se měl kompilovat do výrazně menšího JS, zas spoustu věcí z haskellu neumí, což je trochu problém. Sdílení kódu (nebo aspoň datových struktur) s PureScriptem a Elemem je prý možné, ale nic moc...
-
Díky, Andy, za zajímavý zkušnosti!
S umístění view logiky na frontend jsem začal s Angularem - a v momentě, kdy to uděláš, tak na backendu v podstatě nepotřebuješ framework a vznikne ti SPA. [...] Mám trochu pocit, že SPA a "view logika na frontendu" je v podstatě totéž (protože když už tu view logiku děláš na frontendu, tak mi trochu nedává smysl dělat ovládání toho view na backendu).
Mně vyhovuje, že když mám oddělené stránky, můžu si na backendu řešit, která je jak autentizovaná apod. Tohle určitě měnit nechci. Navíc celej ten koncept SPA se mi nelíbí (nemožnost odkazovat přes URL zvnějšku apod.)
stačí mít serializační instance pro data (auto-generované), která si posíláš, "a je to". Když v API něco změníš, kompilátor ti pohlídá, že ti to na frontendu i backendu souhlasí
Tohle bych právě hodně chtěl, ale určitě kvůli tomu nebudu přecházet na Haskell na backendu. Spíš si asi zkusím promyslet, jestli by se to nedalo pořešit nějakýma makrama v Elixiru, který by mi třeba vygenerovaly boilerplate v JS pro přístup k datům. Momentálně se snažím všechna data přenášet přes websockety (REST jsem už víceméně pohřbil), takže to je jenom otázka definice handlerů pro události ze strany serveru a funkcí pro volání z druhé strany. Nechám si to projít hlavou, možná spojení tohodle + nějaký rozumný framework (Cycle.js nebo React) by bylo pro mě nejlepší.
- Zkompilovaný js je VELKÝ (1MB+)
To bych určitě nebyl ochotnej akceptovat. Jednak mě to dráždí principielně ;) ale hlavně taky potřebuju servírovat mobilům a tam je to s těma datama pořád na štíru... Kolem 100kb je ok, níž se dneska člověk nedostane, kolem 200 už začínám brblat a 400 a víc by bylo vyloženě nepřijatelný :)
-
Navíc celej ten koncept SPA se mi nelíbí (nemožnost odkazovat přes URL zvnějšku apod.)
Tohle je ale dneska non-issue. V angularu se to dělá tak, že ve frontendové aplikaci byly view v "/app/cokoliv", server pro "/app/cokoliv" servíroval default HTML stránku, angular si následně z linku automaticky zjistil, na který jsi stránce a otevřel ti to view. Při kliknutí na link automaticky vyupdatoval URL v záhlaví. Takže jediná otázka je, jak se k tomu postaví search enginy a i ty už to dneska nějak zvládají.
Momentálně se snažím všechna data přenášet přes websockety (REST jsem už víceméně pohřbil), takže to je jenom otázka definice handlerů pro události ze strany serveru a funkcí pro volání z druhé strany. Nechám si to projít hlavou, možná spojení tohodle + nějaký rozumný framework (Cycle.js nebo React) by bylo pro mě nejlepší.
Erlang přístup ;) Já používám v haskellu Servant a ten umožňuje jednoduše nadefinovat Rest API, ale na websockets v tom nic není - ale je to zajímavý, možná teď budu psát nějakou aplikaci, kde by se mi to hodilo, tak uvidím, co z toho vznikne.
To bych určitě nebyl ochotnej akceptovat. Jednak mě to dráždí principielně ;) ale hlavně taky potřebuju servírovat mobilům a tam je to s těma datama pořád na štíru... Kolem 100kb je ok, níž se dneska člověk nedostane, kolem 200 už začínám brblat a 400 a víc by bylo vyloženě nepřijatelný :)
GHCJS na mobily není. To není principiální věc, prostě není, ten runtime je trošku žravý a mobily to nedávaj. Haste generuje výrazně menší kód a je dost haskell-compatibile, problém je, že i něco typu "90% kompatibilní" je na houby, když zrovna potřebuješ něco z těch 10%... možná teď budu psát aplikaci, která teoreticky bude i na mobily, tak budu asi zase hledat :)
-
Erlang přístup ;)
Jj. Moje největší webová aplikace je frontend k monitoringu a správě sítí, takže to jsou pořád nějaký tabulky a grafy a všechno by to mělo být pokud možno dynamický. Takže události, události, události, většina asynchronní - ideální use case pro Erlang ;)
Nejčastější věc, kterou řeším, je vygenerování tabulky z nějaké datové struktury + její updaty (z obou stran - události ze server, události od uživatele). Doteď jsem to dělal "po staru": počáteční tabulka se vygeneruje pomocí tamplatu na backendu a úpravy pak řeší pomocí jquery. Ale už mě to začíná silně prudit, protože se ten kód duplikuje a špatně udržuje. Vždycky to začne s tím, že "jquery stačí, událostí bude málo" a jak se to postupně komplikuje, je to čímdál větší opruz.
Takže moje současná představa je dělat to tak, že template vytvoří jenom omáčku: vlastní stránku + menu a připojení na websocket. Hned po připojení se přes WS pošle init stav, který se vykreslí už čistě na frontendu, a změny se posílají už jenom přes WS. Blbý na tom je, že tímhle způsobem tam vznikne lag mezi vykreslením menu a contentu, ale co jsem to zatím testoval, je to celkem rychlý, takže by to nemělo vadit. Pokud bych zjistil, že to problém je, nechal bych komplet stránku vykreslit na frontendu. Lag tam sice pořád bude, ale aspoň se vykreslí všechno naráz, což je asi pocitově příjemnější.
Tahle představa je teď ve fázi testování, možná se to ukáže jako blbost a udělám to jinak :) Ale teď momentálně se mi ta představa líbí, je to takový hezky jednotný a přímočarý ;)
-
BTW, jeden z důvodů, proč bych chtěl vykreslovat čistě na frontendu, je ten, že ty události chodí fakt kdykoli (z nižší vrstvy aplikace, úplně mimo web) a mezi vykreslením na backendu a připojením na websocket je mezera, ve které se nějaká událost může ztratit - na webu se neobjeví. Ne že by to byl nějakej třeskutej problém prakticky, ale pocitově mě to silně dráždí, protože to je návrhový nedostatek ;)
-
já bych taky potřeboval GUI k aplikaci ve funkcionálním jazyce (Haskell), jestli mi poradíte jak na to tak se pak podělím o zkušenosti :)
dá se říct, že ve webových technologií jsem úplně ztracený
chci napsat co nejmíň html a js, data posílat přes ws a spa (jestli jsem to správně pobral) mi nevadí, možná právě naopak, charakteristika aplikace je shodná s tou prýmkovou (technologie něco dělá, stromy, tabulky a grafy se mění)
-
Navíc celej ten koncept SPA se mi nelíbí (nemožnost odkazovat přes URL zvnějšku apod.)
Nemoznost odkazovat se na SPA - takovy problem davno neni. V Angularu to resi napr. ui-router (https://github.com/angular-ui/ui-router) a o vsechno to prepisovani URL a historii se to stara samo. K "apod." a "SPA se mi nelíbí" se bohuzel nemohu moc vyjadrit, chce to uvest konkretnejsi duvody.
Mně vyhovuje, že když mám oddělené stránky, můžu si na backendu řešit, která je jak autentizovaná apod. Tohle určitě měnit nechci.
Muzete mit oddelene REST end-pointy a ty authentizovat stejne, jak nyni mate stranky, nevidim v tom zadny problem.
Presne jak popisujete to generovani na serveru a pak znovu na FE, tak by to SPA elegantne preklenulo - proste se vsechny stranky generuji na klientovi a hotovo. Server pak muze "zhloupnout" a slouzit spis jako prostrednik na preposilani dat a overovanim auth tokenu.
-
Kdyby slo o SPA, tak bych jednoznacne kazdemu doporucil Meteor + React + Underscore a nejaky knihovny na routovani (asi ReactRouter) a formulare (asi formsy-react). Na normalni stranky je to zbytecny, to je jasny. Me se ted hodne zalibilo prave to Elm (vlastne si to myslim daval ty ten odkaz na nejakou prezentaci na YT), ale nemel jsem moc casu se na to podivat nejak podrobneji, protoze ted fusuju do neceho jinyho. To Elm pry resi vsechno co React a jeste daleko lepe a elegantneji (hlavne protoze to neni JavaScript).
-
Ta ScalaJS (http://www.scala-js.org/) vypada fakt zajimave, pusobi to na me, ze se celkem rozjizdi (musim se k tomu nekdy dokopat a zkusit ji). Ma to "bindingy" na React, Angular, Vue a dalsi (http://www.scala-js.org/libraries/facades.html). Z FP knihoven (http://www.scala-js.org/libraries/libs.html) to podporuje i tezkotonazni Scalaz, coz me celkem prekvapilo. Vykonem i velikosti ty vypada i pouzitelne. Akorat teda nevim, jestli se to OP vyplati zkouset, pokud jazyk na BE ma uz zvoleny, protoze tim IMO prijde o tu nejvetsi vyhodu - jeden silne typovany jazyk na obou stranach, coz umozni sdileni kodu.
-
Nemoznost odkazovat se na SPA - takovy problem davno neni. V Angularu to resi napr. ui-router (https://github.com/angular-ui/ui-router) a o vsechno to prepisovani URL a historii se to stara samo. K "apod." a "SPA se mi nelíbí" se bohuzel nemohu moc vyjadrit, chce to uvest konkretnejsi duvody.
Jak jsem říkal, weby mě neživí, takže to nemám nastudované kdovíjak do hloubky. Věřím, že všechny problémy nějak řešit jdou, ale nemám motivaci je řešit, když ty problémy nemám :) Pro mě osobně je to dost narovnávák na ohýbák... Začít dělat SPA by mi nepřineslo nic než spoustu práce a problémů.
Presne jak popisujete to generovani na serveru a pak znovu na FE, tak by to SPA elegantne preklenulo
To ano, ale taky by se na FE přenesla logika, kterou tam mít nechci, protože si ji pohodlně a příjemně řeším na BE a nemám motivaci to měnit. Ten způsob s websockety, který jsem popisoval výš, je prakticky stejný, jenom ty stránky zůstávají. Kdybych časem zjistil, že se jich chci zbavit a přejít na SPA, tak už to potom bude snazší.
-
- Zkompilovaný js je VELKÝ (1MB+)
Zkoušel jsi použít Google Closure Compiler? Teoreticky by měl umět vyhazovat smetí, nepoužité věci, a tak.
-
Me se ted hodne zalibilo prave to Elm (vlastne si to myslim daval ty ten odkaz na nejakou prezentaci na YT), ale nemel jsem moc casu se na to podivat nejak podrobneji, protoze ted fusuju do neceho jinyho. To Elm pry resi vsechno co React a jeste daleko lepe a elegantneji (hlavne protoze to neni JavaScript).
Elm se mi líbí hodně. Ale pořád si nejsem jistý praktičností. Přece jenom jeto haskellovitost - nemůžeš jenom tak někam šáhnou a udělat rychlou úpravu, protože se ti rozjedou typy... Mají skvělou JSON knihovnu http://package.elm-lang.org/packages/elm-lang/core/1.1.0/Json-Decode jenže zas - struktura JSONu musí přesně sedět. Když se tam objeví null někde, kde jsi ho nevyspecifikoval, celý JSON spadne pod stůl, protože se nenamatchuje...
Na kvalitní precizní práci a na větší projekty to musí být skvělý, to si umím přestavit. Jenom nevím, jestli já ty svoje věci nedělám trochu moc živelně na to, abych tohle mohl efektivně použít. A navíc Haskell sice trochu znám, ale nic reálnýho jsem v něm nedělal, takže je to pro mě trochu mindfuck :) Uvidím, jestli seberu odvahu se do toho pustit. Zatím se mi to líbí hodně.
-
Jak jsem říkal, weby mě neživí, takže to nemám nastudované kdovíjak do hloubky. Věřím, že všechny problémy nějak řešit jdou, ale nemám motivaci je řešit, když ty problémy nemám :) Pro mě osobně je to dost narovnávák na ohýbák... Začít dělat SPA by mi nepřineslo nic než spoustu práce a problémů.
Zato presun na ciste funkcionalni UI problemy neprinese? :D Na narozdil od toho cisteho FP se SPA pouzivaji v obrovskych web aplikacich (predevsim Angular 1 a React), takze jak pises vyse, na ta jednoducha pouziti je to plne vychytane a na ta slozitejsi se muzes spolehnout obrovskou komunitu. To u Elmu nebo PureScriptu proste nemas a asi ani vyhledove v nekolika letech mit nebudes.
K "narovnávák na ohýbák" - ze zacatku jsem byl taky skepticky, ale bylo to dano jen tim, ze jsem byl zvykly na stary zpusob. O SPA premyslej jako o applikaci na smartphone, klientovi se jednou prenese (nainstaluje) a appka si sama vse rendruje a otravuje server jen kvuli datum a operace s daty, ne kvuli kazdemu prekresleni stranky, ktere musi byt specialne reseno pro kazdeho klienta.
Začít dělat SPA FP UI by mi nepřineslo nic než spoustu práce a problémů.
...
To ano, ale taky by se na FE přenesla logika, kterou tam mít nechci, protože si ji pohodlně a příjemně řeším na BE a nemám motivaci to měnit. Ten způsob s websockety, který jsem popisoval výš, je prakticky stejný, jenom ty stránky zůstávají. Kdybych časem zjistil, že se jich chci zbavit a přejít na SPA, tak už to potom bude snazší.
Tak jiste, pokud mas uz BE hotovy vcetne sablon stranek, tak to za to nestoji. Pokud ale ne a nemusis resis takove pytloviny jako podporovat ne-JS verzi a 10 let stary prohlizece, tak mi SPA prijde jako dobra volba. Resp. proc chces mit stav klienta na serveru? Vetsinou muze byt BE ukradeny, ze Lojza je na strance "o projektu". Definovani routovani je (z mych velmi omezenych zkusenosti s BE) hodne podobne jako na BE, akorat to pises pro klienta misto pro server. K tomu overovani, vzdyt to snad musis stejne resit primo na jedno pripojeni WS, takze v SPA verzi se nic nezmeni, ne (je teda mozny, ze to neni pravda, s WS jsem delal jednou)? Zrovna toho prihlaseni bych se treba v Angularu vubec nebal, je to v podstate jen jeden interceptor, kterej do kazdeho dotazu prihodi token a pak to "magicky" funguje vsude. Server si akorat zkontroluje token, pokud klient pristupuje k zabezpecenmu zdroji a konec. BE nehrabe jakkoliv do HTML, maximalne posle staticky soubor (sablonu) FE a ten si ji prechroupa. Libi se mi to oddeleni, ze na severu se neresi zadne vizualni veci, to vsechno patri na FE.
-
- Zkompilovaný js je VELKÝ (1MB+)
Zkoušel jsi použít Google Closure Compiler? Teoreticky by měl umět vyhazovat smetí, nepoužité věci, a tak.
Oni se ghcjs snaží udělat tak, aby s tím fungovalo (a při nějaké rozumné optimalizaci s tím snad funguje), ale nějak extra výrazně to nezmenší. Navíc jak je Haskell lazy, tak ten runtime je prostě trošku žravější... ale možná to ještě zkusím, mrknu, co to udělá.
-
Eh, >1MB je teda zatracene velky. Ta ScalaJS mela runtime myslim 50kB. Jen tak pro srovnani - Angular, ktery je na pomery JS sveta obrovsky, ma ~150kB.
-
Eh, >1MB je teda zatracene velky. Ta ScalaJS mela runtime myslim 50kB. Jen tak pro srovnani - Angular, ktery je na pomery JS sveta obrovsky, ma ~150kB.
V tomhle jsou dobré kompilátory OCamlu do JavaScriptu. Například ze stránky BuckleScriptu (https://github.com/bloomberg/bucklescript) (zatím není vhodný pro produkční nasazení):
Runtime performance:
BuckleScript Immutable Map: 1186ms
Facebook Immutable Map: 3415ms
Code Size:
BuckleScript (Prod mode): 899 Bytes
Facebook Immutable : 55.3K Bytes
-
Tak pokud by slo hodne o velikost, tak bych tipoval ze bude dobre se drzet co nejblize JavaScriptu (napr. Flow nebo LiveScript, ktery se mi dost libi) a ne se snazit dostat behove prostredi z JVM do JavaScriptu jako v pripade Scaly. Ale abych pradu rekl, tak si myslim, ze problem velikosti JS souboru je zbytecne precenovany. Pokud mate dobre nastavene cachovani, tak to klient bude stahovat prave jednou. Navic lze pouzit nejake verejne CDN a pak to muze klidne vychazet, ze to klient (v prepoctu na vasi stranku) bude stahovat napr. 0,1 krat za rok.
-
O SPA premyslej jako o applikaci na smartphone, klientovi se jednou prenese (nainstaluje) a appka si sama vse rendruje a otravuje server jen kvuli datum a operace s daty, ne kvuli kazdemu prekresleni stranky, ktere musi byt specialne reseno pro kazdeho klienta.
Já ten koncept chápu, uznávám, že dává smysl, a kdybych stavěl komerční aplikaci na zelené louce s týmem lidí včetně kovaného frontenďáka, tak bych do toho asi šel. Ale to není moje situace.
Tak jiste, pokud mas uz BE hotovy vcetne sablon stranek, tak to za to nestoji.
Což je přesně moje situace :) Jeden z těch bodů motivace je, že mě baví Elixir a nebaví JS. A ty mi radíš vzít spoustu bezproblémově funkčního kódu v Elixiru a přepsat ho do JS frameworku, který neznám. To mi nepřijde, že by řešilo můj problém ;)
-
Tak pokud by slo hodne o velikost, tak bych tipoval ze bude dobre se drzet co nejblize JavaScriptu (napr. Flow nebo LiveScript, ktery se mi dost libi) a ne se snazit dostat behove prostredi z JVM do JavaScriptu jako v pripade Scaly. Ale abych pradu rekl, tak si myslim, ze problem velikosti JS souboru je zbytecne precenovany. Pokud mate dobre nastavene cachovani, tak to klient bude stahovat prave jednou. Navic lze pouzit nejake verejne CDN a pak to muze klidne vychazet, ze to klient (v prepoctu na vasi stranku) bude stahovat napr. 0,1 krat za rok.
No jo, to platí pro desktop (proto taky když cíluju desktop, tak se ghcjs nebojím), ale pro mobily to funguje jinak. Ostatně - hezký příklad ghcjs aplikace je tady: http://markup.rocks/ (http://markup.rocks/). Popravdě se mi to dost dlouho nahrává i na desktopu, natož na mobilu (který to nějak vůbec nechroustne).
-
Pokud je problem, ze musis generovat HTML stejny kod jak na serveru tak na klientovi, tak to by SPA presne vyresilo. Psal jsem o ScalaJS, ktera ma binding pro Angular, takze to lze i "bez" JS. Uznavam, ze Angular ze zacatku muze pusobit slozite, ale tim, ze urcuje do urcite miry strukturu projektu vyvoj IMO v zaveru zlehcuje, protoze proste nasledujes best-practises a nemusis lepit dohromady mnoho knihoven (React osobne neznam, ale ten seznam (https://medium.com/@amcdnl/i-m-gonna-puke-if-you-compare-angular-to-react-again-heres-why-2869e0853a14#.i9j489i9y) me celkem vystrasil), protoze skoro vse, co potrebujes, mas primo v jednom frameworku pripravene k pouziti.
...
No jo, to platí pro desktop (proto taky když cíluju desktop, tak se ghcjs nebojím), ale pro mobily to funguje jinak. Ostatně - hezký příklad ghcjs aplikace je tady: http://markup.rocks/ (http://markup.rocks/). Popravdě se mi to dost dlouho nahrává i na desktopu, natož na mobilu (který to nějak vůbec nechroustne).
Eh, Firefoxu to dalo hodne zabrat, nekolik (5?) vterin. Ale mozna teda za to muze nejaky addon, nevim. To chapu, ze by to nektere mobily polozilo. Ale treba ten overhead Scaly (http://www.scala-js-fiddle.com/) nepusobi tak hrozne, mozna vterina. A neni tedy lepsi misto ghcjs vzit radeji ten PureScript (http://try.purescript.org/), ktery me jede jako blesk a je porad haskell-like?
-
FP jazyk bez reaktivity je pro real world použití naprosto nepoužitelný. A UI je real world použití ... ELM a nebo v JS skus React, dost si toho vypujčil z FRP.
-
ELM a nebo v JS skus React, dost si toho vypujčil z FRP.
ELM je momentálně můj favorit. Myslel jsem, že bych šel spíš do Motorcycle, ale jak jsem to testoval, tak bych si pro něj asi stejně musel dopsat tu logiku, která v Elmu je jako základ (událost -> stav -> view) a jedna věc mě dost drasticky odrazuje: pokud dojde k výjimce uvnitř promise (který se tam používají všude), tak prohlížeč nevyplivne řádek původního zdrojáku, ale řádek ve vnitřnostech knihovny. To je dost drastická komplikace, pokud se to nedá nějak řešit (a nevím jak by to šlo). Je to pěkně vymyšlený framework, ale to JS je tam prostě koule na noze...
-
ELM je momentálně můj favorit.
Já jsem v Elmu nic nenaprogramoval, ale asi by mi chyběla řada vlastností z jiných funkcionálních jazyků (zvláště, pokud by se jednalo o větší program).
-
Já jsem v Elmu nic nenaprogramoval, ale asi by mi chyběla řada vlastností z jiných funkcionálních jazyků (zvláště, pokud by se jednalo o větší program).
Co máš namysli? Hodně se probírá absence (haskellovských) tříd. Ještě něco? Jako jazyk jsem to nijak detailně nezkoumal, zatím mi šlo spíš o to si to vyzkoušet prakticky - získat z toho nějaký pocit, jak by se mi tímhle způsobem pracovalo...
Můžeš pls krátce napsat, jestli je tam něco, co by na (spíš jednodušší) praktické programování mohlo mít vliv?
-
Nevím jak je na tom Elm teď, hodně dlouho jsem ho nezkoušel, před hodně měsíci sem si v něm udělal takovou hodně easy hru. A můžu říct, vítek sem měl na Elm bambilion, proto sem ho v minulých diskuzích označoval za hračku. Kupříkladu mi tam scházeli eventy na klávesnici s vetší granularitou (myslím že keyup, už nevím, možná že už v STD lib je) takže sem si je musel dohackovat pomocí JS FFI. Bohužel jsem si ten svůj seznam kritiky smazal, takže nepomůžu. Absence typových tříd mi ani nevadila, nepochybně ale jen proto že jsem psal fakt hodně jednoduchou appku.
Co je (bylo?) tragické byla absence oficiální podpory node.js. A GUI blbinek v STD lib které znemožněj něco podobného v budoucnosti.
Multithreading je (byl?) kompletně ignorován. Sice workery jsou dost tvrdě nepoužitelný pro FP (nemaj sdílení paměti), pro FPR ne protože reaktivní uzly paralelně běžet bez sdílení paměti mohou. Sice by se musel při startu ELM runtime celej poslat do workeru, ale to by nebylo tak strašný když by těch workerů nebylo moc a existovali by po celou dobu běhu. A ELM runtime není moc velkej.
-
Nevím jak je na tom Elm teď, hodně dlouho jsem ho nezkoušel
Co jsem tak koukal kolem a kolem, vypadá to, že jde rychle dopředu, možná, že už leccos neplatí...
Kupříkladu mi tam scházeli eventy na klávesnici s vetší granularitou [...]Co je (bylo?) tragické byla absence oficiální podpory node.js. A GUI blbinek v STD lib které znemožněj něco podobného v budoucnosti.
To mě zrovna vůbec netrápí. Můj typickej use-case je tabulka nějakých položek, u každé je několik tlačítek (smaž, zobraz detaily,...) a přes WS přichází nové položky, které je do tabulky potřeba doplnit.
Takže potřebuju, aby FE uměl vzít data, vykreslit z nich tabulku, umět na stisknutí tlačítka poslat na BE přes WS událost ve stylu ["delete",ID], BE v DB smaže položku a zpátky pošle něco ve stylu ["remove",ID] a FE ten patřičný řádek z tabulky odstraní. Plus samozřejmě taková ta klasika jako uspořádání tabulky podle sloupce, na který se klikne apod. Technicky žádné extra špeky. Pokud by se to dalo napsat obecně, jako generická logika, které by se jenom předhodila definice struktury dat a seznam událostí, co to má umět, a všechny tabulky by byly obsluhovaný jedním kódem, bylo by to úplně ideální.
Taky mám pár trochu složitějších vizualizací v D3, ale ty můžu případně nechat v JS, to mi tolik žíly netrhá.
-
Hodně se probírá absence (haskellovských) tříd.
To může být jeden z problémů. Dále tam chybí třeba rozšiřitelný pattern matching nebo automatické generování kódu (například parsování hodnot z JSONu nebo porovnávání hodnot si budete muset pro každý typ napsat ručně (http://stackoverflow.com/questions/32575003/elm-how-to-decode-data-from-json-api)).
Často mi také chybí polymorfní varianty z OCamlu - zejména, když systém pracuje s mnoha událostmi a různé jeho části zpracovávají různé podmnožiny událostí (ve Scale jsme k tomu používali Coproduct z knihovny shapeless, nicméně komfortem je to daleko za OCamlem).
BTW při výběru jazyka (a knihoven) doporučuji dát pozor na rychlost kompilace.
-
Dále tam chybí třeba rozšiřitelný pattern matching
Co si pod tím mám představit?
nebo automatické generování kódu (například parsování hodnot z JSONu nebo porovnávání hodnot si budete muset pro každý typ napsat ručně (http://stackoverflow.com/questions/32575003/elm-how-to-decode-data-from-json-api)).
Parsování JSONu jsem už zkoušel (kvůli těm WS zprávám) a je to pracné. Už jsem o tom psal výš. Zas ale se to dá docela hezky parametrizovat a navíc to člověka donutí k pečlivosti (z BE prostě musím poslat správně strukturovaný JSON). Je to takové pro a proti, to je přesně ten důvod, proč nad tím dumám :)
Utěšuju se tím, že se mi tam ty zprávy budou asi docela opakovat, takže nějaká znovupoužitelnost by se tam mohla vyklubat...
Často mi také chybí polymorfní varianty z OCamlu - zejména, když systém pracuje s mnoha událostmi a různé jeho části zpracovávají různé podmnožiny událostí (ve Scale jsme k tomu používali Coproduct z knihovny shapeless, nicméně komfortem je to daleko za OCamlem).
BTW při výběru jazyka (a knihoven) doporučuji dát pozor na rychlost kompilace.
OCaml neznám skoro vůbec a Scalu málo, takže závažnost tohodle taky neumím posoudit. Pokud správně tuším problém, asi na to člověk musí jít v Elmu dost "ručně" pomocí klasických "union types" (tak tomu říkají v Elmu, teď si nevybavím, jestli to má nějaký spešl název v Haskellu - prostě klasické "Result a = Err | Ok a"). Akorát takhle ošperkovat pak člověk musí všechny ty podčásti, se kterými bude chtít zvlášť pracovat a to je pracné, tomu rozumím.
Taky jsem moc nepochopil, proč se v Elmu nemůže stejně jmenovat typový a hodnotový konstruktor. Autor asi chtěl předejít zmatení začátečníků, ale přijde mi to trochu nepraktické (zbytečně nové identifikátory).
-
Dále tam chybí třeba rozšiřitelný pattern matching
Co si pod tím mám představit?
Můžete si definovat vlastní vzory pro pattern matching. Například pro čísla si v F# (viz active patterns (https://msdn.microsoft.com/en-us/library/dd233248.aspx)) můžete definovat vzor
let (|Even|Odd|) input = if input % 2 = 0 then Even else Odd
a pak psát (match ... with je jako case ... of):
match input with
| Even -> printfn "%d is even" input
| Odd -> printfn "%d is odd" input
V praxi to lze použít třeba pro parsování (https://github.com/tpetricek/FSharp.Formatting/blob/master/src/FSharp.Markdown/MarkdownParser.fs). Scala má něco podobného a říká se tomu extraktory.
Parsování JSONu jsem už zkoušel (kvůli těm WS zprávám) a je to pracné. Už jsem o tom psal výš. Zas ale se to dá docela hezky parametrizovat a navíc to člověka donutí k pečlivosti (z BE prostě musím poslat správně strukturovaný JSON). Je to takové pro a proti, to je přesně ten důvod, proč nad tím dumám :)
Ve Scale s knihovnou circe (https://github.com/travisbrown/circe) stačí deklarovat case classu (záznam) a pak napsat jen decode[Foo], kde Foo je název deklarované case classy. Pokud není k dispozici dekodér pro Foo, tak se pomocí implicitního makra vygeneruje automaticky.
Pokud správně tuším problém, asi na to člověk musí jít v Elmu dost "ručně" pomocí klasických "union types" (tak tomu říkají v Elmu, teď si nevybavím, jestli to má nějaký spešl název v Haskellu - prostě klasické "Result a = Err | Ok a").
Ano, to lze v OCamlu také (a říká se tomu varianty). Předpokládejme, že dále máme Barva = Zelena | Cervena | Modra. Polymorfní varianty dovolují napsat funkci, jenž zpracovává pouze zprávy Ok a | Zelena | Cervena (a když do ní zkusíte dát Modra nebo Err nebo něco jiného, tak to kompilátor označí za chybu). V OCamlu je rozdíl v syntaxi - názvy polymorfních variant začínají zpětnou uvozovkou. Další rozdíl je, že se nemusí dopředu deklarovat.
Oproti Coproductu z shapelessu to má o dost lepší typovou inferenci, nezpomaluje to kompilátor a podporuje to i rekurzivní typy.
-
Můžete si definovat vlastní vzory pro pattern matching.
Aha, takže něco jako guards v Erlangu, ale pojmenované a znovupoužitelné. To je dobrý, to se mi líbí.
Pro zajímavost: v tom patternu můžu použít libovolnou fci? V Erlangu je to omezené jenom na některé jednoduché fce, aby se v rámci matchování neděla nějaká zvěrstva :)
Ve Scale s knihovnou circe (https://github.com/travisbrown/circe) stačí deklarovat case classu (záznam) a pak napsat jen decode[Foo], kde Foo je název deklarované case classy. Pokud není k dispozici dekodér pro Foo, tak se pomocí implicitního makra vygeneruje automaticky.
Hmm, to je taky dobrý!
Polymorfní varianty dovolují napsat funkci, jenž zpracovává pouze zprávy Ok a | Zelena | Cervena (a když do ní zkusíte dát Modra nebo Err nebo něco jiného, tak to kompilátor označí za chybu).
Aha, takže můžu vybrat jenom některé varianty z různých typů? To je teda dost divočina ;) A jaký typ se z toho pak inferuje, když je to částečně Result a částečně Color? Vytvoří automaticky při kompilaci nějaký interní typ "XXXX a = Ok a | Zelena | Cervena"?
-
Aha, takže něco jako guards v Erlangu, ale pojmenované a znovupoužitelné. To je dobrý, to se mi líbí.
Jak nad tím teď tak uvažuju, v Elixiru by se to dalo udělat pomocí makra. Ale bylo by to asi trochu syntakticky kostrbatější a byl by tam potenciál pro špatně čitelný chyby.
-
Extraktory ve Scale jsou skvela vec, pattern matching je diky nim hodne silny. Jde to treba pouzit s regularnimi vyrazy:
val Pattern = "^(.*)@(.*)$".r
"my-email@seznam.cz" match {
case Pattern(name, domain) => println(s"Got a match! name = $name and domain = $domain")
case _ => println("No match found.")
}
Vystup:
Got a match! name = my-email and domain = seznam.cz
Online si to muzete zkusit tamhle -> http://ideone.com/Yd84oe.
-
Můžete si definovat vlastní vzory pro pattern matching.
Aha, takže něco jako guards v Erlangu, ale pojmenované a znovupoužitelné. To je dobrý, to se mi líbí.
Myslím, že to není úplně jako guards - F# má také guards a také pomocí when. Rozdíl je v tom, že active patterns mohou mít i výstup. Například
/// Matches when a string starts with a sub-string wrapped using the
/// opening and closing sub-string specified in the parameter.
/// For example "[aa]bc" is wrapped in [ and ] pair. Returns the wrapped
/// text together with the rest.
let (|StartsWithWrapped|_|) (starts:string) (ends:string) (text:string) =
if text.StartsWith(starts) then
let id = text.IndexOf(ends, starts.Length)
if id >= 0 then
let wrapped = text.Substring(starts.Length, id - starts.Length)
let rest = text.Substring(id + ends.Length, text.Length - id - ends.Length)
Some(wrapped, rest)
else None
else None
Výstup je dvojice (wrapped, rest). Ukázka použití
match "[Zkousime active](pattern)s" with
| StartsWithWrapped "[" "]" (vHranatych, StartsWithWrapped "(" ")" (vKulatych, zbytek)) ->
printfn "v hranatych '%s', v kulatych '%s', zbytek '%s'" vHranatych vKulatych zbytek
| _ -> printfn "nic"
vypíše: v hranatych 'Zkousime active', v kulatych 'pattern', zbytek 's'
Pro zajímavost: v tom patternu můžu použít libovolnou fci? V Erlangu je to omezené jenom na některé jednoduché fce, aby se v rámci matchování neděla nějaká zvěrstva :)
Uvnitř active patternů i guardů jde používat libovolné funkce.
Polymorfní varianty dovolují napsat funkci, jenž zpracovává pouze zprávy Ok a | Zelena | Cervena (a když do ní zkusíte dát Modra nebo Err nebo něco jiného, tak to kompilátor označí za chybu).
Aha, takže můžu vybrat jenom některé varianty z různých typů? To je teda dost divočina ;) A jaký typ se z toho pak inferuje, když je to částečně Result a částečně Color?
Bude se inferovat typ [< `Res of 'a | `Zelena | `Cervena]. Znak < říká, že funkce dovede zpracovat tyto 3 varianty nebo méně (do funkce lze dát např. i hodnotu typu [`Res of 'a | `Cervena]). Viz manuál OCamlu (http://caml.inria.fr/pub/docs/manual-ocaml-4.02/lablexamples.html#sec46).
-
Jojo, v Haskellu na to jsou extensiony ViewPattern a PatternSynonyms. PatternSynonyms mají navíc tu vlastnost, že mohou být dvojsměrné (tzn. fungovat jako konstruktor). To použití zas tak časté není - ale v těch pár případech, kdy jsem to použil, to docela zvýšilo čitelnost.
-
Jen pro zajímavost (proč mám rád haskell ;) ):
tsplit :: Char -> T.Text -> Maybe (T.Text, T.Text)
tsplit chr txt
| T.null end = Nothing
| otherwise = Just (start, T.drop 1 end)
where
(start, end) = T.break (== chr) txt
wrapped :: Char -> Char -> T.Text -> Maybe (T.Text, T.Text)
wrapped dstart dend txt
| Just ("", cont') <- tsplit dstart txt,
Just (inside, rest) <- tsplit dend cont' = Just (inside, rest)
| otherwise = Nothing
pattern Hranate txt rest <- (wrapped '[' ']' -> Just (txt, rest))
pattern Kulate txt rest <- (wrapped '(' ')' -> Just (txt, rest))
match :: T.Text -> T.Text
match (Hranate vHranatych (Kulate vKulatych zbytek)) =
"v hranatych " <> vHranatych <> ", v kulatych " <> vKulatych <> ", zbytek " <> zbytek
match _ = "nic"
main = print $ match "[Zkousime active](pattern)s"
-
Jen pro zajímavost (proč mám rád haskell ;) ):
Drobný rozdíl je, že kód v F# dovoluje, aby „závorka“ byla libovolný řetězec - zatímco u kódu v Haskellu to musí být jeden znak.
-
Drobný rozdíl je, že kód v F# dovoluje, aby „závorka“ byla libovolný řetězec - zatímco u kódu v Haskellu to musí být jeden znak.
Proč mám rád Haskell^2 včetně ukázky obousměrných Pattern Synonyms:
tsplit :: T.Text -> T.Text -> Maybe (T.Text, T.Text)
tsplit chr txt
| T.null end = Nothing
| otherwise = Just (start, T.drop (T.length chr) end)
where
(start, end) = T.breakOn chr txt
wrapped :: T.Text -> T.Text -> T.Text -> Maybe (T.Text, T.Text)
wrapped dstart dend txt
| Just ("", cont') <- tsplit dstart txt = tsplit dend cont'
| otherwise = Nothing
pattern Hranate txt rest <- (wrapped "[" "]" -> Just (txt, rest))
where Hranate txt rest = "[" <> txt <> "]" <> rest
pattern Kulate txt rest <- (wrapped "(" ")" -> Just (txt, rest))
where Kulate txt rest = "(" <> txt <> ")" <> rest
match :: T.Text -> T.Text
match (Hranate vHranatych (Kulate vKulatych zbytek)) =
"v hranatych " <> vHranatych <> ", v kulatych " <> vKulatych <> ", zbytek " <> zbytek
match _ = "nic"
main = do
print $ match "[Zkousime active](pattern)s"
print $ Hranate "Zkousime active" (Kulate "pattern" "s")
-
Myslím, že to není úplně jako guards - F# má také guards a také pomocí when. Rozdíl je v tom, že active patterns mohou mít i výstup. Například
Aha, chápu. No tak to už je úplná divočina :) Pěkně!
-
For record:
Tak jsem se trochu víc ponořil do Elmu, ze začátku to bylo trochu náročnější, než jsem si občerstvil haskellovský styl a pochopil, jak to vlastně mají celé vymyšlené, ale jakmile se to zlomilo, můžu říct, že jsem fakt nadšenej. Pro programátora je to jednoduché, přímočaré a jakmile jsem si napsal kostru (připojení na websockety, správné předávání zpráv komponentám a jeden widget), jsem schopnej nový widget vytvořit během chviličky, prakticky jenom přejmenováním a úpravou modelu a view.
Hodně se mi líbí, jak mají vymyšlenou komunikaci (signály, mailboxy, porty) - FRP je fajn, cítím se v něm skoro jako v Erlangu ;) Líbí se mi možnost celkem bezproblémové komunikace s javascriptem (přes port, takže čistě) a mile mě překvapilo, že existuje nečistá funkce Debug.log, kterou se dají kdekoli v případě potřeby dělat ladící výpisy. Vypadá to, že autor je pragmatik a ne pure-fašista, což kvituju ;)
Musím říct, že ve staticky typovaném frontendu se po těch letech s JS cítím jak Alenka v říši <div>ů - člověk přidá nějakou událost na tlačítku a kompilátor ho upozorní, že tuhle akci ještě v update funkci nezpracoval. Žádný chyby po nasazení, funguje pověstné haskellovské "pokud se to zkompiluje, tak to funguje" :)
Takže, pánové, díky moc za cennou konzultaci, rady a tipy. Zdá se, že habemus framework! ;)
-
F# je moj oblubeny jazyk ale na dynamicke zalezitosti sa vôbec nehodi. F# ma silne typovanie a svet js je preane opacny. Existuje dokonca transpiler F# do js vola sa dunscript ale ako som uz hovoril f# si s js kniznicami nerozumie.
Clojure nepoznam ale nieco som zacul o frameworku ohm clojuristi jo dost chvalia.
Pre mna osobne bol najlepsou volbou cisty js neni to zas moc funkcionalne ale da sa v tom uz celkom obstojne programovat. Babel je dnes uz nevyhnutnost a k tomu webpack. react je perfektna kniznica mozem len odporucit. A k tomu immutable.js na pracu s kolekciami. V reacte je totiz dolezite aby state bol immutable co kolekcie jska nesplnaju.
-
Oprava Funscript.
Este doplnim ze preco vlastne nie f# na klienta. Na klientovi sa vsetko tvori on the fly a f# sa naopak mohutne spolieha na typy compile time. f# nema ani podporu duck typingu da sa tam sice doprogramovat pretazenim operatorov ? A ?<- Ale neni to ono. Nieco sa obchadza pomocou type providerov ale stale to nema na dynamicke typy.
-
F# je moj oblubeny jazyk ale na dynamicke zalezitosti sa vôbec nehodi. F# ma silne typovanie a svet js je preane opacny.
Úplně nerozumim tomu, proč by frontend měl být "dynamičtější" než zbytek aplikace. Od backendu dostává nějaká data, ta nějak zobrazuje a reaguje na události od uživatele. To není nic, na co by se statické typování nedalo použít, všechno je známo v době překladu.
Integrace s JS je problém, to je jasné. Elm na to jde pomocí portů, což mi zatím připadá dost elegantní přístup - port funguje tak, že má nějaký JS kód, který kooperuje s tím jiným JS, ale vrací přesně daný typ a do zbytku aplikace se to promítá jako stream událostí jednoho typu, takže se s tím pak už dá pracovat silně typovaně.
-
Co ctu, tak FE vyvojari velkych aplikaci casto pokukuji po poradne typovanych i statickych jazycich. Proto treba dvojkovy Angular je primarne TypeScript vec.
S propojenim s okolnim JS pribude vetsinou krok navic, ale nebyva to nejaky zavratny problem. Zmineny TypeScript pouziva type definition (http://definitelytyped.org/tsd/) a takova ScalaJS facades (http://www.scala-js.org/libraries/facades.html). Oboje funguje jako tenka vrstva pro "pridani" typů urcite JS knihovne. Zni to v podstate stejne, jako ty porty popisovane Mirkem.
-
Oprava Funscript.
FunScript je o dost horší než WebSharper. Řadu konstrukcí z F# jako například třídy nebo rozhraní překládá FunScript špatně (programy přeložené do JS pak nefungují).
f# sa naopak mohutne spolieha na typy compile time.
Z mé zkušenosti (používám React) s tím žádný problém není - spíše naopak - díky tomu se jde hladce vyznat i ve složitějších aplikacích.