Zobrazit příspěvky

Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.


Příspěvky - BoneFlute

Stran: 1 ... 31 32 [33] 34 35 ... 133
481
Vývoj / Re:Kotlin nebo Scala pro backend?
« kdy: 04. 11. 2020, 18:37:11 »
Jenže tam chybí nějaký cíl, něco, co by to zastřešilo, dalo to jazyku nějaký smysl. U Javy, Scaly, Go, C++, Rustu, C, JavaScriptu, TypeScriptu, Pythonu, Perlu nebo PHP dokážu ten jazyk charakterizovat jednou větou. V případě Kotlinu to nedokážu – resp. jedna věta by byla o tom, jak Kotlin vznikl, ne k čemu je určen.

Kotlin je určen ke všemu, k čemu je určena java. Má mít kompaktnější syntax (properties, data classes, switch expressions, lambdy, type inference, template strings....  něco z toho se později dostává do javy..). Má být bezpečnější pro "průmyslové použití" tj návrhem preventivně bránit částým chybám (null safe calls, == vs ref. equality..). "Průmyslové použití" pro mne znamená  velký projekt, kde kód píše hodně lidí s různými úrovněmi znalosti.  Zároveň, do třetice, ten jazyk má být jednoduchý na naučení (ne o moc složitější než java) a kód v něm má být dobře udržovatelný (jako v javě). Takže se právě naopak chce vyhnout zbrklému přidávání features stylem "kočička pejsek".
A řekl bych, že úspěšně.
Tak určitě je lepší než Java. To je ale hodně nízká laťka.
Chtěl jsem tu jen oponovat pocitu, že Kotlin je dort pejska a kočičky mým pocitem, že naopak Kotlin je docela pěkně konzistentní.

Osobně mi přijde taky málo, ale to je už jinej příběh.

482
Vývoj / Re:SQL skopirovanie novo pridaneho zaznamu do triggru
« kdy: 04. 11. 2020, 11:32:48 »
ak padne transakcia v trigri, pripadne ten druhy server bude nedostupny, tak sa zaznam nevlozi ani do tej prvej db a padne to na chybe.
Což bejvá žádoucí.

Bezne sa to robi cez job. kazdych xx minut si urobi select novych zaznamov a tie vlozi. ked by druha db padla, alebo spojenie na nu, tak sa nic nedeje, data sa dotiahnu neskor, ked sa obnovi funkcnost.
Což naopak nemusí být žádoucí.

483
Vývoj / Re:Kotlin nebo Scala pro backend?
« kdy: 04. 11. 2020, 11:28:28 »
Jenže tam chybí nějaký cíl, něco, co by to zastřešilo, dalo to jazyku nějaký smysl. U Javy, Scaly, Go, C++, Rustu, C, JavaScriptu, TypeScriptu, Pythonu, Perlu nebo PHP dokážu ten jazyk charakterizovat jednou větou. V případě Kotlinu to nedokážu – resp. jedna věta by byla o tom, jak Kotlin vznikl, ne k čemu je určen.

Kotlin je určen ke všemu, k čemu je určena java. Má mít kompaktnější syntax (properties, data classes, switch expressions, lambdy, type inference, template strings....  něco z toho se později dostává do javy..). Má být bezpečnější pro "průmyslové použití" tj návrhem preventivně bránit částým chybám (null safe calls, == vs ref. equality..). "Průmyslové použití" pro mne znamená  velký projekt, kde kód píše hodně lidí s různými úrovněmi znalosti.  Zároveň, do třetice, ten jazyk má být jednoduchý na naučení (ne o moc složitější než java) a kód v něm má být dobře udržovatelný (jako v javě). Takže se právě naopak chce vyhnout zbrklému přidávání features stylem "kočička pejsek".
A řekl bych, že úspěšně.

484
Vývoj / Re:Kotlin nebo Scala pro backend?
« kdy: 04. 11. 2020, 00:58:34 »
hrozne tristi sily a pokroku to spis skodi nez prospiva

A v čem by sis teda představoval ten pokrok? Aby to dle tvého nebylo plejtvání?

