Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »Richard Stallman přednáší ve středu 7. května od 16:30 na Technické univerzitě v Liberci o vlivu technologií na svobodu. Přednáška je určená jak odborné tak laické veřejnosti.
Jean-Baptiste Mardelle se v příspěvku na blogu rozepsal o novinkám v nejnovější verzi 25.04.0 editoru videa Kdenlive (Wikipedie). Ke stažení také na Flathubu.
TmuxAI (GitHub) je AI asistent pro práci v terminálu. Vyžaduje účet na OpenRouter.
Byla vydána nová verze R14.1.4 desktopového prostředí Trinity Desktop Environment (TDE, fork KDE 3.5, Wikipedie). Přehled novinek i s náhledy v poznámkách k vydání. Podrobný přehled v Changelogu.
Bylo vydáno OpenBSD 7.7. Opět bez písničky.
V Tiraně proběhl letošní Linux App Summit (LAS) (Mastodon). Zatím nesestříhané videozáznamy přednášek jsou k dispozici na YouTube.
Navíc, aby se mohl spustit druhý getJSON(), musí být známa hodnota cfg a to nastane až skončí první getJSON().Takhle sekvenční je to bohužel vždycky (i kdyby se
cfg
vůbec nepoužila). Napíšete-li například
async function f() { await readA(); await readB(); }tak se stejně napřed spustí
readA
a teprve poté, co úspěšně (bez vyhození výjimky) skončí, se spustí readB
. Cílem je, aby se to chovalo podobně jako klasický synchronní program, což zde například znamená, že readB
se nespustí, pokud readA
neskončí, a to je obecně těžké zjistit (halting problém).
Ještě zmíním, že i zásobník se v některých implementacích tváří jako u synchronního programu, a to i přesto, že výpočet ve skutečnosti skáče po různých vláknech.
To ale celkově vypadá dost samoúčelně a potom jakákoliv syntaxe vypadá zbytečně.I tak mi to přijde lepší než
function f() { readA() .then(function() { readB(); }); }
objektový jazyk s třídami, kde standardní viditelnost členských proměnných je public a standardní viditelnost metod je private, ač bychom to chtěli naopakPokud vubec mit defaultni viditelnost, tak nejlogictejsi mi prijde private pro vsechno.
Neni mi z toho jasny proc by se teda ten await nemel pouzivat.Vyznačení, že se volá asynchronní akce a funkce bude pravděpodobně přerušena, nepovažuji za tak důležité, aby mělo speciální syntax. Naopak v kódu, který dělá mnoho asynchronních volání, to snižuje přehlednost.
Nebo co kdyz volani neprobiha v event loop vlakne?V C#, když není k dispozici event loop vlákno (přesněji, když je
SynchronizationContext.Current == null
), tak se kód spouští na ThreadPoolu – ten je k dispozici vždy.
Co kdyz tu funkci chci volat normalne?Co myslíte volat normálně? Takové funkce typicky vrací objekt, který nějak reprezentuje asynchronní výpočet – např.
Promise
, Future
, Task
nebo Awaitable
– tj. nějak se musíte dostat k návratové hodnotě, která je (možná) v tom objektu.
Argument ze to vyznaci IDE neberu, tohle by nemelo byt zaivsle na nejakych featurach IDE. Ne vzdy clovek cte kod v IDE, ne vsichni pouzivaji IDE, atd.Díky, to je dobrá poznámka, argument jsem odstranil.
Threads are evil. Avoid them.Vlakna jako takova zlo nejsou. Za vetsinu spatneho muze mutable state.
Kazda komponenta je (zjednodusene) pure funkce, ktera dostane stav a vrati popis UI (na webu HTML).Tohle ale není úplně praktické, často se hodí, když i jednotlivé komponenty mají vnitřní stav. Například stav scrollbaru nebo pozice kurzoru v textovém poli nebo stav nějaké animace – tyhle věci často nechcete mít v tom "hlavním" velkém stavu.
props
, ten dostane zvnejsku od rodicovske komponenty a state
, ktery si nastavuje sama v reakci na ruzne eventy.
A při každé změně znova vygenerovat UI? Bleee, zkus tam udělat něco většího a bude se to sekat jak svině. Pro web dobrý, to jo. Ale jinak fakt ne.To je bohužel pravda, v některých komponentách pak musíte implementovat
shouldComponentUpdate
, který zamezí zbytečným aktualizacím komponenty.
funkcionalni paradigma nabízí vynikající možnost paralelizaceCo, když je úloha taková, že každý krok je závislý na výsledku předchozího kroku? V některých speciálních případech sice můžete zkusit spekulativní paralelizaci – například lexikální analýza – ale to jsou spíše výjimky.
To je bohužel v dnešní době častý problém, výkon potřebný pro vytvoření paralelní operace je moc velký (dáno architekturou CPU kterou používáme). Takže v dnešní době funkcionální paradigma ani nemůže pořádně ukazovat svou sílu.
To se o Prologu říká taky :)
Třeba OpenPower plaforma s FPGA kartami zapojenými do IOMMU to změní.
Imperativni kód se špatně paralelizuje. To je jeho hlavní nevýhoda.Hm, ne vzdy a navic kolik % kodu se paralelizuje? Jinak sdileny mutable state mi obcas prijde jako nejcistssi zpusob jak neco naprogramovat. Funkcionalni kod ma urcite vyhody, to nepopiram, moje pointa je, ze ne ve vsech situacich je to ten nejlepsi pristup.
A při každé změně znova vygenerovat UI? Bleee, zkus tam udělat něco většího a bude se to sekat jak svině. Pro web dobrý, to jo. Ale jinak fakt ne.Taky moje prvni reakce byla, ze to musi byt strasne pomaly. Ale rychlost je naopak jedna z hlavnich prednosti Reactu, alespon ve srovnani s konkurenci (Angular, Ember). Pokud jsou vsechny komponenty opravdu pure funkce a vsechen stav je immutable, tak to lze udelat tak, ze se pregeneruji jenom komponenty ktere se zmenily, stavi porovnat minuly stav s novym. Myslim ze pak by se i u slozitejsiho UI vetsina updatu vesla do 1 ms a urcite by nemel byt problem dosahnout 60 FPS.
a nebo aspoň uniqueness typy jako má CleanV čem je to lepší než IO monáda?
main :: [Message] -> [Message]
main msg = ...
Kde listy [Message] jsou nekonečné díky lenosti. A program přijímá skrz zprávy všechny změny z okolního světa, a sám odpovídá skrz nekonečný list zpráv runtime systému. Vlastně tak jako GC je nutno pro čistě funkcionální jazyky z toho důvodu že alokace paměti není referenčně transparentní (a persistentní datové struktury bez GC taky nejdou). Tak je třeba i IO přesunout do runtime systému, s vyšší úrovní abstrakce se prostě nepotřebné věci zanedbávají, v tomto případě ruční provádění IO.
Uniquiness typování ale je skutečně referenčně transparentníNerozumím, proč IO monáda není skutečně referenčně transparentní.
Uniquiness typování ale je skutečně referenčně transparentní, takže de klasicky využít s pure paralelismem.Máte na mysli fakt, že IO monáda vynucuje lineární uspořádání akcí? Uspořádání akcí, sice jen částečné, vynucuje i uniqueness typování, ne?
Bohužel ho má jen zanedbaný Clean.AFAIK má to ještě Mercury. Podobné chování pravděpodobně půjde zajistit i v jazycích s lineárními typy jako např. ATS.
Vlastně tak jako GC je nutno pro čistě funkcionální jazyky z toho důvodu že alokace paměti není referenčně transparentníI v IO monádě nebo s uniqueness typováním můžete ručně alokovat i dealokovat paměť. Referenčně transparentní to není například v případě, kdy můžete pozorovat adresy objektů, ale s dostatečnými omezeními to může být referenčně transparentní.
e
je referenčně transparentní, pokud mohu v každém programu nahradit libovolné výskyty e
hodnotou e
a chování programu se nezmění.
No, a kdyby to byla referenčně transparentní funkce, nevadilo by ji jednou vyhodnotit a pak jen dávat její výsledek žejo? Hezký, tvůj program by se ale choval trošku jinak než jak bys očekával. Ono, při každém vyhodnocení tadle funkce vrací něco jinéhoPrávě, že ne. Ta funkce vrací při každém vyhodnocení to samé, a to hodnotu typu
IO [Int]
.
IO [Int]
můžeme chápat jako popis akcí, co se mají stát. A sám o sobě je takový popis referenčně transparentní – popis žádné vedlejší efekty nedělá.
Ale tu zprávu naneštěstí vyhodnotí monadické operátory >> a >>=.Tyto operátory nic nevyhodnocují. Můžeme si představit, že to vyhodnocuje jakýsi interpretr, k němuž nemáte přístup, používáte-li Safe Haskell, nebo máte přístup přes
unsafePerformIO
apod., pokud nepoužíváte Safe Haskell.
Něco ji musí rozhoupat k akce ... a runtime to není, je to nejbližší operátor >> nebo >>=Můžete si zkusit, že
>>
nic takového nedělá, například vyhodnocení výrazu
(putStrLn "A" >> putStrLn "B") `seq` 4nezpůsobí žádný vedlejší efekt, a to i přesto, že se
putStrLn "A" >> putStrLn "B"
vyhodnocuje do slabé hlavní normální formy.
(putStrLn "A" >> putStrLn "B") `seq` 4
vrátí 4. Funkce seq má typ (a -> b -> b) což znamená že když dáme na první místo IO objekt a na druhý cokoli jiného krom jiného IO objektu, vznikne nám strašná chyba. IO objekt unikne do čistého kódu a bude vyhodnocen!! V čistém kódu platí úplně jiná pravidla, funkce se volají v jiném pořadí než byly napsaný, pokud se volají vůbec, vyhodnocují se taky všelijak, někdy víckrát, někdy jen jednou. Prostě kdyby pomocí funkce seq bylo možno vyhodnotit IO objekt a pak v klídku pokračovat v čistém kódu, nic by nefungovalo tak jak má. Proto je tam zadrátovaná ochrana, a IO objekt se prostě ignoruje a zahodí. Pro "vyhodnocení" IO objektů slouží >> a >>=.
Ono, ve skutečnosti, operátory >> a >>= nic nevyhodnocují, je to ale pěkné a snadné si to představovat. Lépe se poté akceptuje víra že IO monáda je Pure. IO monáda je vlastně jen tuple s obsaženým fake členem, který zajišťuje, aby kompiler nepřerovnal ňák blbě volání funkcí vracejících IO (jinak než jsme napsali). Operátor >> pak jen zřetězuje nečistá volání a >>= napojuje na nečistý kód čistý kód. Toť vše, žádné interpretry v pozadí neexistují, a jejich představování je skutečně záležitost víry. Stejně jako čistota IO. Sem se teď koukal na stránky Haskellu, a maj je nový ... když sem uviděl to tvrzení pod nadpisem "Purely functional", chtělo se mi rozplakat a poslat jim tam ukázku "čistého" Haskellu kterou sem právě dopsal. Prej že všechny výrazy nemůžou měnit proměnný. A co je kurva IORef, nebo TVar, nebo Chan a nebo další ze zástupu měnitelných datových struktur !!! Takový ty keci o čistotě sou lži, ve chvíli kdy mám funkci která vrací svou návratovou hodnotou hovno ale Chanellem (poslaným v argumentu!!) šupá data do mateřského vlákna, je mi blivno, to nemůže zdraví člověk nazvat PURE!
Ale na to mi evangelista odpoví, "Ale IORef se přece nemění ne? :) Furt je to ta samá reference :) Tak vidíš že sem měl pravdu ... je to čistý :)" ... Jo, svůj obsah ale mění ... a vo to de.
Takový ty keci o čistotě sou lži, ve chvíli kdy mám funkci která vrací svou návratovou hodnotou hovno ale Chanellem (poslaným v argumentu!!) šupá data do mateřského vlákna, je mi blivno, to nemůže zdraví člověk nazvat PURE!Definice: Funkce
f
je pure, pokud je výraz "f a1
… an
" referenčně transparentní pro libovolné referenčně transparentní a1
… an
.
Podle této definice, jsou funkce v Haskellu pure. Nevidím tedy žádný problém.
Například i funkce
function f() { var u = 10; u += 10; return u; }je pure a nevadí ani to, že uvnitř mění proměnnou
u
.
Ono, ve skutečnosti, operátory >> a >>= nic nevyhodnocují, je to ale pěkné a snadné si to představovat.Podle mě to právě není dobrá a ani přesná představa (viz ten můj příklad). Lepší a přesnější je právě ta představa, kterou nabízím já, a to IO jako volná monáda + interpretr. To, že to GHC implementuje jinak, není příliš podstatné, když se to chová stejně. Ve scalaz se to například implementuje skutečně jako volná monáda + interpretr – viz
Task
ze scalaz.
Jakákoli funkce která tyto podmínky nesplňuje není pure. Funkce vracející IO monádu tyto podmínky nesplňují, takže nejsou čisté. Hotovo.Splňují, už jsme to tu řešili. Např.
putStrLn
bere řetězec a vrací IO ()
, to je vše, žádný side effect nedělá, je to tedy čistá funkce.
(Problém může nastat jedině s funkcemi, které uvnitř používají unsafePerformIO
apod. – např. readFile
.)
IO monáda může komunikovat se světem, takže není zvenku čistá.Vy nemáte žádný
runIO
, který by ji spustil, takže pro vás je čistá.
Pokud jste například v jazyce s eager vyhodnocováním, tak i následující funkce je čistá
type foo let f (x : foo) = printf "foo"Důvodem je, že ji nikdy nemůžete zavolat, protože nejde zkonstruovat hodnotu typu
foo
. (V Haskellu má každý typ hodnotu bottom, takže tam bych tu funkci ještě musel udělat striktní v 1. argumentu.)
Poznámka pro neznalé: Hlavní výhoda funkcionálního paradigmatu je ta, že umožňuje teoreticky implicitní paralelismus bez nutnosti paměť zamykat. Protože data se nikdy v referenčně transparentním jazyku nemění.Bezpečný implicitní paralelismus bez zamykání umožňují i jazyky, kde se data mění. Podívejte se třeba na jazyk ParaSail. Cituji ze stránek jazyka:
Every ParaSail expression is defined to have parallel evaluation semantics. That is, given a ParaSail expression like F(X) + G(Y), the language rules ensure that it is safe to evaluate F(X) and G(Y) in parallel. The compiler makes the decision based on complexity or other criteria whether a given computation should be created as a potentially parallel activity. An underlying scheduler then maps these potentially parallel activities to particular processing resources, by default using a work-stealing approach, which provides load balancing across processors while also providing good locality of reference and minimal cache contention.
Kompiler prostě sám přijde na to, co chce zamykat a co ne podle toho jak si to přerovná.Pokud tomu dobře rozumím, tak se zamykají pouze objekty označené jako konkurentní (pomocí klíčového slova
concurrent
), které obsahují metody označené pomocí locked
nebo queued
– to jsou také místa, kde je paralelismus nedeterministický.
Ostatní věci se nezamykají a paralelismus je deterministický (nebo žádný, pokud si kompilátor myslí, že to nejde bezpečně paralelizovat). Pomocí ||
jde požádat o explicitní paralelismus.
Například výraz
X := 3 || X := 5se nepřeloží.
Pokud máš objekt který mění stav, a chceš ho číst, či ho modifikovat, vždy ho musíš zamknout, jinak se ti taky může (nemusí, ale je to ruská ruleta) změnit pod rukama.Například u indexovatelných objektů je schopen rozpoznat, zda přistupujete k disjunktním částem, takže žádné zamykání není třeba. Tohle je vidět na paralelním Quicksortu (In-Place version of Quicksort – slajd 59).
Čistě funkionalni jazyk ale nepotřebuje žádné lockovani. To je jeho síla.Tohle pak ještě umí synchronní jazyky jako např. Esterel nebo ReactiveML. Nicméně aplikace těchto jazyků je poměrně specifická.
Jak je to vlastně u nich vnitřně řešený?Třeba ReactiveML se kompiluje do OCamlu a OCaml paralelismus nepodporuje (může běžet nejvýše 1 vlákno). Všechno se tedy vykonává sekvenčně a implementace může provádět a provádí mutaci dat.
Hlavní výhoda funkcionálního paradigmatuO tom mam trochu pochybnosti, treba klasicky clanek "Why functional programming matters" spis mluvi o vetsi modularnosti. A i jine prezentace co jsem videl si predevsim pochvaluji typovy system a kontrolu chyb.
Místo jen přebírání cizích myšlenek doporučuji i myslet, popřípadě přečíst těch cizích myšlenek hodněMozna by pomohlo, kdyby ses vic rozepsal (jaky presne jsi mel problem a jak to treba FRP resi) nez si jen stezoval na to, jak jsou vsichni hlupaci a nechapou FP. Ono bys totiz pri tom vysvetlovani treba prisel na to, ze tvuj oblibeny pristup ma uplne stejne "mouchy" jako ty ostatni, akorat je to schovane nekde jinde.
Haskell nemá žádné FRP knihovny realizující IO.Hm, kdyz nad tim tak premyslim, neni mi moc jasne, co by jsi chtel paralelizovat na I/O. Bud potrebujes zapisovat na stejny soubor/zarizeni, a pak se nejake contention nevyhnes. Nebo budes zapisovat na ruzna zarizeni a pak nemusis nic zamykat.
V případě málo jader je plýtvání lock free přístup, v případě velkého množství jader je to ale opačně, protože lockovani je pak neskutečně drahé.Nebudes v pripade vice jader take zahazovat vice vypoctu, a nula od nuly pojde?
Normálně se tam žádné výpočty nezahazují. Proč by měli?Zahazují se, když např. začnete jeden thunk vyhodnocovat paralelně ve více vláknech.
tvuj oblibeny pristup ma uplne stejne "mouchy" jako ty ostatni, akorat je to schovane nekde jinde.Presne tak. Dokud neuvidim ze to lide pouzivaji a jsou s tim produktivnejsi, tak tomu neuverim. U FP evangelistu jde casto o to, ze se na to nedivaji pragmaticky, ale ideologicky / pocitove, proste se jim libi ta myslenka, prijde jim to krasne ciste. Pripomina mi to esej o Lispu od Paula Grahama. Motivovala me k tomu, abych se jeden Lisp naucil, ale casem jsem dosel k tomu, ze ta esej je v podstate bullshit.
Taky moje prvni reakce byla, ze to musi byt strasne pomaly. Ale rychlost je naopak jedna z hlavnich prednosti Reactu, alespon ve srovnani s konkurenci (Angular, Ember).Je otázkou, jak to srovnání provádíte. Když máte nějakou zanořenou komponentu, tak při její aktualizaci v Reactu generujete a porovnáváte virtuální DOM minimálně pro všechny její předky (potřebujete přegenerovat uzly na cestě z kořene virtuálního domu až do aktualizované komponenty; odbočky z této cesty ne, když vhodně použijete
shouldComponentUpdate
).
Zatímco v Angularu můžete onu komponentu přímo nabindovat na část modelu a změna modelu změní pouze tu komponentu – nijak se to nedotkne jejích předků.
shouldComponentUpdate
a update se provede jenom pri zmene stavu.
A samotne vygenerovani komponenty je pry radove rychlejsi nez zmena DOMu.
Vlakna jako takova zlo nejsou. Za vetsinu spatneho muze mutable state.shared mutable state. There, I fixed it for you. Lokální měnitelný stav je OK.
Proč tedy asynchronní kód nevypadá stejně jako synchronní a proč tam kompilátor nebo interpretr automaticky nedoplní awaity?A jak pozná, že to má udělat? V C# z návratového typu, dejme tomu, ale ostatní zmiňované jazyky jsou dynamicky typované, takže to může udělat buďto vždycky (overhead jako prase), nebo nikdy (a nechat to na programátorovi). Já bych async/await vyčítal spíš to, že nejde rozumně dělat promise pipelining.
ale ostatní zmiňované jazyky jsou dynamicky typované, takže to může udělat buďto vždycky (overhead jako prase)Pozná to za běhu, že se podívá, co funkce vrátila (např. jestli má vrácený objekt určitou metodu). Myslíte, že to je velký overhead?
await
se typicky implementuje jako nějaká syntaktická transformace, takže ano, myslím, že to je velký overhead. Dělat to za běhu by bylo ještě horší.
await
se typicky implementuje jako nějaká syntaktická transformace
Syntaktická transformace je jedna z možností, kterou např. používá C#. VC++ to dělá jinak, používá fibers (viz
Async-Await in C++, část A kind of magic…), a podobně to může dělat virtuální stroj pro dynamicky typovaný jazyk.
Tiskni
Sdílej: