Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
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.
Uplynulo dlhých osem rokov od môjho posledného blogu, odvtedy som tu už len read-only. Až prudko inšpiratívny zápis minulý týždeň ma inšpiroval aby som niečo nové vytvoril. Naposledy ma takto nadchol sadam, vtedy som vytvoril osifont a potom som sa o to roky musel starať.
Poďme ale k veci. Chcel som si štruktúrovaný OS vyskúšať. Papier znesie všetko ale aké je to v praxi? Spravil som jednoduché demo. Začal som postupne pridávať základné programy. Pridal som podporu pre pajpy - štruktúra z jedného programu je vstup druhého. Napríklad uname | filter version. Každý program má v sebe manuál a tak ma napadlo spraviť program "examples" ktorý by vypísal všetky príklady použitia všetkých programov. Man vracia samozrejme štruktúru a tak nebol problém vytiahnuť to a vrátiť všetko v jednom poli. To bol moment kedy som si uvedomil že to nie je až taká blbosť ako som si myslel. To by bola nádhera mať takto celý systém.
Na záver som tam ešte pridal jednoduchý filesystém a textový editor aby sa dalo editovať existujúce programy a pridávať nové. Zdrojové kódy a online demo.
Tiskni
Sdílej:
ls
atd.) blející JSON nebo nějaký formát (počítám, že pro Frantu by bylo potřeba přidat podporu XML isatty
, ale to je na tohle moc omezené...
počítám, že pro Frantu by bylo potřeba přidat podporu XML
XML v tomhle případě ne, dělám na něčem jiném, postaveném na relačním modelu.
Samozřejmě jsem o XML uvažoval, ale u něj je problém jednak ta ukecanost, která data dost nafoukne, a jednak to, že se nedají XML soubory za sebou řetězit jen tak spojením příkazem cat
, nebo nejde připisovat záznamy do stávajícího souboru.
Správa systému je jen jedno z možných použití. Ty příklady se zatím točí většinou kolem fstab
u, protože to je první co jsem udělal, a lidi to znají Ale ta myšlenka je zcela obecná -- proudové zpracování dat -- které se dá použít k čemukoli. Relace (a důležité je, že jich v jednom proudu může být víc) jsou dostatečně univerzální model, aby se jím daly popsat prakticky jakákoli data.
Ale ta myšlenka je zcela obecná -- proudové zpracování dat -- které se dá použít k čemukoliv
Relace (a důležité je, že jich v jednom proudu může být víc) jsou dostatečně univerzální model, aby se jím daly popsat prakticky jakákoli data.Jedna z hlavnich deviz relacniho modelu dat je v tom, ze nediktuje, jak maji byt fyzicka data ulozena a zpracovana. Automaticka volba algoritmu podle konkretniho dotazu a povahy dat je podle me naprosta killer feature. To jsou veci, ktere v tvem pripade kvuli proudovemu zpracovani dat padaji. Dal zustava otevrena otazka, jak moc efektivne lze operace relacni algebry vyjadrit v prostredi s potencialne nekonecnymi proudy (a i s konecnymi to muze byt problem). JOIN vypada jako orisek sam o sobe. Ale treba takova projekce taky neni bez zaludnosti. Pokud se chces drzet relacniho modelu (coz zrejme mas v planu), tak by projekce (v tve terminologii relpipe-tr-cut) nemela pripustit duplicitni radky, tedy mela by se chovat jako "SELECT DISTINCT". To ale nejde dost dobre udelat bez ukladani dat do pameti, coz je trochu v rozporu s ideou proudoveho zpracovani dat.
Proudové zpracování se použije tam, kde to jde a kde to má smysl. Ta omezení a odlišnosti od DBMS tam samozřejmě jsou. DISTINCT se většinou dělat nebude, pokud to uživatel vyloženě nepožaduje, stejně tak UNION bude většinou ALL. Spousta "cut" a "grep" úloh se proudově dělat dá a jde to udělat na jeden zátah záznam po záznamu. Stejně tak lze počítat i některé statistiky. Mám tam i tr-python
(a pak tr-guile
), který umožní jak filtrování libovolně složitou podmínkou, tak změnu dat na úrovni jednotlivých záznamů. V plánu je i změna struktury tzn. relace na výstupu může mít jiný počet a typy atributů než ta vstupní. Měl by tam pak přibýt i režim puštění skriptu na úrovni celých relací nebo celého proudu. Implementace je celkově hodně pomalá, ale to se dá vylepšovat postupně, v první řadě je potřeba hlavně stabilizace toho formátu a API.
V případě úloh, které z principu proudově řešit nelze, tak si nástroj natáhne celý proud do paměti (případně odloží na disk), tam ho zpracuje a pak teprve odešle na výstup. V plánuje např. nástroj, který naplní data ze vstupu do sqlite databáze (v paměti), pustí nad nimi zadané SQL dotazy (takže tam půjde dělat i ty JOINy, DISTINCTy atd.) a výstup (opět relace) bude průběžně odesílat na STDOUT.
Pokud tvoje práce vypadá tak, že máš hromadu dat a tu dlouhodobě nějak obděláváš a na náhodných místech ji čteš, tak to je úloha pro DBMS a proudově ji řešit nelze. Tam ty roury dávají smysl leda jako doplněk, např. vstupní nebo výstupní filtr, který zajistí konverzi různých formátů nebo integraci s okolními systémy. Cílem není něco nahrazovat (už vůbec ne DBMS), ale spíš vylepšit a rozšířit stávající postupy -- aby data měla jasně danou strukturu, aby nástroje byly znovupoužitelné a daly se libovolně kombinovat: vstup → transformace → výstup
, kde na všech těch třech místech můžeš dosazovat různé nástroje, vyměňovat je, řetězit a celé to spolu mluví společným jazykem.
Tam, kde jsou data jednorozměrná (jedna relace s jedním atributem) se to dá snadno kombinovat se stávajícími nástroji jako třeba find -print0
. Tam, kde máme jednu relaci s více atributy, se to taky dát integrovat bez nějakého programování -- v příkladech na webu je např. výstup přes xargs -0
nebo while
cyklus, který naplní jednotlivé atributy do proměnných a ty si zpracuješ záznam po záznamu v shellu.
Ta omezení a odlišnosti od DBMS tam samozřejmě jsou. DISTINCT se většinou dělat nebude, pokud to uživatel vyloženě nepožaduje, stejně tak UNION bude většinou ALL.Ok. V tom pripade ale nejde o relacni zpracovani dat a nemas to postavene na relacnim modelu. Relace je mnozina a tudiz nepripousti duplicity. To ti pak bude delat paseku treba s JOINem. Co se tu snazis vytvorit je proudove zpracovani (plochych) strukturovanych dat. Coz si z principu nemyslim, ze je neco spatneho, ale je zavadejici tomu rikat relacni zpracovani. Z toho pak plyne, ze spis nez algoritmy pro praci s relacnimi daty, by mohly v tvem pripade najit prakticke uplatneni algoritmy, ktere byly vytvoreny pro zpracovani dernych stitku, pasek, atp. kdy se v minulosti pouzivaly pocitace presne tak, jak ma fungovat tvuj system.
Vím, že s tímhle je potřeba se nějak vypořádat a asi to tam líp popsat... Ve zkratce: ty duplicity jsou implementační detail a jejich odstranění je pouze odloženo na okamžik kdy (jestli) bude potřeba. Tzn. pokud bude v tom potrubí např. krok JOIN nebo UNION (bez ALL), tak se duplicity odstraní v rámci něj. Ale do té doby můžou skrze potrubí vesele proudit data obsahující duplicity. Ano, je to něco za něco, hrozí např. že se nějaká funkce zavolá na stejných datech opakovaně, i když by ji stačilo zavolat jednou (protože v příštím kroku dojde k deduplikaci, ale to ten aktuální krok neví), ale na druhou stranu stačí po většinu času držet v paměti právě jeden záznam. Na rozdíl od SQL to není tak deklarativní a je na uživateli, aby navrhl pořadí operací tak, jak mu to vyhovuje, a např. na vhodné místo vložil relpipe-tr-distinct
1 rozhodl, zda ušetří raději cykly CPU nebo paměť.
[1] resp. on to spíš bude nějaký relpipe-tr-order
nebo -sort
, který udělá volitelně odstranění duplicit, protože -distinct
by taky musel umět řadit.
Ve zkratce: ty duplicity jsou implementační detail a jejich odstranění je pouze odloženo na okamžik kdy (jestli) bude potřeba.To neni implementacni detail, ale rozchod s logickym modelem, na kterem stavis.
a rozdíl od SQL to není tak deklarativní a je na uživateli, aby navrhl pořadí operací tak, jak mu to vyhovujeTo mi v principu nevadi a neni to nijak v rozporu s relacnim modelem. Problem je, ze to, co vlastne delas, neni ve sve podstate prace s relacnimi daty, i kdyz ty to tak nazyvas. V popisu sice odkazujes na puvodni Codduv clanek, ale ve skutecnosti kopirujes SQL, ktere z praktickych/historickych duvodu muselo delat kompromisy. Otazka je, proc to u noveho projektu neudelat poradne uz od sameho zacatku.
Vím, že s tímhle je potřeba se nějak vypořádat a asi to tam líp popsat...V momente, kdy (si) priznas, ze to, s cim pracujes, ve skutecnosti nejsou relace, ale proudy plochych (flat) strukturovanych dat, veskere vysvetlovani nebude treba, i operace budou davat smysl bez toho, aniz by bylo potreba nejak dodatecne resit nekonzistenci s logickym modelem, tj. treba ty duplicity.
V popisu sice odkazujes na puvodni Codduv clanek, ale ve skutecnosti kopirujes SQL, ktere z praktickych/historickych duvodu muselo delat kompromisy. Otazka je, proc to u noveho projektu neudelat poradne uz od sameho zacatku.
Pokud by "pořádně" znamenalo, mít v každý (tzn. i ten, který uživatele nezajímá) okamžik data unikátní, tak by to vyžadovalo, je pořád dokola řadit a odstraňovat duplicity. Jaký užitek by to přineslo?
Mě zajímá, aby se to navenek chovalo konzistentně, aby když se např. nějaká operace jmenuje JOIN nebo UNION, tak aby vrátila, co od ní člověk čeká. Ale, že někde uvnitř proudí duplicitní data, to mě až tak netrápí. V metadatech bude časem možnost deklarovat, že jsou data unikátní/setříděná, ale nevidím přínos v tom tam tohle pravidlo zadrátovat natvrdo a vyžadovat ho vždy, protože to by podle mého nic dobrého nepřineslo.
Jaký užitek by to přineslo?Ze by se to chovalo konzistentne a v souladu s nejakymi teoretickymi predpoklady, ktere sis sam nastavil. Z pohledu RM kazda ntice v dane relaci vyjadruje nejaky fakt, treba "pes ma ctyri nohy", "/dev/sda5 je pripojeno na /home". Jaky smysl ma, kdyz tento fakt zopakujes dvakrat, trikrat, ...? Porad to bude stejny fakt. I proto dava smysl mit relaci jako mnozinu ntic, protoze nezalezi na poradi faktu a pravdivost daneho faktu lze jednoduse vyjadrit tak, ze do dane relace bud nalezi nebo nenalezi.
Mě zajímá, aby se to navenek chovalo konzistentně, aby když se např. nějaká operace jmenuje JOIN nebo UNION, tak aby vrátila, co od ní člověk čeká.A to je problem, v tvem settingu zavest nektere operace konzistentne bude problem. Vezmi si treba rozdil nebo prunik, v pripade mnozinoveho rozdilu/pruniku je to jednoduche. S duplicitnimi daty uz zacnes narazet na problemy. Vezmi si dve tabulky T1 a T2 s nticemi A a B.
T1 = { A, A, A, B, B } T2 = { A }Co by melo byt vysledkem operace
T1 EXCEPT T2
, ktera rika, vyber z T1 takove ntice, ktere nejsou v T2? Ma to byt { B, B }
nebo { A, A, B, B }
nebo snad { B }
ci { A, B }
.
U sjednoceni se duplicitni radky ztrati (muzes je eliminovat, kdyz to potrebujes), ale v tomto pripade to ma dopad na konkretni vysledek. Mnozinove operace tu evidentne nedavaji dobry smysl, protoze jsou nejednoznacne.
Zeptam se jinak. Jaky uzitek prinasi tvarit se, ze pracujes s relacnim modelem, kdyz s nim ve skutecnosti nepracujes?
Co by melo byt vysledkem operace T1 EXCEPT T2, ktera rika, vyber z T1 takove ntice, ktere nejsou v T2? Ma to byt { B, B } nebo { A, A, B, B } nebo snad { B } ci { A, B }.
Výsledkem by bylo 'B' (stejně jako v SQL). Viz co jsem psal o duplicitách výše:
jejich odstranění je pouze odloženo na okamžik kdy (jestli) bude potřeba
Odstranění duplicit je nutné v tomto kroku, tak se stane v něm a nebude se dělat (zbytečně) někde dřív.
Zeptam se jinak. Jaky uzitek prinasi tvarit se, ze pracujes s relacnim modelem, kdyz s nim ve skutecnosti nepracujes?
Relační model je přirozená forma, se kterou tam chci pracovat. V nějakém prostředí je přirozené pracovat se stromovými strukturami, v jiném s obecnými grafy, v jiném s poli bajtů nebo maticemi čísel atd. a v tomto prostředí to jsou relace. Že v tom prostředí budeš pracovat s daty, která pro něj nejsou přirozená, je tvoje věc, tvoje riziko. Ano, bylo by možné striktně vyžadovat, aby na výstupu byly vždy jen unikání záznamy, ale nevýhody převažují nad výhodami. Proto jsem se rozhodl tu kontrolu (resp. odstranění duplicit) přenést na vstup programu, pro který je ta unikátnost důležitá.
{ B, B }
odpovida prirozene (slovni) interpretaci "except"
{ A, A, B, B }
odpovida vysledku, pokud relacni model postavis na multimnozine (k tomu existuji nejake vicemene konzistentni teoreticke zaklady, i kdyz vetsinou to vypada jen jako snaha dat SQL alespon nejaky teoreticky podklad.
{ B }
odpovida chovani SQL a je to trochu WTF vysledek, protoze s B se nijak nepracuje presto zmizi. Vezmi si treba T EXCEPT {}
, jeden by cekal, ze bude platit (T EXCEPT {}) == T
, coz odpovida chovani mnozinoveho rozdilu a platilo by i v pripade multimnozin. Ale v tvem (a v SQL) pripade ({ A, A, A, B, B } EXCEPT {}) == { A, B })
. Jestli to neni divne chovani, tak uz opravdu nevim.
Relační model je přirozená forma, se kterou tam chci pracovat.Ale to, s cim pracujes, neni relacni model, ale jiny model postaveny na dvourozmernych tabulkach. Ne kazda dvourozmerna tabulka odpovida relaci a ma to sve opodstatneni, viz muj predchozi komentar o tom, ze nema smysl jeden fakt uvadet vicekrat. Jinak, abys to chapal spravne, me nevadi, co (nebo jak) delas za projekt a chapu, ze nekomu to muze prijit uzitecne. Mne vadi, ze rikas, ze tam pouzivas relacni model pricemz to ma do relacniho modelu daleko a ze pouzivas oznaceni pro mnozinove operace pro operace, ktere mnozinove nejsou.
XML v tomhle případě ne, dělám na něčem jiném, postaveném na relačním modelu.Tomuhle moc nerozumim. Je tam nějaký relační model ve smyslu třeba referencování pomocí cizích klíčů? Jak na to koukám, tak mi to přijde, že to je jen kontejner polí tuplů. Což je v podstatě podmnožina nějakého modelu á la JSON nebo něco podobného (teď nemyslim serializaci, ale sadu datových typů a jejich strukturuování). Nebylo by lepší / obecnější prostě použít nějaký takový datový model a nad tím používat operátory a koncepty funkcionálního programování? Shellová pipeline svou podstatou přímo vybízí k použití nějaké monadické struktury napřo. pro error handling, debugovací informace atd.
Budou tam volitelná metadata, která umožní popsat např. ty cizí klíče nebo význam jednotlivých atributů nebo přidat nějaká omezení jako jsou délky, možná regulární výrazy atd. V podstatě taková strojově čitelná dokumentace. Nicméně z podstaty věci tam není žádná centrální autorita (není to DBMS), která by tahle pravidla mohla vynutit. Takže pokud se budeš odkazovat na neexistující data, tak to v příštím kroku buď spadne nebo nic nenajde, záleží, jak to příslušný filtr implementuje. Ale myslím, že tyhle odlišnosti od DBMS jsou celkem zřejmé a intuitivní.
Takže pokud se budeš odkazovat na neexistující data, tak to v příštím kroku buď spadne nebo nic nenajde, záleží, jak to příslušný filtr implementuje.Ok. Pokud neznáš koncept Either/Result jak je použit v jazycích jako Haskell, OCaml, Rust, Swift a podobně, tak vřele doporučuju se na to mrknout. Na tenhle usecase mi to přijde jako prdel na hrnec. Zejména když to podporuje řetězení, tak je to super. Tj. je to podobné jako řetězní výjimek, ale s tím, že to je jen hodnota, takže není potřeba řešit mechanismus na výjimky a nedochází tam k tomu přerušení toku kódu.
P.S. V podstatě se to oproti DBMS chová trochu jako dynamické programovací jazyky, kde máš taky větší volnost, některé věci stojí spíš na konvencích než striktně garantovaných pravidlech, a taky tam můžeš něco "slíbit" a pak to porušit a výsledkem je, že ti to spadne. Nebrání ti to se střelit do nohy -- to potrubí je tvoje a je v tvém vlastním zájmu si ho nerozbíjet. Není to jako databáze, kam můžeš pustit někoho cizího, aby ti tam třeba INSERToval nebo volal nějakou proceduru a DBMS ohlídá, že neporuší cizí klíče, délky polí atd. Tady je ta kontrola volitelná a uděláš ji pomocí vložení nějakého validátoru, když ji potřebuješ.
tree -J
už dávno bleje JSON.
A tree -X
zase XML :-) BTW: když na ty dva výpisy koukám, tak mi přijde, že v JSONu je hrozného vizuálního šumu (dvojtečky, uvozovky, čárky, složené závorky). Oproti tomu se to XML čte líp.
Tak se na ty dva výpisy zkus podívat ;-)
wc -c
. Ten JSON ti přijde hůř čitelný IMHO protože jsi zvyklý na XML a protože ten výstup z nějakého důvodu nedělá mezery za tečkou a mezi obsahem a složenýmá závorkama, dost to zhušťuje.
Případně o dost lidsky čitelnější než JSON i XML bude nejspíše YAML:
tree -J | python -c 'import sys, yaml, json; yaml.safe_dump(json.load(sys.stdin), sys.stdout, default_flow_style=False)'
Hezký výstup by šel i pomocí TOMLu, ale to vyžaduej víc processingu a nemam teď čas to psát...
Ten JSON ti přijde hůř čitelný IMHO protože jsi zvyklý na XML
Ne, psal jsem o vizuálním šumu. Ty kombinace dvojteček, čárek a uvozovek hned vedle sebe jsou hodně rušivé. Stejně tak ty složené1 závorky na začátcích řádků rozostřují tu hranu a úroveň odsazení.
JSON:
$ tree -J /etc/network [ {"type":"directory","name":"/etc/network","contents":[ {"type":"directory","name":"if-down.d","contents":[ {"type":"file","name":"avahi-autoipd"}, {"type":"file","name":"bind9"}, {"type":"file","name":"postfix"}, {"type":"link","name":"wpasupplicant","target":"../../wpa_supplicant/ifupdown.sh","contents":[]} ]}, {"type":"directory","name":"if-post-down.d","contents":[ {"type":"link","name":"avahi-daemon","target":"../if-up.d/avahi-daemon","contents":[]}, {"type":"link","name":"bridge","target":"/lib/bridge-utils/ifupdown.sh","contents":[]}, {"type":"file","name":"wireless-tools"}, {"type":"link","name":"wpasupplicant","target":"../../wpa_supplicant/ifupdown.sh","contents":[]} ]}, {"type":"directory","name":"if-pre-up.d","contents":[ {"type":"link","name":"bridge","target":"/lib/bridge-utils/ifupdown.sh","contents":[]}, {"type":"file","name":"wireless-tools"}, {"type":"link","name":"wpasupplicant","target":"../../wpa_supplicant/ifupdown.sh","contents":[]} ]}, {"type":"directory","name":"if-up.d","contents":[ {"type":"file","name":"avahi-autoipd"}, {"type":"file","name":"avahi-daemon"}, {"type":"file","name":"bind9"}, {"type":"file","name":"ntpdate"}, {"type":"file","name":"openssh-server"}, {"type":"file","name":"postfix"}, {"type":"link","name":"wpasupplicant","target":"../../wpa_supplicant/ifupdown.sh","contents":[]} ]}, {"type":"file","name":"interfaces"} ]}, {"type":"report","directories":4,"files":19} ]
XML:
$ tree -X /etc/network <?xml version="1.0" encoding="UTF-8"?> <tree> <directory name="/etc/network"> <directory name="if-down.d"> <file name="avahi-autoipd"></file> <file name="bind9"></file> <file name="postfix"></file> <link name="wpasupplicant" target="../../wpa_supplicant/ifupdown.sh"></link> </directory> <directory name="if-post-down.d"> <link name="avahi-daemon" target="../if-up.d/avahi-daemon"></link> <link name="bridge" target="/lib/bridge-utils/ifupdown.sh"></link> <file name="wireless-tools"></file> <link name="wpasupplicant" target="../../wpa_supplicant/ifupdown.sh"></link> </directory> <directory name="if-pre-up.d"> <link name="bridge" target="/lib/bridge-utils/ifupdown.sh"></link> <file name="wireless-tools"></file> <link name="wpasupplicant" target="../../wpa_supplicant/ifupdown.sh"></link> </directory> <directory name="if-up.d"> <file name="avahi-autoipd"></file> <file name="avahi-daemon"></file> <file name="bind9"></file> <file name="ntpdate"></file> <file name="openssh-server"></file> <file name="postfix"></file> <link name="wpasupplicant" target="../../wpa_supplicant/ifupdown.sh"></link> </directory> <file name="interfaces"></file> </directory> <report> <directories>4</directories> <files>19</files> </report> </tree>
Ten YAML je čitelnější, ale ta automatická konverze do toho nastrká různé - contents: - contents:
. A editovat YAML mi přijde horší než XML, např. to - contents: []
a různé další způsoby zápisu. U XML se všechno dělá jedním způsobem a snáz ho odkoukáš z jiných částí dokumentu, kdybys ten formát neznal.
A nejčitelnější je samozřejmě ten původní "grafický" formát :-)
$ tree /etc/network /etc/network ├── if-down.d │ ├── avahi-autoipd │ ├── bind9 │ ├── postfix │ └── wpasupplicant -> ../../wpa_supplicant/ifupdown.sh ├── if-post-down.d │ ├── avahi-daemon -> ../if-up.d/avahi-daemon │ ├── bridge -> /lib/bridge-utils/ifupdown.sh │ ├── wireless-tools │ └── wpasupplicant -> ../../wpa_supplicant/ifupdown.sh ├── if-pre-up.d │ ├── bridge -> /lib/bridge-utils/ifupdown.sh │ ├── wireless-tools │ └── wpasupplicant -> ../../wpa_supplicant/ifupdown.sh ├── if-up.d │ ├── avahi-autoipd │ ├── avahi-daemon │ ├── bind9 │ ├── ntpdate │ ├── openssh-server │ ├── postfix │ └── wpasupplicant -> ../../wpa_supplicant/ifupdown.sh └── interfaces 4 directories, 19 files
[1] někdo jim říká "chlupaté" což je dost příznačný název
Ty kombinace dvojteček, čárek a uvozovek hned vedle sebe jsou hodně rušivé. Stejně tak ty složené1 závorky na začátcích řádků rozostřují tu hranu a úroveň odsazení.A v Jave te to nerusi? Me treba jo, a proto jsem si nakonec oblibil Haskellovou syntaxi (a rekl bych, ze $ je s prehledem nejpouzivanejsi symbol v mem kodu
Ne, psal jsem o vizuálním šumu. Ty kombinace dvojteček, čárek a uvozovek hned vedle sebe jsou hodně rušivé. Stejně tak ty složené1 závorky na začátcích řádků rozostřují tu hranu a úroveň odsazení.Když si to trochu přeformátuju - přidám vhodné mezery, tak mam:
{ "type": "file", "name": "avahi-autoipd" },
{ "type": "file", "name": "bind9" },
{ "type": "file", "name": "postfix" },
{ "type": "link", "name": "wpasupplicant", "target": "../../wpa_supplicant/ifupdown.sh", "contents": [] }
A to mi přijde úplně v pohodě, pro mě určitě ne horší než to XML, spíš lepší.
Když už mě na tom JSONu něco vysírá, tak je to nepodpora čárky za poslední položkou objektu/pole, to je naprosto nesmyslná limitace.
U XML se všechno dělá jedním způsobemROFL
<link name="bridge" target="/lib/bridge-utils/ifupdown.sh"></link>
Neměly by to být nepárové tagy? Případně neměl by name
být v obsahu elementu? Případně neměly by všechny pod-elementy ve složce být file
a mít atribut regular
, link
atd.? To by mi přišlo smysluplnější, ale YMMV.
Samozřejmě ono něco podobného platí do jisté míry i u těch ostatních formátů (např. inline table v TOMLu atd.), ale to XML mi v tomhle přijde zdaleka nejhorší a nejméně jednoznačné. Je to dané taky tím, že XML dává celkem hodně velkou volnost aplikacím různé věci různě interpretovat, takže člověk je s XML v neustálé nejistotě, jak to která aplikace schroustá nebo neschroustá.
Oproti tomu třeba string v JSONu je vždycky zapsán stejně a existuje pouze jedna interpretace, ditto TOML, pokud vím.
Suma sumárum, XML nemá mimo markup vůbec co dělat tree -J | jq
parametry předávané objektem: app {"param1":"value", "param2":{"foo":"bar"}} parametry předáváné "hezky" app --param1 "value" --param2 {"foo":"bar"}, interně interpret převede na způsob výše.Taky by mohlo být užitečné mít nějakou ENV proměnnou PRETTY=true|false, která pokud je nastavená, zajistí že interpret za každý příkaz nakonec přidá | pretty pro defaultní lidštější výpisy. Taky je zajímavé, jak se man dostane k datům nápovědy příkazu. Pokud je předaný jako parametr javascript konstanta SOS.man, příkaz vrátí nápovědu, kterou man může zobrazit. Konstantu ale nemohu předat z interpretu, jde to udělat jen z JS. Lepší by podle mě bylo, kdyby tyhle věci byly jasně definované v API, kterým se předávají apkám parametry (je jedno, jestli serializovaný jako json nebo jako objekt mezi apkama v JS). Tedy pokud udělám třeba: app {"_command": "man"}, každá apka by tomuto příkazu měla rozumět a vrátit mi man a je jedno, jestli to napíšu z konzole, nebo to pošle apka man. Zároveň by třeba ono _command bylo vyhrazené slovo, takže pokud příjde _command, který ještě není definovaný, odpoví že mu nerozumí, ale nebude si tam implementovat své vlastní _commandy, ale jenom ty ze standardu OS. A aby to bylo úplně cool, chtělo by to se z interpretu dostat přímo k jazyku, kde se dá s objekty čistě pracovat, což je u tebe JS. Tedy něco jako
PWD=`js --cmd 'SOS["bin"]["pwd"]();'`Čistě ale interpret přímo v JS by asi příliš praktický nebyl, takže nějaký "pseudobash" nad tím není špatny nápad. Bavím se samozřejmě o tom konceptu, nikoliv o tom jak je praktické mít OS v js, na jazyku nezáleží.
Ah, ano. Nepocital som s tym ze by pretty dostal na vstup retazec (lebo retazec je citatelny) takze to povazuje za pole znako a vypise to ako pole. Mal by vratit string.
> s tím že někdy se předává objekt v jsonu, někdy dva jsony, někdy string...Vstup moze byt len jeden ale ked program nie je sucastou rury tak dovolim zapisat input priamo z klavesnice, inak by som musel pisat echo vstup | program, co ale nemusi byt az tak zle..., v sucasnosti je to teda:
echo vstup | program argument program vstup argument
Keby som zrusil "program input argument" tak by to poriesilo problem rozdelovania 2 struktur.Zaujimave...
> zajistí že interpret za každý příkaz nakonec přidá | pretty pro defaultní lidštější výpisy.Premyslal som nad bodkou na koci, "command | command." by na koniec pridal | pretty
> Konstantu ale nemohu předat z interpretu, jde to udělat jen z JSJa myslim ze to nie je az taky problem. Ak chcem man data pouzijem man a ten mi tie data da. Inak by samozrejme slo napisat program ktory jednoducho vrati SOS.man:
SOS.bin.man2 = function (input, argument) { return SOS.man; };
Ale nie je sposob ako to dostat do argumentu lebo by trebalo nieco ako: echo `man2`
> chtělo by to se z interpretu dostat přímo k jazykuMozno by stacilo pridat novy prikaz: eval "alert(1+2)", alebo echo "alert(1+2)" | eval
Teď si přijdu jako šťoural a škarohlíd, proto bych to rád ještě víc rozvedl co se týče rozdílů s objektovým systémem:
Hezká ukázka je třeba tvoje implementace příkazu uptime
:
$ uptime { "seconds": 423.362, "minutes": 7.056033333333334, "hours": 0.11760055555555556, "days": 0.004900023148148148, "start": "2018-12-18T23:42:33.374Z", "start_ms": 1545176553374, "now": "2018-12-18T23:49:36.736Z", "now_ms": 1545176976736, "short": "7m up", "human": "7 minutes up" }
Na první pohled super. Zamysleme se však co jsi to dostal za objekt (protože jsi dostal objekt v JSONu). Očividně má spoustu properties o nějakém datovém typu. Zcela očividně je to objekt časové značky. Jak nyní například provedu deltu jednoho objektu s druhým?
Pokud bys dostal skutečný objekt, prostě bys ho odečetl od toho druhého. Co když budeš chtít třeba tenhle objekt přepočítat do jiné časové zóny? Property start
je očividně v ISO formátu, kde časová zóna je a stejně tak now
, ale co ty ostatní? Budeš muset mít ručně nějaký externí tool, co ten zbytek projde a zaktualizuje, což je ve své podstatě procedurální programování. Funkcionalita je oddělená od dat. Kdyby to byl skutečný objekt, tak by na to měl jednoduše metodu (funkcionalita by byla s daty spojená).
Další příklad třeba - tohle je konkrétní zobrazení objektu, není to pravda samotná. Pravda samotná jsou data uložená v počítači, na které se můžeš dívat jako na JSON, nebo třeba na YAML, nebo třeba grafickou tabulku v HTML. Kdyby to byl objekt, tak může mít patřičné metody toJSON, toYAML a tak podobně. Byl by na stringové formě nezávislý.
Nemáš k tomu zabudovanou nápovědu (uznávám, že tam máš man
). Například co je za formát now
? Musíš jít zase někam externě hledat popis, což je zase procedurální programování. Kdyby to byl objektový systém, tak si dáš prostě help(result.now)
a tam si přečteš třeba co bylo použito za formátovací string. Jenže ve skutečnosti bys tam vůbec neměl string "2018-12-18T23:42:33.374Z"
, ale datetime objekt, který bys mohl třeba upravit.
Pak samotný příkaz uptime
. To je v podstatě z určitého uhlu pohledu možné vnímat jako objekt, který vrátí tuhle stringovou reprezentaci, místo skutečného datetime objektu. To proto, že se na něj pořád díváme jako na program. V konkrétní chvíli zavolání vrátí konkrétní string (k tomu se ještě vrátím). To má své nevýhody v tom, že kdybys to chtěl použít třeba jako updatované hodiny, které zobrazují uptime
, tak to musíš buďto neustále volat znova, což má nezanedbatelnou režii, nebo si to přepočítat na nějaký datetime
a operovat s ním. Kdyby to byl objekt, tak prostě zavoláš vždycky metodu kolik uplynulo času.
No a pak ten JSON. JSON je struktura zkolabovaná na pole bajtů. Když s ním chceš pracovat, tak ho musíš rozparsovat na skutečné datové objekty. To přináší úplně nesmyslnou režii.
Chápeš, uptime
si vytvoří nějakou reprezentaci bodu v čase, který pak serializuje do JSONu ideálně nějakým serializátorem, ale možná taky skládáním stringů, a pak to druhý program bere, tokenizuje, parsuje, běží nad tím stavové automaty, které z toho rekurzivně sestaví nějakou obdobu dictionary, ze které se přečte jedno číslo a celé se to zase zahodí.
Kdybys předával rovnou skutečný objekt, tak k tomuhle nikdy nedochází.
Já osobně jsem se učil Haskell (spolu s dalšími funkcionálními jazyky) pár měsíců před Smalltalkem a rozhodně mě tolik nezaujal.
Každému z nás funguje mozek trochu jinak, což je dáno geneticky, prostředím a zkušenostmi. Každý preferuje trochu jiný druh myšlení a tak mu může vyhovovat i odlišné programovací paradigma. Jsou lidé, kteří se plácají v imperativních jazycích a najdou se třeba v logickém programování.
Rád bych dal Haskellu ještě po čase opět druhou šanci, jako jsem ji dal Prologu a rozhodně jsem toho nelitoval. Abych pravdu řekl, u Haskellu mě momentálně nenapadá žádná reálná úloha, u které bych si řekl, že Haskell je pro její řešení ten nejlepší a nejvhodnější nástroj. Byl bych rád, pokud byste uvedl nejlépe několik takových, u kterých si to myslíte.
No, ja nevim jestli je nejaka realna uloha, na kterou je Haskell nejlepsi nastroj. Cim jsem starsi, tim mi to prijde hur polozena otazka. Obvykle se to nejvic vychvaluje na kompilatory a ruzne prototypovani, ale jako obecny programovaci jazyk se to da pouzit pro spoustu domen.
Já vím, že ta otázka je trochu hloupá a u jazyka pro obecné použití s jiným paradigmatem se na ni často nedá odpovědět uspokojivě tak, aby to tazatele zaujalo, viz třeba podobný dotaz směřovaný na Pharo. Ale třeba u logického programování je jednoduché najít řadu úloh, pro které je vyloženě ideální. V případě Haskellu by mohla být silným lákadlem snadná paralelizovatelnost, ale ani tam si nejsem jist, jestli se nejedná jen o chimérickou vlastnost, kterou zatím nikdo nedokázal skutečně použitelně implementovat.
Jinak si myslim, ze podobne jako Lisp (ci Scheme) se ma smysl to naucit prave kvuli tomu paradigmatu. (Pises, ze ses to ucil s "jinymi funkcionalnimi jazyky", asi zalezi s jakymi, treba Lisp je hodne jiny.)
Chápu, Lisp bych osobně řadil blíže ke Smalltalku než ke skutečně funkcionálním jazykům.
Ted duraz na cistotu a lenivost v Haskellu je zezacatku dost divny. Ale mne to doslo ve chvili, kdy jsem zjistil, ze v tom udelam totez, co v Lispu (a pomerne obtizne), a s typovou bezpecnosti navic. A clovek si uvedomi, jak moc uloh je vlastne jen interpretace nejakeho "programu".Druha vec, kterou mi to dalo - Haskell me nuti psat opravdu kratke funkce. Je to temer vylucne diky durazu na cistotu - v jinych jazycich je snazsi se nejak uspinit. To vyrazne zvysuje citelnost a znovupouzitelnost.
OOP mi moc nevyhovuje. Nevim, co je, ci by mel byt, objekt. Proti tomu, funkce a datove typy maji celkem jasne formalni definice. Proste nejak vim, kdy je potrebuji (a kdy ne), u objektu to neni zdaleka tak zjevne. Tohle plati pak i pro zakladni typove tridy - proste vidim, kdy to potrebuji.
Můj osobní aktuální nepříliš podložený dojem je ten, že jakmile v programu musíte použít monády, nevybrali ste si na její řešení vhodný nástroj. Co se týče toho, co by mělo být objekt, tam je odpovědě přeci jasná: všechno Haskell se se vším snaží pracovat, jako by to nemělo stav, což je naopak základní vlastnost objektů. Myslím, že kvůli tomu věci občas zbytečně komplikuje a potřebuje pak vymýšlet děsivé formalismy jako zygohistomorphic prepromorphisms
Takze, abych to shrnul. Nemam pocit, ze Haskell je nejake jedno paradigma, ktere ti zmeni zivot (nebo tvoji aplikaci). Spis se naucis spousta drobnosti, ktere jsou (pro svuj ucel) tak jednoduche, jak jen mohou byt. Coz je dane tim, ze lide premysleli nad matematickymi zaklady kazde te veci.
Jak jsem psal, chtěl bych dát Haskellu ještě šanci, protože jednou za čas se přinuti převrátit si mozek naruby neuškodí.
Já vím, že ta otázka je trochu hloupá a u jazyka pro obecné použití s jiným paradigmatemNejde jen o paradigma, Haskell je svym zpusobem abstraktnejsi nez bezne programovaci jazyky (snad to bude jasne dal, proc, ale uz jenom kdyz uvazime zpusob vyhodnocovani). Takze je to trochu jako ptat se, "na co se C hodi vic nez assembler"?
Haskellu by mohla být silným lákadlem snadná paralelizovatelnostTo je zatim opravdu spis teoreticke. V Haskellu se da psat efektivni a paralelizovatelny kod, ale vyzaduje to znat jej hodne do hloubky. Je to trochu jako s tou analogii mezi C a assemblerem, jsme nekde v 80. letech, a kompilatory vyssich jazyku nejsou dost rozvinute na to, aby prevazne konkurovaly rucne psanemu assembleru. Hlavni lakadlo je v te abstrakci, ktera umoznuje vetsi prehlednost. Pritom je (temer kazdemu) zjevne, ze je to budoucnost.
Můj osobní aktuální nepříliš podložený dojem je ten, že jakmile v programu musíte použít monády, nevybrali ste si na její řešení vhodný nástroj.To je spatny dojem. Predne je potreba si uvedomit, ze v Haskellu se da programovat uplne stejne imperativne jako v kazdem jinem jazyce. Je to pak podobne asi jako se daji psat ciste strukturovane programy v OOP (vsechno v jednom objektu) nebo jako se da C pouzivat jako assembler (jedna velka funkce, vsechny promenne jsou globalni). Druha vec je, ze byt monada je vlastnost nejakych matematickych objektu. Neni to tak, ze se programator rozhodne "pouzit monadu", ale spis tak, ze ten a ten objekt "je monada". Pak jsou dve moznosti - muzes si uvedomit, ze to (co drzis v ruce) monada je, a pristoupit tak k tomu, a tim ziskas celou infrastrukturu (ruzne knihovni funkce) kterou pro monady Haskell nabizi. Nebo si to nemusis uvedomit (klidne i zamerne), a pak to proste napises tradicnim zpusobem. Je to dost podobne jako s tou volbou, jestli chces udelat promennou globalni nebo lokalni. Pokud ji udelas lokalni, bude to vetsi opruz - musis ji pak ruzne predavat jako parametr a podobne. Ale lide celkem souhlasi, ze je to prehlednejsi. Stejne je to i u monad - pokud explicitne deklarujes, ze je neco monada, kod se tim zprehledni. Podobna vec plati pro vetsinu typovych trid, nejen pro monady (za vsechny treba monoid). Muzes programovat, aniz by je znal. Ale znat ty hlavni je vyhoda, protoze se mene nadres. A neni to tak odlisne od matematiky. Treba pro nekoho muzou integraly vypadat hrozive. Ano, vsechno se da spocitat i bez nich. Ale pokud je znas a umis s nimi pracovat, je to proste prehlednejsi s nimi (nedokazujes si neustale znovu specialni pripady vet pro praci s nimi). Takze pokud bych mel dat radu, jak se ucit Haskell, tak nelamat si s tim hlavu jestli pouzivas monady nebo ne a jestli znas teorii kategorii. Pis to jak chces a az to budes potrebovat, dojde ti to. Jako kdyz se clovek uci poprve programovat, styl je taky vedlejsi. A s tim objektem.. Reknu to jinak. Na prvni pohled by se mohlo zdat, ze typova trida je jako design pattern. Ale typova trida ma (typicky) jasnou definici (ne ovsem nutne formalizovanou v pocitaci) - poznas, jestli ta vec ma prislusnou vlastnost nebo ne. Druha mensi vyhoda pak je, ze v Haskellu muzu explicitne rict, ze tohle je takova a takova typova trida. Tezko se vysvetluje proc, ale rict, ze vsechno je objekt a tady je par patternu proste neni dostatecne formalni zaklad, na kterem by se dalo bez obav stavet; je v tom tak nejak prilis mnoho intuice.
Haskell se se vším snaží pracovat, jako by to nemělo stav, což je naopak základní vlastnost objektů. Myslím, že kvůli tomu věci občas zbytečně komplikujeTa bezestavovast je docela silna vlasnost a umoznuje to nektere algoritmy zapsat elegantneji.
potřebuje pak vymýšlet děsivé formalismy jako zygohistomorphic prepromorphismsZ tohoto duvodu se mi zalibila Scala. Primarne te tlaci k tomu psat program funkcionalne, ale kdyz potrebujes, neni vubec bolestive vyskocit do objektoveho sveta a tam ulohu resit objektove, typicky treba UI.
Ta bezestavovast je docela silna vlasnostAno, chtel jsem napsat totez o referencni transparenci. Dava to cloveku moznost vyrabet opravdu znovupouzitelne stavebni bloky. Je to jako kostky Lega - hodne firem vyrabi takove kostky, ale jen z Lega se da postavit neco vetsiho, aniz by se to zacalo vselijak kroutit diky tem nepresnostem. A v tom je duvod, proc mi OOP nepripada dost formalni.
Z tohoto duvodu se mi zalibila Scala.A ja ji z podobneho duvodu moc nemusim, protoze jsem normalne celkem pohodlny a tak mi ta vynucena cistota chybi. Pokud se nekdo uci Scalu s tim, naucit se FP, tak je riziko, ze se toho moc nenauci, protoze si to bude dal psat objektove. S Haskellem je to jine.
Pokud se nekdo uci Scalu s tim, naucit se FP, tak je riziko, ze se toho moc nenauci, protoze si to bude dal psat objektoveJa se na to divam spis pragmaticky. Minimalne standardni knihovna je napsana tak, aby vedla k FP. To je podle me prvni a dobry krok, kde zacit. Na tom clovek muze s klidem zjistit, ze FP neni nic sloziteho, ze to muze prinaset vyhody a ze mutabilita objektu je vlastne problem. A postupne ho to navede k tomu, aby sam delal kod, ktery je funkcionalni (referencne transparentni). Nekde k tomu dospeje driv, nekdo pozdeji. Ale i jednotlive dilci kroky vidim pozitivne.
tak je riziko, ze se toho moc nenauci, protoze si to bude dal psat objektove. S Haskellem je to jineHaskellova komunita podle me dela FP docela medvedi sluzbu, kdy se casto tvari, ze clovek musi mit za sebou nekolik semestru teorie kategorii, typu a kdo vi ceho, aby pochopil vsechny ruzne -morfismy a mohl programovat v Haskellu. To v konecnem dusledku odradi spoustu zajemcu a ti radsi zustanou u OOP a budou tvrdit, ze FP je strasne slozite nebo v praxi nepouzitelne.
Haskellova komunita podle me dela FP docela medvedi sluzbu, kdy se casto tvari, ze clovek musi mit za sebou nekolik semestru teorie kategorii, typu a kdo vi ceho, aby pochopil vsechny ruzne -morfismy a mohl programovat v Haskellu. To v konecnem dusledku odradi spoustu zajemcu a ti radsi zustanou u OOP a budou tvrdit, ze FP je strasne slozite nebo v praxi nepouzitelne.Ano, ale na druhou stranu z toho vznikají celkem zábavné memy, jako třeba Zygohistomorphic prepromorphisms nebo "A monad is just a monoid in the category of endofunctors, what's the problem?".
Haskellova komunita podle me dela FP docela medvedi sluzbu, kdy se casto tvari, ze clovek musi mit za sebou nekolik semestru teorie kategorii, typu a kdo vi ceho, aby pochopil vsechny ruzne -morfismy a mohl programovat v Haskellu.Ja si myslim, ze je to nevyhnutelne. Ja chapu funkcionalni programovani jako jakysi "most" mezi programovanim a jistou specializovanou oblasti matematicke logiky (kolem lambda kalkulu, teorie typu a teorie kategorii). A Haskell je primo uprostred toho mostu. No a od otevreni toho mostu se na nem setkavaji ruzni lide. Ta druha strana ma jinou kulturu, a taky jiny jazyk. A nekteri z tech lidi, co se takto stretavaji, se divaji na druhou stranu pohrdave. Kdyz jsem byl jeste na VS, kolem roku 2000, delal jsem klasickou matematiku a o teto oblasti matematicke logiky jsem mnoho nevedel. Trochu me zajimalo automaticke dokazovani, ale matematici kolem automatickeho dokazovani pouzivaji prave zcela jiny jazyk nez normalni matematici. Tehdy jsem si to ani neuvedomoval, a veci jako Coq mi prisly zcela nesrozumitelne. Mnohem pozdeji jsem zjistil, ze zde existuje tento most (Haskell). A to vyjasnilo hodne veci, treba ze matematika a programovani je vlastne z jisteho pohledu totez (Curry-Howard izomorfismus) a ze ta tajemna oblast matematiky je proste jen jiny matematicky jazyk, asi jako je Python jiny jazyk nez C. Najednou, skrz ten Haskell, to co delaji ti na te druhe strane toho mostu, zacalo byt uplne prirozene. Jako v jinych inzenyrskych oborech, kde eventualne inzenyri zjistili, ze potrebuji opravdu dobre znat fyziku, myslim, ze postupne programatori zjisti, ze potrebuji opravdu dobre znat tu oblast matematiky. Muzeme se dlouho snazit o elegantni design ad hoc, bez skutecne formalnich zakladu (jako to treba dela Alan Kay nebo Rob Pike nebo Rich Hickey), ale myslim, ze je to ve finale marna snaha, protoze proste matematici tohle delaji staleti (hledani a popis elegantnich systemu) a maji v tom zatracene dobrou praxi (stalo se to Einsteinovi, a stalo se to Peyton-Jonesovi v pripade monad, a mnoha jinym, ze v matematice nasli uz pripravene nejelegantnejsi mozne reseni sveho problemu).
Muzeme se dlouho snazit o elegantni design ad hoc, bez skutecne formalnich zakladu (jako to treba dela Alan Kay nebo Rob Pike nebo Rich Hickey), ale myslim, ze je to ve finale marna snaha, protoze proste matematici tohle delaji staleti (hledani a popis elegantnich systemu) a maji v tom zatracene dobrou praxi (stalo se to Einsteinovi, a stalo se to Peyton-Jonesovi v pripade monad, a mnoha jinym, ze v matematice nasli uz pripravene nejelegantnejsi mozne reseni sveho problemu).
Tak v čem je tedy problém a proč většina lidí stále píše v jazycích jako C nebo Java?
U toho assembleru si ale dokážu představit praktické důvody, proč použít C nebo vyšší programovací jazyk -- kompilátory z vyšších jazyků vygenerují lepší kód než drtivá většina programátorů napíše v assembleru, je to efektivnější a i u těch nejlepších assembleristů by byla ztráta času psát v něm všechno (když už, tak má smysl v něm optimalizovat jen některé části programu).
Ale u těch jazyků jako Haskell pořád nevím, jestli je to jen mentální cvičení nebo to má mít nějaký reálný přínos. Někdo už se tu ptal, k čemu se Haskel hodí víc než jiné jazyky, ale konkrétní odpověď nedostal. Ano, můžeš říkat, jak mi to otevře oči, rozšíří obzory a tak, to je všechno hezké, ale budu pak psát programy v kratším čase, s méně chybami, rychlejší? Bude to nějaký měřitelný a nezanedbatelný rozdíl oproti současnosti? (se svojí současnou efektivitou jsem poměrně spokojen) Pokud ne, tak to počítám pořád do toho mentálního cvičení. Což je sice taky důvod proč něco dělat... Ale v tom případě mi přijde přínosnější si obzory rozšiřovat jinak, např. si přečíst nějakou knihu, klidně i mimo obor, někam se podívat, věnovat se i činnostem, které mají přesah do hmotného světa (něco fyzického vyrábět atd.), protože samotné psaní kódu je jen malá část celkové mozaiky a ve výsledku hrají podstatnější roli spíš jiné věci, než zda jsi to napsal v tom či onom jazyce/paradigmatu. Je to asi jako kdybys točil film s perfektním kameramanem a zvukařem, ale scénář nestál za nic. V tom filmu pak sice může být pár zajímavých momentů, nad kterými lidi z oboru budou rozjímat, ale celkově ten film bude špatný a neúspěšný. Navíc je otázka, jestli ten kameraman a zvukař jsou objektivně perfektní/nejlepší, nebo zda jen mají v určitých kruzích dobré jméno a jsou tam uctíváni.
U toho assembleru si ale dokážu představit praktické důvody, proč použít C nebo vyšší programovací jazykAno, protoze zijes v jine ere. To co pak pises dal jsou uplne stejne diskuse na toto tema jako pred 40 lety, akorat tehdy se diskutoval assembler vs. vyssi jazyk. A uprimne, nechapu, co se mi svym textem snazis sdelit. Proc by me melo zajimat, ze te to nezajima?
Ale u těch jazyků jako Haskell pořád nevím, jestli je to jen mentální cvičení nebo to má mít nějaký reálný přínosObecne funkcionalni pristup muze prispet ke zkvalitneni kodu a jeho zprehledneni. Uz nekolikrat jsem se dostal do pasti, kdy jsem si udelal hezky objektovy model, ktery se s pridavanim dalsich funkci zacal rozpadat, protoze byl vytvoreny s predpoklady, ktere se v budoucnu staly/ukazaly jako neplatne. Treba jsem mel optimalizator dotazu pro relacni databazi nejdriv napsany ciste objektove a pak jsem jej pro prilisnou komplikovanost prepsal do funkcionalniho stylu. Vysledny kod je sice o neco min efektivni, ale je mnohem srozumitelnejsi a udrzovatelnejsi.
Ja chapu funkcionalni programovani jako jakysi "most" mezi programovanim a jistou specializovanou oblasti matematicke logiky (kolem lambda kalkulu, teorie typu a teorie kategorii).Ty se snazis chapat FP (nebo spis Haskell) jako prostredek, ktery umoznuje vyjadrit fundamentalni vztahy mezi vypocetnim procesem a urcitou oblasti matematiky. To je relevantni oblast, pokud te to zajima, nebo se snazis vytvorit programovaci jazyk nebo vypocetni model pro nejaky programovaci jazyk. Bez toho to rozumne nepujde, protoze pak vytvoris neco, co bude nejakym zpusobem nekonzistentni. Pro priklad, jak dopada nepochopeni teoreticke podstaty problemu, nemusime chodit daleko, viz vyse. Ja jsem ve svem prispevku mel namysli spis ten prakticky pohled, kdy programovaci jazyk slouzi jako prostredek k reseni konkretnich (domenovych) problemu. V takovem pripade FP funguje jen jako prostredek, jak organizovat vypocet, a je to spis forma HCI nez nejaky nastroj k pochopeni podstaty vesmiru, zivota a tak vubec. Tech dokladu, ze opravdu nepotrebujes znat teorii typu/kategorii, je cela rada. Treba Lispova komunita se bez toho v podstate obejde, studenti prvnich rocniku, kde se ve vyuce inspirovali SICP, zvladaji funkcionalni programovani bez dalsich problemu, a dalo by se pokracovat. Kdyz jsme u toho, funkcionalne se da programovat i v Jave 1.4, je to opruz, ale jde to. Funkcionalne programovani je z meho pohledu hlavne o uchopeni problemu, ktere te pak vede k nejakemu srozumitelnemu reseni. Proto z toho praktickeho pohledu (co bylo pointou meho predchoziho prispevku), cim vic se bude uplatnovat funkcionalni styl programovani v realnych programech, tim lip. Ale at proboha Haskellisti nedesi bezne programatory tim, ze musi mit za sebou X semestru abstraktni matematiky. S takovou spoustu lidi jen odradi a ti se pak budou placat v objektech se vsemi vyhodami ale i neduhy, co k tomu patri.
Ale at proboha Haskellisti nedesi bezne programatory tim, ze musi mit za sebou X semestru abstraktni matematiky.Takhle, ja souhlasim, ze by to nemeli delat. A myslim, ze v mnoha pripadech neni umyslem nekoho desit. Ale mam za to, ze k tomu bude dochazet, protoze proste jde o urcity kulturni stret a vysledek bude pravdepodobne nejaka synteza obou kultur. (Nepochybne existuje i pohled z druhe strany - mnozi ti teoretici take nejsou vzdy zcela nadseni z toho, jak se funkcionalni programovani podarilo nekde zpitvorit do realne praxe.) Jinak to co rikas v podstate doporucuje Don Stewart, jeden z prednich clenu Haskellovske komunity - programovat v Haskellu pokud mozno bez vsech tech fancy vynalezu z teorie typu a kategorii, jenom pomoci zakladnich znalosti o funkcich a datovych typech, a dokonce i vyhnout se zbytecnemu pouzivani typovych trid.
Jinak to co rikas v podstate doporucuje Don Stewart, jeden z prednich clenu Haskellovske komunity - programovat v Haskellu pokud mozno bez vsech tech fancy vynalezu z teorie typu a kategorii, jenom pomoci zakladnich znalosti o funkcich a datovych typech, a dokonce i vyhnout se zbytecnemu pouzivani typovych trid.To si myslim, ze je rozumny pristup a od lidi z Haskell komunity docela nezvykly. Asi to bude tim, ze kdyz clovek chce resit vedlejsi efekty, musi zabrednout do monad a veci okolo. V tomto smeru jazyky, ktere nejsou ciste funkcionalni, maji tu vyhodu, ze opustit ciste funkcionalni svet je mnohem jednodussi a primocarejsi. Jeste jedna vec, Haskell nabizi celou skalu abstrakci, ale o jejich pouzitelnosti by se daly vest diskuze. Ze zkusnosti, pro vyraznou cast (aplikacnich) programatoru jsou i genericke tridy (napr. v Jave) natolik abstraktni, ze pro ne nemaji pouziti (ve smyslu, ze by je vytvareli), coz naznacuje, jak moc nektere vlastnosti, kterych si na Haskellu ceni jedni, budou oceneny temi, kteri maji programovani jako svuj denni chleb.
To je imho KILLER feature, v ziadnom pripade by som to nechcel inak
> No a pak ten JSON. JSON je struktura zkolabovaná na pole bajtů. Když s ním chceš pracovat, tak ho musíš rozparsovat na skutečné datové objekty. To přináší úplně nesmyslnou režii.Ak pouzivas pajpu tak sa nikde nic neparsuje, medzi programami sa predava priamo objekt, resp. jeho referencia. To ze vydis json ako string sposobuje terminal (ked dobehne posledny prikaz tak sa zobrazi vysledok s indentom danym v env.indent)
> Nemáš k tomu zabudovanou nápovědu. Například co je za formát now?Neni problem pridat do manualu uptime toto:
format: { now: "ISO 8601", now_ms: "UNIX Epoch time" },
A potom napr.:
$ man uptime | filter format | values | nth 0 | filter now | values | join ISO 8601
Keby to malo viacurovnovy filter tak staci man uptime | filter format.now
To je imho KILLER feature, v ziadnom pripade by som to nechcel inakProč?
Ak pouzivas pajpu tak sa nikde nic neparsuje, medzi programami sa predava priamo objekt, resp. jeho referencia. To ze vydis json ako string sposobuje terminal (ked dobehne posledny prikaz tak sa zobrazi vysledok s indentom danym v env.indent)Jo, to uznávám. To je momentálně případ tvého systému, kdybys to chtěl však naroubovat na unix, tak tam tyhle problémy mít imho budeš.
Neni problem pridat do manualu uptime toto:No, to je právě ono. Proč? Proč mít popis někde vedle? Ve výsledku je to to samé, akorát ten tvůj přístup je nepřímý a nepřímo prolinkovaný s těmi daty, kde musíš něco filtrovat a spojovat roury do sebe, abys dostal něco co může být jednu referenci daleko. Jinak ten tvůj systém mi trochu připomíná tu mnou několikrát zmiňovanou Generu.
To je momentálně případ tvého systému, kdybys to chtěl však naroubovat na unix, tak tam tyhle problémy mít imho budeš.
Tohle by šlo řešit tak, že by shell interpretoval tu rouru a pokud by na obou stranách | našel objektové programy, tak by je nepropojil přes STDIO, ale spustil by je třeba s nějakou proměnnou prostředí, která by jim řekla, kudy spolu mají objektově mluvit (např. přes nějakou sběrnici poslat zprávu typu: támhle v paměti jsem ti nechal objekt ke zpracování).
Případně by shell došel k tomu, že nejde o příkaz (proces, který se teprve má spustit) ale o referenci na již existující objekt, jehož metoda se má zavolat. Podobně jako existují příkazy, aliasy, funkce a built-in příkazy shellu, tak by mohly existovat objekty/metody.
Tohle by šlo řešit tak, že by shell interpretoval tu rouru a pokud by na obou stranách | našel objektové programy, tak by je nepropojil přes STDIO, ale spustil by je třeba s nějakou proměnnou prostředí, která by jim řekla, kudy spolu mají objektově mluvit (např. přes nějakou sběrnici poslat zprávu typu: támhle v paměti jsem ti nechal objekt ke zpracování).Ono jde taky o to, že nemůže nechat jen objekt, ale všechny jeho závislosti, jinak ti nebudou fungovat metody, clojures a tak podobně. Tudíž potřebuješ nějaké neustále běžící objektové prostředí. A pokud ho máš, tak ti spousta ostatních věcí, jako třeba roury přestane dávat smysl.
Mně spíš vadí, že se tam míchá obsah a forma a data nejsou v čisté podobě. Přitom čistá informace je tam jen jedna: okamžik startu systému, nebo maximálně ještě aktuální čas. Všechno ostatní je jen dopočítané sekundární, prezentace odvozená z původních čistých dat.
V objektovém světě by měl být spíš objekt systém a ten by měl atribut okamžik startu.1 A pak by byl způsob, jak tento atribut naformátovat a prezentovat. Ideálně bys měl mít možnost aplikovat toto formátování jak na tento atribut, tak třeba na okamžik přihlášení uživatele nebo vytvoření souboru nebo jakýkoli jiný údaj stejného typu. Kde tento způsob definovat je otázka paradigmatu (objektově/procedurálně/funkcionálně...), ale určitě si myslím, že by měl být na jednom místě a měl by být znovupoužitelný, aplikovatelný na různá data. A ne že data budou chodit už naformátovaná do deseti různých formátů.
[1] Mimochodem v objektovém systému nic jako příkazy/procesy moc nedává smysl -- všechno by to byly jen nějaké atributy (sloty, jak tomu někde říkají) jiných objektů, jejichž metody se dají volat (nebo obecněji: předávat jim zprávy).
Kdybys předával rovnou skutečný objekt, tak k tomuhle nikdy nedochází.To si myslim, že je do jisté míry iluze. Souvisí to s tímhle výrokem:
Další příklad třeba - tohle je konkrétní zobrazení objektu, není to pravda samotná.Přijde mi, že máš dojem, že ten v případě použití "skutečného objektu" je ten objekt ta pravda samotná. Ale to není pravda. Ten objekt nevyhnutelně taky má svůj nějaký formát, podobně jako ten JSON. Samozřejmě u toho objektu je to in-memory formát narozdíl od JSONu, takže se s tím pracuje líp, ale je to pouze kvantitativní posun k lepšímu, nikoli kvalitativní skok ze serializovanách dat k pravdě. Souhlasim tady s JS1. Nevim, jestli je kvůli tomu nutné se učit Haskell (já ho neumim), ale je dobré si uvědomit, že principielně není žádný rozdíl mezi "živým objektem", na kterém zavoláš metodu a mezi "mrtvými daty", které předhodíš nějaké funkci/programu/whoever. To první je jen taková maškaráda, kterou předvádí OOP. Ty znáš Déčko, takže bys mohl tohle vědět díky UFCS. Podobně jako JSON i ten formát toho objektu bude mít nějaký svůj bias. Např. jak dobře se bude pracovat se Selfovým objekt z C++? Nikdy jsem to nedělal, ale hádám, že blbě. Nebo když budu chtít poslat Selfový objekt do JavaScriptu nebo Pythonu? Buď se s tím bude pracovat blbě, nebo se to bude muset nějak převést, a to se dostaneš k operaci ekvivalentní tomu parsování...
Nevim, jestli je kvůli tomu nutné se učit Haskell (já ho neumim), ale je dobré si uvědomit, že principielně není žádný rozdíl mezi "živým objektem", na kterém zavoláš metodu a mezi "mrtvými daty", které předhodíš nějaké funkci/programu/whoever. Ty znáš Déčko, takže bys mohl tohle vědět díky UFCS.UFCS v D je v jen způsob implementace dynamický přidávaných traitů, které se jinak řeší třeba delegací. Je sice pravda, že UFCS ti umožňuje dělat OOP bez implicitně spojených dat a funkcionality, ale máš je stále spojené nepřímo přes datové typy. Je to hezká funkcionalita z hlediska programátora, ale nevím jak je to s praktičností, a jestli by nebylo třeba lepší používat ten smalltakovský model, kde jednoduše funkcionalitu přidáš do cílového objektu / classy. Pokud bys něco implementoval přes UFCS, tak je dobré si uvědomit, že pak všude kde to chceš použít máš najednou dvě závislosti - na objektu, nad kterým je to implementováno a na samotné funkci. Což se může začít nabalovat, pokud tam máš tohohle kódu víc.
Podobně jako JSON i ten formát toho objektu bude mít nějaký svůj bias. Např. jak dobře se bude pracovat se Selfovým objekt z C++? Nikdy jsem to nedělal, ale hádám, že blbě.Zrovna Self je celý napsaný v C++, takže dobře.
Nebo když budu chtít poslat Selfový objekt do JavaScriptu nebo Pythonu? Buď se s tím bude pracovat blbě, nebo se to bude muset nějak převést, a to se dostaneš k operaci ekvivalentní tomu parsování...Budeš kolem toho muset mít nějaký wrapper, asi jako když interfacuješ s C knihovnou. V tomhle by bylo ideálnější mít nějaký systém ala ten GraalVM, kde můžeš ty objekty (alespoň co tak chápu) používat přímo.
UFCS v D je v jen způsob implementace dynamický přidávaných traitů, které se jinak řeší třeba delegací. Je sice pravda, že UFCS ti umožňuje dělat OOP bez implicitně spojených dat a funkcionality, ale máš je stále spojené nepřímo přes datové typy. Je to hezká funkcionalita z hlediska programátora, ale nevím jak je to s praktičností, a jestli by nebylo třeba lepší používat ten smalltakovský model, kde jednoduše funkcionalitu přidáš do cílového objektu / classy. Pokud bys něco implementoval přes UFCS, tak je dobré si uvědomit, že pak všude kde to chceš použít máš najednou dvě závislosti - na objektu, nad kterým je to implementováno a na samotné funkci. Což se může začít nabalovat, pokud tam máš tohohle kódu víc.Tohle celé mi přijde jako řešení implementačních detailů, které jsou podstatné z programátorského hlediska pro nějaké namespacování nebo sémantiku overloadingu / vyhledávání / linkování, ale jinak na obecné úrovni mi to přijde jako úplně šumák. Jinými slovy přidání funkce pracující se strukturou a přidání metody do objektu vnímám jako identickou operaci která se liší jen v tehcnických detailech.
Zrovna Self je celý napsaný v C++, takže dobře.Počkat, to z toho vůbec neplyne. Třeba Python (CPython) je napsaný v C, ale z C/C++ se s tím pracuje pěkně debilně.
Budeš kolem toho muset mít nějaký wrapper, asi jako když interfacuješ s C knihovnou. V tomhle by bylo ideálnější mít nějaký systém ala ten GraalVM, kde můžeš ty objekty (alespoň co tak chápu) používat přímo.Jo, to by šlo, Graal a Truffle jsou zajímavé projekty. Jsem zvědav, jak se jim bude dařit. Mam trochu obavu, že je dost možná převálcuje webassmebly. V každém případě u těhle ambicí je IMHO víc než kdekoli jinde ďábel v detailech. Třeba u Graalu jsem někde četl, že je problém s warmup a spotřebou paměti. Ale vypadá to jako zatím asi nejlepší pokus. Uvidíme.
Jinými slovy přidání funkce pracující se strukturou a přidání metody do objektu vnímám jako identickou operaci která se liší jen v tehcnických detailech.Objekt si nese metody s sebou, což vede na jiné rozdělení kompetencí. Z hlediska třeba algoritmů to je možná detail, ale z principu softwarové architektury je to principiální věc (alespoň z pohledu na systém zvenčí - interně mohou ty metody nezávislé na třídách, jako třeba traity).
No a tady jde o to, zda by ten systém mohl být nezávislý na programovacím jazyku. Což je IMHO podmínka praktického rozšíření...Budeš kolem toho muset mít nějaký wrapper, asi jako když interfacuješ s C knihovnou. V tomhle by bylo ideálnější mít nějaký systém ala ten GraalVM, kde můžeš ty objekty (alespoň co tak chápu) používat přímo.Jo, to by šlo, Graal a Truffle jsou zajímavé projekty. Jsem zvědav, jak se jim bude dařit. Mam trochu obavu, že je dost možná převálcuje webassmebly. V každém případě u těhle ambicí je IMHO víc než kdekoli jinde ďábel v detailech. Třeba u Graalu jsem někde četl, že je problém s warmup a spotřebou paměti. Ale vypadá to jako zatím asi nejlepší pokus. Uvidíme.
Např. jak dobře se bude pracovat se Selfovým objekt z C++? Nikdy jsem to nedělal, ale hádám, že blbě. Nebo když budu chtít poslat Selfový objekt do JavaScriptu nebo Pythonu? Buď se s tím bude pracovat blbě, nebo se to bude muset nějak převést, a to se dostaneš k operaci ekvivalentní tomu parsování...
GraalVM tohle nějak zvládá, ale na úrovni OS by to bylo ještě o dost těžší. Moc si nedovedu představit, na jakých principech by tam fungoval GC a jak to naroubovat na spouštění programů. Úniky paměti by tam byly asi dost peklo a často by ses dostal do stavu, kdy máš plno objektů v paměti a nevíš, jestli už je můžeš uvolnit nebo ne. Musel bys nějak spolehlivě sledovat reference napříč různými programy psanými navíc v různých programovacích jazycích. Možná by pomohl Region-based memory management, kde by se třeba po skončení procesu zahodila celá množina objektů. Ale zase by z toho bylo potřeba vyjmout některé objekty, které proces záměrně předal jiným procesům, které ještě běží...
Jinak do toho GraalVM bys mohl teoreticky nabootovat a prohlásit ho za OS. Ale problém tohoto přístupu je, že když se ti tam něco podělá nebo dojde paměť, tak jsi skončil a musíš restartovat celý systém. V tomhle jsou klasické OS odolnější, protože jen pozabíjí neposlušné procesy a jede se dál, protože ten základ, který to řídí je relativně jednoduchý.
class System { class Xorg { class Windows { class SomeProgram { object STDINOUT.writeData() object STDINOUT.readData() ... } class AnotherProgram {...} } All Windows calls ... } All System calls ... ... class STDINOUT { object data object getData() object writeData() } }Máme tu aj druhú možnosť a to nezávislú na systéme a spraviť to len užívateľskom priestore. stratí sa pointa že všetko vracá objekt, ale rúry (unifikované objektové rozhranie) budú fungovať, len úplne inak, proste budú do objektov pridávať svoje metódy, tie sa spustia a skončením programu sa odstránia. Príklad:
class STDINOUT { object data object getData() object setData() ... // Metods added by programs object SomeProgram.muliply() }Alebo to chápem zle, v tom prípade by sa hodil nejaký názorný príklad.
Není to tak dokonalé jako předmět článku, ale řeší to použitelný výpis pro uživatele i možnost jiným programům porozumět přenášeným datům. https://gitlab.com/tomas.srb/bystros