Scala, Kotlin, Rust jsou následovníci Java, Python.
Java, Python jsou následovníci C, C++, Basic, Pascal
C je následovník Assembleru.

Můj děda programoval u IBM v kolíčcích, a nad Assemblerem ohrnoval nos.

485
Kód: [Vybrat]
fn div (a: Int, b: Int) -> Result Int String
if b == 0 then
Fail ("Dělení nulou")
end
Succes (a / b)

match a <- div(42, a):
Fail msg -> print(msg)
_ -> print(a)



Kód: [Vybrat]
fn div (a: Int, b: Int) -> throw Int
if b == 0 then
throw Error ("Dělení nulou")
end
a / b

try:
print(div(42, a))
catch e:
print(e)

To je skutečný jazyk nebo nějaký funkcionální pseudokód?

Pseudokód. Mix Swiftu, Rustu a TypeScriptu.

486
Teď se Ti myslím povedla demonstrace jedné ze skutečných výhod výjimek, která ale může fungovat asi jenom v dynamických jazycích typu Pythonu - ten context manager pozná výjimku podle parametru, který ji identifikuje.

Jinak je to věc, která se dá řešit destruktorem při výstupu z rozsahu platnosti proměnné - třeba v Rustu se udělá drop v opačném pořadí (vzhledem k pořadí definice proměnné) automaticky a je vymalováno taky.

Obávám se, že rozhodně nemohu souhlasit. Už jsem tu toto téma někdy rozebíral, žel neúspěšně. Má aktuální úroveň poznání mi říká, že dynamické jazyky nepřináší nic co by principielně nešlo ve statických jazycích (a stáli bychom o to). Každopádně, asi zůstaňme u tématu.

Principiálně ano. Přemýšlím, jak by se to dělalo v C++. Pokud si pamatuju dobře, můžeš jako výjimku házet leccos, takže by maximálně šlo do exit metody poslat info, jestli výjimka byla nebo ne. U dynamických jazyků typu Pythonu je hodnota proměnné libovolná.

No ale zase, kdybychom měli k dispozici jenom bool, šlo by něco podobného i bez výjimek - třeba v Rustu. Tam se mi dokonce rýsuje i řešení s identifikací typu Erroru - pomocí downcastu by to mělo být možné vydolovat i z wrapperu, jaký dělá třeba anyhow! Tudíž asi musím vzít zpět svoje tvrzení o výhodě výjimky, protože podle všeho by to mělo jít postavit i nad Resultem - musel by se udělat příslušný trait (nebo změnit protokol Dropu) a jazyk by tomu musel vyjít vstříc.
Mnou poklamovaná jediná výhoda výjimek, ale zato zásadní - je čitelnost. Na úrovni kompileru a možností, a logiky, a bezpečnosti v následujících dvou příkladech není rozdíl:

Kód: [Vybrat]
fn div (a: Int, b: Int) -> Result Int String
if b == 0 then
Fail ("Dělení nulou")
end
Succes (a / b)

match a <- div(42, a):
Fail msg -> print(msg)
_ -> print(a)



Kód: [Vybrat]
fn div (a: Int, b: Int) -> throw Int
if b == 0 then
throw Error ("Dělení nulou")
end
a / b

try:
print(div(42, a))
catch e:
print(e)

487
Typy v C++ jsou hrubé, syntaxe je ošklivá, ale co do schopností jsou velmi mocné. C++ má jeden z nejsilnějších typových systémů ze všech mainstreamových jazyků. Kód ení moc hezký, ale principy jsou tam stejné jako ve zbytku světa. Takže prosím ignoruj jazyk a soustřeď se na principy. Ty jsou to o co mi jde.

Nenech se znérvóznit mou antipatií k C++. Je to přeci jen už dlouho, co jsem v něm dělal. :-)

Typy v Haskellu tohle moc neřeší. Jestli kus kódu může selhat nezávisí na jazyce, ale na tom, co ten kus kódu dělá. V Haskellu jsem toho napsal taky dost. Monáda ti ten "fail" bude propagovat nahoru úplně stejně neviditelně jako výjimky v c++. A v haskellu taky IMO nejde zaručit že kus monadického kódu ten fail nezavolá. A pure věci nakonec stejně musíš protlačit do toho stavového světa (nebo ten vnější RealWorld něčím prohnat ;) ).
Předpokládejme, že máme nějakou strukturu, jako to __exit__ u Pythoního with. Tvrdíš (a já nemám důvod nesouhlasit), že musíme zajistit, aby to __exit__ nevyhazovalo výjimku. OK. Co brání, aby v případě, že kompiler zjistí, že v něm je výraz, který výjimku 1) vyhazuje odmítl kód přeložit? (Odmysleme si, že teď lepím syntaxi z Pythonu, na typované myšlení z Haskellu.)

Tudíž nemohu souhlasit, že to Typy v Haskellu neřeší. Domnívám se, že naopak. Naopak!

Monáda ti ten "fail" bude propagovat nahoru úplně stejně neviditelně jako výjimky v c++.
Jak neviditelně?! Vždyť naopak, ty monády jsou v Haskellu největší pruda, protože jdou vidět moc.


A v haskellu taky IMO nejde zaručit že kus monadického kódu ten fail nezavolá.

Tady je nějaký zmatek v názvosloví.
Monáda nemůže selhat. Monáda nemůže zavolat fail. Monáda má množinu stavů, jeden z nich může být klasifikován jako chyba. Zaručený je tam všude všechno.

Moc ti teď bohužel nerozumím.



1) Výjimkou myslím klidně i Monádu, IOMonádu, Effects, cokoliv co bychom potřebovali.

488
Kód: [Vybrat]
# Python
with open('dog_breeds.txt') as src, threading.Lock(), db.connection() as con:
    con.insert(src.readlines())

(GoLang má defer, což je něco podobného ale hnusnějšího.)

Řekl bych, ty tak docela nepotřebuješ rozlišovat co může selhat a co ne. Jako spíše zajistit tu atomicitu.

Ten with řeší dvě věci, automaticky uzavřít zdroj, když něco selže, a rollback při chybě v bloku.

Tohle je zatím nejhezčí s čím jsem se setkal.

Teď se Ti myslím povedla demonstrace jedné ze skutečných výhod výjimek, která ale může fungovat asi jenom v dynamických jazycích typu Pythonu - ten context manager pozná výjimku podle parametru, který ji identifikuje.

Jinak je to věc, která se dá řešit destruktorem při výstupu z rozsahu platnosti proměnné - třeba v Rustu se udělá drop v opačném pořadí (vzhledem k pořadí definice proměnné) automaticky a je vymalováno taky.

Obávám se, že rozhodně nemohu souhlasit. Už jsem tu toto téma někdy rozebíral, žel neúspěšně. Má aktuální úroveň poznání mi říká, že dynamické jazyky nepřináší nic co by principielně nešlo ve statických jazycích (a stáli bychom o to). Každopádně, asi zůstaňme u tématu.



Já teď opravdu neřeším atomicitu, ale kusy kódu co zaručeně nemůžou selhat. I v jednom vlákně se ta transakčnost nedá zaručit pomocí with a podobných.
With, defer, tryWithResource a podobně umí jen to, co destruktory v c++ - zavolat kus kódu na konci bloku. (Taky se pomocí destruktorů dají celkem snadno implementovat). Pro tu transakci to nestačí. Např to with ještě potřebuje aby _každý_ resource uměl zaručeně neházející rollback (pomocí __exit__).

Svým kódem jsem se snažil ilustrovat tohle : Mám několik resourců, update každého může selhat a chci updatovat všechno nebo nic. Buďto můžu spočítat nový stav všech a pak je bez házení prohodit. Nebo můžu updatovat jeden po druhém, ale potřebuju možnost jak je bez házení vrátit zpět. Nevím, jak to udělat bez kusu kódu co zaručeně neselže.

Jádro je ten kus kódu co zaručeně nehází. Bez něho to AFAIK nejde. Destruktory, with, defer a podobné jsou jen bonus co ušetří mechanické bušení try-finally a podobného boilerplate kódu.

Kus kódu, který zaručeně nemůže selhat IMHO není problém. Třeba pomocí typů toho lze dosáhnout velice snadno (jsem ze světa Haskell, Rust, etc C++ je samozřejmě jinej případ). FP taky udělají hodně práce. Všechny tyhle požadované záruky ti kvalitní typový systém může dát (neříkám, že na 100%, ale nenechme se rozptylovat podrobnostmi). Chápu, proč to tak komentuješ. Protože C++. Typy C++ a typy v Rust, to je jako mít a nemít.

Já jsem řešil syntax. Ta mě zajímá. Zdá se, že v tomto se trochu míjíme, protože ty se zahrabáváš do implementačních detailů a ještě navíc v C++.

489
Mě víc zajímala ta syntaxe, jak si to @Jiří Havel představoval. Protože tam je IMHO ještě co objevovat a vylepšovat.
Já tu ale nepíšu o nějakých hypotetických nových jazycích. Já tu píšu o tom, jak se v c++ normálně píše kód se strong exception safety. Například mám třídu co má dvě dynamické pole stejné délky a metodu resize:
Kód: [Vybrat]
class Foo
{
private:
  std::unique_ptr<Bar[]> m_Bar;
  std::unique_ptr<Baz[]> m_Baz;
  size_t m_Size = 0;
public:
  void resize( size_t new_size )
  {
    std::unique_ptr bar( new Bar[new_size] ); // muze hodit
    std::unique_ptr baz( new Baz[new_size] ); // muze hodit
    // nějake kopirovani co muze hazet atd.

    // noexcept "commit" :
    m_Bar = std::move( bar ); // nebo swap( m_Bar, bar );
    m_Baz = std::move( baz );
    m_Size = new_size;
  }
}

O co mi šlo je, že ten házející a neházející kód se nijak neliší, takže při čtení od sebe nejdou poznat. Ty  výjimky prostě probublávají bez povšimnutí. A líbilo by se mi mít něco jako :
Kód: [Vybrat]
  void resize( size_t new_size )
  {
    std::unique_ptr bar( new Bar[new_size] ); // muze hodit
    std::unique_ptr baz( new Baz[new_size] ); // muze hodit
    // nějake kopirovani co muze hazet atd.

    noexcept {
      m_Bar = std::move( bar );
      m_Baz = std::move( baz );
      m_Size = new_size;
    }
[/quote]
Prostě říct překladači, kde nesmí nic lítat. A pokud bych tam zavolal něco co není noexcept tak aby to zahlásil.

Jinak podobnost se zmiňovanými funkcionálními myšlenkami není vůbec náhodná. Ten házející kód vytváří nový stav pokud možno s minimem vedlejších efektů. A viditelné vedlejší efekty se stanou v té commit fázi.

Což je si ale, přiznejme si, nic moc.

Kód: [Vybrat]
# Python
with open('dog_breeds.txt') as src, threading.Lock(), db.connection() as con:
    con.insert(src.readlines())

(GoLang má defer, což je něco podobného ale hnusnějšího.)

Řekl bych, ty tak docela nepotřebuješ rozlišovat co může selhat a co ne. Jako spíše zajistit tu atomicitu.

Ten with řeší dvě věci, automaticky uzavřít zdroj, když něco selže, a rollback při chybě v bloku.

Tohle je zatím nejhezčí s čím jsem se setkal.

490
Vývoj / Re:Kotlin nebo Scala pro backend?
« kdy: 02. 11. 2020, 16:19:56 »
... ale (to (je (pro ( mě (extrém)))) a myslím že i pro mnoho lidí.
To je mýtus.

491
Takže jsi myslel trasakčnost na úrovni jazyka a to včetně externích závislostí. Zajímavé.

Zajímavé je, jak by se něco takového provedlo v čistě funkcionálním kódu.

To mi moc zajímavé nepřijde. Funkcionální kód nemá efekty. Tudíž transakce je jednoduchá - zahodit ;-) (Tady trochu provokuju.)
No podle mě zas tak ne. Třeba v Haskellu je kód s efekty oddělený od kódu bez efektů. Takže by, teoreticky, napřed došlo k výpočtu finálního stavu a pokud by výpočet prošel, došlo by k jeho zápisu. Že by ten zápis byl chráněn transakcí, je jasné, ale to už by si ta low level část systému musela pohlídat sama...
To “zahodit” znamená, že výpočet se v monádě dostane na vedlejší kolej. Ten kód oddělený není, jen pracuje v rámci složitějšího typového systému. BoneFlute má pravdu, že to je v podstatě zdarma.
Však já polemizuju pouze s tím "Tady trochu provokuju". "kód oddělený není, jen pracuje v rámci složitějšího typového systému" - není to slovíčkaření? Prostě se ví, která funkce má efekty a která ne a dokud se výpočet dělá v bezefektové funkci, víme, že výsledek se může zahodit.
Možná jsem jen úplně nepochopil komentář o tom rozdělení.

Nicméně zajímavější jsou ty “efekty,” to s tím zahazováním je tedy rollback? A co je pak commit? Jakému typovému operátoru odpovídá? Podle mě je tohle všechno ve FP plně transparentní, ale možná mi něco uniká.

@Ink defakto přesně pochopil mou provokaci. (IO) Monády ve FP (nebo jakákoliv jejich alternativa) jsou přesně ta část jazyka, která není funkcionální. Tudíž nesplňuje zadání :-)

Vezmu-li čistě funkcionální kód, tak ten je v okamžiku kompilace "vyřešen" a neexistuje tam cesta jak něco může selhat. Tudíž předem vím, že 8 `div` 0 se nemůže vykonat, tudíž ho ani nevykonám, tudíž pro něj nejen že nealokuju paměť, já ho prostě budu ignorovat, vůbec nebude. Monády to celé trochu zamotávají, ale jinak fungují úplně stejně.

Pak je tam taková ta vazba mezi pure functional a zbytkem - ať už pomocí IOMonád, nebo Effects, nebo čehokoliv jiného. A tam to zase dostává na starost jazyk, aby se s tím popral -
Citace
ale to už by si ta low level část systému musela pohlídat sama.
.

Mě víc zajímala ta syntaxe, jak si to @Jiří Havel představoval. Protože tam je IMHO ještě co objevovat a vylepšovat.

492
Děkuji za příspěvek.

Na jednu stranu je to co píšeš dost inspirativní. Na druhou stranu si nejsem úplně jist, zda tě dobře chápu.

Cítím v tvém popisu defer z Go. Taky mi přijde, že mluvíš vlastně o určité podobě transakcí - kód změní stav, a pokud vznikne chyba, tak se vrátí původní stav. Je to to co myslíš? Jak se práce se stavem promítne do věcí jako side effects (zapisování do souboru, posílání emailu)? Nechtěl by si napsat nějakou ukázku kódu, jak by to mělo fugovat?

To co popisuješ, existuje to v nějakém jazyce, nebo je to jen studie/úvaha?

Dělal jsem si jednu studii, kdy jsem měl jazyk, který si jednak hlídal při kompilaci, zda jsou všechny scénáře pokryty, zda nemůže dojít k nějaké neošetřené chybě. A dále si při každém spuštění apky kontroloval, zda jsou dostupné externí závislosti (nainstalované knihovny, dostupné externí rutiny/binárky, dostupnost k databázi, filesystému). Čímž jsem chtěl zajistit, aby vlastní běh té aplikace nemohl selhat.
Jestli by měl z mého příspěvku být cítit nějaký jazyk, tak C++. O exception safety se primárně mluví právě v souvislosti s c++ i když je to obecnější koncept. Ale právě v c++ je tohle uvažování vcelku běžné. Strong exception safety jsou transakce, jen se neřeší atomičnost z pohledu jiných vláken.

Zápis do souboru jako transakce je myslím poměrně známý postup :
- Vytvořím pomocný soubor zapíšu ho a flushnu na disk. Pokud tohle selže, pak je původní soubor stále netknutý.
- Přejmenuju pomocný soubor. Pokud má tahle operace strong exception safety, pak ji bude mít i celý zápis souboru.

A stejně se dá uvažovat i o jednotlivých objektech programu. Např při přidávání do dynamického pole mi může selhat alokace, nebo kopírování nějakého objektu. Takže alokuju nový kus paměti, všechno do něj nakopíruju a nakonec swapnu odkaz na nový blok paměti.

Obecně pokud mám swap, který dokáže prohodit vnitřnosti objektů bez možných výjimek, pak se na tom dá stavět transakční chování pro větší a větší bloky programu. A dobrým zvykem je, pokud je to možné, dávat vlastním objektům rozumný swap který jen prohodí ukazatele a nemůže házet.
Takže jsi myslel trasakčnost na úrovni jazyka a to včetně externích závislostí. Zajímavé.
Zajímavé je, jak by se něco takového provedlo v čistě funkcionálním kódu.

To mi moc zajímavé nepřijde. Funkcionální kód nemá efekty. Tudíž transakce je jednoduchá - zahodit ;-) (Tady trochu provokuju.)

493
Děkuji za příspěvek.

Na jednu stranu je to co píšeš dost inspirativní. Na druhou stranu si nejsem úplně jist, zda tě dobře chápu.

Cítím v tvém popisu defer z Go. Taky mi přijde, že mluvíš vlastně o určité podobě transakcí - kód změní stav, a pokud vznikne chyba, tak se vrátí původní stav. Je to to co myslíš? Jak se práce se stavem promítne do věcí jako side effects (zapisování do souboru, posílání emailu)? Nechtěl by si napsat nějakou ukázku kódu, jak by to mělo fugovat?

To co popisuješ, existuje to v nějakém jazyce, nebo je to jen studie/úvaha?

Dělal jsem si jednu studii, kdy jsem měl jazyk, který si jednak hlídal při kompilaci, zda jsou všechny scénáře pokryty, zda nemůže dojít k nějaké neošetřené chybě. A dále si při každém spuštění apky kontroloval, zda jsou dostupné externí závislosti (nainstalované knihovny, dostupné externí rutiny/binárky, dostupnost k databázi, filesystému). Čímž jsem chtěl zajistit, aby vlastní běh té aplikace nemohl selhat.
Jestli by měl z mého příspěvku být cítit nějaký jazyk, tak C++. O exception safety se primárně mluví právě v souvislosti s c++ i když je to obecnější koncept. Ale právě v c++ je tohle uvažování vcelku běžné. Strong exception safety jsou transakce, jen se neřeší atomičnost z pohledu jiných vláken.

Zápis do souboru jako transakce je myslím poměrně známý postup :
- Vytvořím pomocný soubor zapíšu ho a flushnu na disk. Pokud tohle selže, pak je původní soubor stále netknutý.
- Přejmenuju pomocný soubor. Pokud má tahle operace strong exception safety, pak ji bude mít i celý zápis souboru.

A stejně se dá uvažovat i o jednotlivých objektech programu. Např při přidávání do dynamického pole mi může selhat alokace, nebo kopírování nějakého objektu. Takže alokuju nový kus paměti, všechno do něj nakopíruju a nakonec swapnu odkaz na nový blok paměti.

Obecně pokud mám swap, který dokáže prohodit vnitřnosti objektů bez možných výjimek, pak se na tom dá stavět transakční chování pro větší a větší bloky programu. A dobrým zvykem je, pokud je to možné, dávat vlastním objektům rozumný swap který jen prohodí ukazatele a nemůže házet.

Takže jsi myslel trasakčnost na úrovni jazyka a to včetně externích závislostí. Zajímavé.

Jak by vypadala syntaxe?

494
Pokud může házet úplně všechno, pak se dost blbě udržujou invarianty objektů. Daleko lepší je házející kus a pak commit co nic házet nesmí. Při čtení kódu ale jednoduše nepoznám, kde zrovna jsem.
Můžeš to prosím rozvést?
Myslel jsem konkrétně "strong exception safety". Takže operace buď projde, nebo se komplet rollbackne. To se obvykle dělá tak, že se spočítá celý nový stav a ten se pak swapne s tím starým. Výpočet nového stavu může házet podle libosti, ale swap nesmí. A teď jak zaručit že nic v tom swapu nehází.

Pokud může házet cokoliv, tak se dá maximálně dosáhnout "basic exception safety". Takže po vyhození výjimky nic neleakuje, ale stav je nějak změněný a musím si ho nějak vyresetovat. Jo, invarianty jednotlivých objektů jsou obvykle ok. To jsem napsal trochu blbě. Myslel jsem spíš něco jako návrat programu do stavu před (high level) operací, co tu výjimku vyhodila.

Takže problém je v tom, že potřebuju bloky kódu o kterých si můžu být jistý že nehází. Můžu zkontrolovat jednotlivé funkce a ověřit podle typu nebo dokumentace. Ale tuhle tupou mechanickou činnost bych rád nějak přehodil na překladač. Navíc to není při letmém čtení kódu nijak vidět. Můžu přidat komentář, který kus nehází, ale ten co do toho bude koukat po mně stejně neví, jestli tomu komentáři může věřit.
Ani checked exceptions to zas tak moc neřeší. U nich vím co může z funkce lítat, ale pokud chci vědět i odkud, tak musím hledat.

Zrovna chyby jsou místo, kde je pomoc překladače obzvlášť potřeba. Protože řešení chyb a nestandardních situací je vždycky ten nejmíň otestovaný a nejvíc zabugovaný kus projektu. A to díky tomu, že jsou ty situace vzácné.

Děkuji za příspěvek.

Na jednu stranu je to co píšeš dost inspirativní. Na druhou stranu si nejsem úplně jist, zda tě dobře chápu.

Cítím v tvém popisu defer z Go. Taky mi přijde, že mluvíš vlastně o určité podobě transakcí - kód změní stav, a pokud vznikne chyba, tak se vrátí původní stav. Je to to co myslíš? Jak se práce se stavem promítne do věcí jako side effects (zapisování do souboru, posílání emailu)? Nechtěl by si napsat nějakou ukázku kódu, jak by to mělo fugovat?

To co popisuješ, existuje to v nějakém jazyce, nebo je to jen studie/úvaha?

Dělal jsem si jednu studii, kdy jsem měl jazyk, který si jednak hlídal při kompilaci, zda jsou všechny scénáře pokryty, zda nemůže dojít k nějaké neošetřené chybě. A dále si při každém spuštění apky kontroloval, zda jsou dostupné externí závislosti (nainstalované knihovny, dostupné externí rutiny/binárky, dostupnost k databázi, filesystému). Čímž jsem chtěl zajistit, aby vlastní běh té aplikace nemohl selhat.

495
Ale kritika výjimek mě zajímá. Idris zmínil, že je pak těžší zajistit typovou bezpečnost, ok.
Jestli tě zajímá kritika výjimek, tak bych měl i další drobnost.

Výjimky IMO oddělují tu standardní a nestandardní cestu až moc dokonale. Jeden extrém je manuální ošetřování chyb furt dokola. Druhý extrém ale je, když při čtení kódu netuším, kde to může a nemůže vyletět.
OK, to beru. Tak v prvé řadě skutečnost, že nemusím odchytit potenciální chybu, a mohu ji bezmyšlenkovitě přenechat volajícímu, to je moc špatné. (Checked versus unchecked exceptions v javě.) Řekl bych, že tohle dělá hodně. I když to možná jde ještě líp, jak zmiňuješ tu přednášku.

Pokud může házet úplně všechno, pak se dost blbě udržujou invarianty objektů. Daleko lepší je házející kus a pak commit co nic házet nesmí. Při čtení kódu ale jednoduše nepoznám, kde zrovna jsem.
Můžeš to prosím rozvést?

Stran: 1 ... 31 32 [33] 34 35 ... 133