Ideálny programovací jazyk

Re:Ideálny programovací jazyk
« Odpověď #255 kdy: 15. 05. 2019, 22:29:33 »
A za třetí při porovnání referencí  vás bude varovat IDE, protože je to opravdu jen výjimečná operace a takové použití spíš vypadá na chybu.
Tohle beru jako rozumné řešení problému - upozornění, že by to mohla být blbost, to rozumného programátora (i začínajícího) trkne. 
To by teprve byl zmatek, kdyby se objekty někdy porovnávaly podle reference a někdy podle hodnoty.
Je to jen aplikace unboxingu konkrétních typů na další operátor. Když se to může dít  při jiných operacích (přiřazování, vkládání parametrů), je jen věcí dohody, že se to může dít i při porovnávání.


Re:Ideálny programovací jazyk
« Odpověď #256 kdy: 15. 05. 2019, 22:40:17 »
To by teprve byl zmatek, kdyby se objekty někdy porovnávaly podle reference a někdy podle hodnoty.
Neřešíme už tu několik stránek to, že přesně tohle se v Javě děje? Vestavěné typy se porovnávají podle hodnoty a naše podle reference. ::)

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Ideálny programovací jazyk
« Odpověď #257 kdy: 15. 05. 2019, 22:45:46 »
Co třeba zlomky? Ostatně problém jsou i ty řetězce – jsou řetězce „č“ a „č“ stejné? Jsou? A neměly by stejné řetězce mít stejný počet znaků? První má jeden znak, druhý dva…
To jsou z prstu vycucané pseudoproblémy. U zlomků by jeden očekával algebraickou rovnost (u floatu se taky rovná 1.2 a 1.2000000, pokud na ně tedy neudělám napřed toString(), hejže?). Řetězce se většinou porovnávají jednoduše jako pole bytů, tedy typicky unicode (8 nebo 16). Pokud někdo řeší složitou typografii, určitě může použít sofistikovanější knihovnu pracující s glyfy, ligaturami apod., ale každý chápe, že to je speciální případ. Ostatně moderní jazyky to takto mají právě z toho důvodu, že to dává největší smysl.

Re:Ideálny programovací jazyk
« Odpověď #258 kdy: 15. 05. 2019, 22:55:39 »
Pokud implementuju zlomky, pak je to stejné.
A nebo různé, záleží na okolnostech. Třeba když budu implementovat systém pro matematickou sazbu (TeX), rozhodně nechci, aby mi klidně místo 2/4 vysázel 1/2, protože je to přece stejné.

Jsou stejné. Liší se počet bytů, ne znaků. Našemu pojmu znak (ve významu používaném v běžném životě) spíš odpovídá pojem grapheme cluster, které mají oba řetězce po jednom. Zase je to o tom, jestli chci pracovat s textem, nebo polem bytů a tohle už můžu odlišit na úrovni typového systému.
Neliší se jen počet bytů, liší se i počet znaků. V první textu je jeden znak „č“, v druhém textu jsou dva znaky – malé „c“ a za ním háček pro kombinování. Aby byly ty řetězce shodné i na počet znaků, musíte nejprve provést jejich normalizaci – pak budou opravdu na bit stejné. Ale opět – někdy nechcete provádět žádnou normalizaci, někdy chcete provádět standardní normalizaci Unicode, a někdy chcete řetězce porovnávat třeba bez ohledu na velikost písmen a na diakritiku.

Je to jen aplikace unboxingu konkrétních typů na další operátor. Když se to může dít  při jiných operacích (přiřazování, vkládání parametrů), je jen věcí dohody, že se to může dít i při porovnávání.
Unboxing se neaplikuje na operátory, ale na výskyt konkrétních hodnot (konstant nebo proměnných). A unboxing se v Javě nikdy nedělá svévolně, že by kód byl validní i bez unboxingu, ale kompilátor se rozhodl, že typy změní. Autoboxing/unboxing se aplikuje jedině v případě, že daný kód nejde přeložit, ale aplikováním boxingu/unboxingu přeložit půjde. Tedy se aplikuje jenom tam, kde je ve zdrojovém kódu nesoulad typů, např. máte metodu, která má jako parametr velký Integer, ale cpete do něj malý int. Na kódu Integer == int se uplatní, protože jinak by to nešlo přeložit. Integer == Integer je ale validní javovský kód, a kompilátoru nepřísluší hodnotit, jak moc je takový kód pravděpodobný.

Re:Ideálny programovací jazyk
« Odpověď #259 kdy: 15. 05. 2019, 22:58:17 »
Tak se jeste zeptam, abych vedel co je idealni  ;)

Clojure nema operatory, ale:
Mame funkci (=) , ktera porovnava hodnoty.
Funkci (identical?) , ktera porovnava reference.
A pak jeste specialne pro cisla funkci (==), ktera porovnava hodnoty nezavisle na typu.

Je to "idealni"?


Re:Ideálny programovací jazyk
« Odpověď #260 kdy: 15. 05. 2019, 23:01:01 »
Neřešíme už tu několik stránek to, že přesně tohle se v Javě děje? Vestavěné typy se porovnávají podle hodnoty a naše podle reference. ::)
Ne, neděje. Už jsem to psal několikrát, primitivní typy se porovnávají podle hodnoty, objekty se porovnávají podle reference. String je taky vestavěný typ, ale je to objekt, takže se porovnává podle reference. Java obecně se hodně snaží vyhýbat magii s vestavěnými typy a pojem „vestavěný typ“ se u Javy ani nepoužívá. Vlastně jediná „magie“, která mne napadá, je sčítání řetězců. Jinak se v Javě snad všechno tváří jako uživatelské typy – jako třídy, které by mohly být kompletně implementovány koncovým programátor.

Re:Ideálny programovací jazyk
« Odpověď #261 kdy: 15. 05. 2019, 23:08:53 »
U zlomků by jeden očekával algebraickou rovnost
Myslím, že kdybyste ve zdrojáku napsal 2/4 a TeX by vám to vysázel jako 1/2, velice rychle byste změnil názor.

u floatu se taky rovná 1.2 a 1.2000000, pokud na ně tedy neudělám napřed toString(), hejže?
Po té, co se začínající programátoři v druhé lekci dozví, jaký je rozdíl mezi hodnotou a referencí, a že objekty nikdy nemají porovnávat pomocí ==, hned ve třetí lekci se dozví, že floaty se nikdy neporovnávají na rovnost. float 1.2 se nerovná floatu 1.2000000. A to není žádná specialita Javy, tak to mají všechny jazyky, které používají čísla s plovoucí čárkou dle IEEE-754.

Ostatně moderní jazyky to takto mají právě z toho důvodu, že to dává největší smysl.
Problém je v tom, že někdy prostě nejde vybrat, co dává největší smysl. Uváděl jsem tu příklad s elementem z DOM XML – tam dávají stejný smysl všechny tři varianty. Porovnávat identitu, porovnávat název elementu a jmenný prostor, a porovnávat název elementu, jmenný prostor i prefix jmenného prostoru.

Re:Ideálny programovací jazyk
« Odpověď #262 kdy: 15. 05. 2019, 23:09:39 »
V tom poolu konstant žádný problém není – když chápete rozdíl mezi hodnotou a referencí, nemůžete hodnotu Integerů nikdy porovnávat pomocí ==.
Omyl. Můžu si myslet, že to má Java vyřešeno stejně dobře jako Erlang atomy. Napíšu si na to i unit testy, ale jako na potvoru tam použiju "malá" čísla. A na produkci se objeví "velká" čísla.

Byla to neznalost programátora? Ano.  Byla to chyba programátora? Ano.

Programátor si myslel, že konstrukci rozumí a dokonce to i byla pravda - chtěl porovnávat reference (!!!) ). Co neznal, byly internals implementace poolu "malých" hodnot.

Byl jazykem překvapen? Byl. Má ideální jazyk programátora překvapovat? Nemá.

Zopakuje Filip Jirsák po stopadesáté první, že někdo nechápe rozdíl mezi referencí a hodnotou a s poolem to nemá co dělat? Nevíme, ale je to velmi pravděpodobné.

protože operátory jsou vždy v nějakém případě kontraintuitivní
Můžete uvést příklad z Elixiru nebo Rustu?
Tak třeba Rust má spoustu operátorů, které nejsou vůbec intuitivní, to je problém sám o sobě.
Ok. A ten příkad teda?

protože u složitějších typů vždy narazíme na to, že prostě není jasné, co je to rovnost.
Nevím, proč bysme měli. Třídy ekvivalence mají být součástí definice typu. Jistě, jsou situace, kdy se dají nadefinovat různě. To už je na programátorovi, jak si je chce nadefinovat. Ale nevidím v tom sebemenší problém, natož abychom na něj "vždy naráželi".

Podívejte se třeba, jak má Haskell nadefinovanou třídu Eq. Problém je kde?
« Poslední změna: 15. 05. 2019, 23:15:04 od Mirek Prýmek »

Re:Ideálny programovací jazyk
« Odpověď #263 kdy: 15. 05. 2019, 23:13:07 »
Ztracim se. Prece se tu rikalo, ze problem neni v tom operatoru, ale v te kesi....
Filip má velmi efektivní selektivní vnímání ;)

Re:Ideálny programovací jazyk
« Odpověď #264 kdy: 15. 05. 2019, 23:29:20 »
Omyl. Můžu si myslet, že to má Java vyřešeno stejně dobře jako Erlang atomy. Napíšu si na to i unit testy, ale jako na potvoru tam použiju "malá" čísla. A na produkci se objeví "velká" čísla.

Byla to neznalost programátora? Ano.  Byla to chyba programátora? Ano.

Programátor si myslel, že konstrukci rozumí a dokonce to i byla pravda - chtěl porovnávat reference (!!!) ). Co neznal, byly internals implementace poolu "malých" hodnot.

Byl jazykem překvapen? Byl. Má ideální jazyk programátora překvapovat? Nemá.

Zopakuje Filip Jirsák po stopadesáté první, že někdo nechápe rozdíl mezi referencí a hodnotou a s poolem to nemá co dělat? Nevíme, ale je to velmi pravděpodobné.
Když ono to z vašich komentářů opravdu vypadá, že netušíte, o čem píšete.

Napsal jste, že programátor chtěl porovnávat reference. A pomocí == opravdu reference porovnává. Byla to neznalost programátora? Ne. Byla to chyba programátora? Ne. Fungoval mu program správně v testu s malými čísly? Ano. Fungoval mu správně na produkci s velkými čísly? Ano. Vracelo porovnání true, když byly reference stejné? Ano. Vracelo porovnání false, pokud byly reference jiné? Ano. Snažil se Mirek Prýmek popsat nějaký problematický příklad, a přitom popsal příklad, ve kterém je vše v pořádku, vše funguje správně a podle programátorova očekávání? Ano.

Jediná chyba tedy byla v tom, že jste si myslel, že je tam něco špatně. Takže mi z toho vychází akorát: Rozumí Mirek Prýmek rozdílu mezi hodnotou a referencí v Javě, rozumí tomu, jak funguje pool Integerů? Ne.

Další váš omyl je v tom, že píšete o jazyce. Pool Integerů není žádná vlastnost jazyka, je to normálně implementované ve třídě Integer (a podobně ve třídě String). Nic vám nebrání, abyste si takovou třídu napsal sám, občas se to používá.

Podívejte se do implementace metody Integer.valueOf(int), jak je to naprogramované. Celý ten zázrak má tři řádky:

Kód: [Vybrat]
if (i >= IntegerCache.low && i <= IntegerCache.high)
  return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);


Ok. A ten příkad teda?
Ten následoval hned po té části, kterou jste citoval.

Nevím, proč bysme měli. Třídy ekvivalence mají být součástí definice typu. Jistě, jsou situace, kdy se dají nadefinovat různě. To už je na programátorovi, jak si je chce nadefinovat. Ale nevidím v tom sebemenší problém, natož abychom na něj "vždy naráželo".
Ano, takže jste sám potvrdil, že intuitivnost ekvivalence naráží na to, že pro stejné typy dávají smysl různé třídy ekvivalence. Můžete si sice nadefinovat, že Zlomek1 porovnává zlomek po převedení do základního tvaru a Zlomek2 porovnává zlomky tak, jak jsou, ale intuitivní to není. A pak si ještě zkusíte porovnat Zlomek1 se Zlomkem2, a vzápětí Zlomek2 se Zlomkem1, a máte z toho pořádný guláš.

Re:Ideálny programovací jazyk
« Odpověď #265 kdy: 15. 05. 2019, 23:30:24 »
Filip má velmi efektivní selektivní vnímání ;)
Nikoli, já pouze vím – na rozdíl od vás – jak to funguje.

Re:Ideálny programovací jazyk
« Odpověď #266 kdy: 15. 05. 2019, 23:37:45 »
Ještě abyste pochopil ten rozdíl:

Kód: [Vybrat]
assert !(new Integer(1) == new Integer(1));
boolean b = Integer.valueOf(1) == Integer.valueOf(1);
assert b || !b;

Na prvním řádku se vytvářejí dvě instance, musí to tedy být dvě různé reference. Operátor == u objektů porovnává reference, takže rovnost na prvním řádku nikdy nemůže být splněna.

Na druhém řádku se volá statická metoda, ta mi vrátí nějakou referenci. Nikde není řečeno, zda pro stejné hodnoty to bude vracet jeden objekt nebo dva různé objekty. V té metodě klidně může být orákulum, které vám v polovině případů bude vracet objekt z poolu a v druhé polovině případů nové instance. Takže o té rovnosti nelze bez znalosti konkrétní implementace rozhodnout, zda platí nebo neplatí.

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Ideálny programovací jazyk
« Odpověď #267 kdy: 15. 05. 2019, 23:43:45 »
U zlomků by jeden očekával algebraickou rovnost
Myslím, že kdybyste ve zdrojáku napsal 2/4 a TeX by vám to vysázel jako 1/2, velice rychle byste změnil názor.
Tohle je nesmírně hloupý příklad, v TeXu není žádný typ zlomek, \frac{a}{b} je AST jako každý jiný, TeX zlomky nijak nevyhodnocuje  ::)

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Ideálny programovací jazyk
« Odpověď #268 kdy: 15. 05. 2019, 23:47:15 »
Omyl. Můžu si myslet, že to má Java vyřešeno stejně dobře jako Erlang atomy. Napíšu si na to i unit testy, ale jako na potvoru tam použiju "malá" čísla. A na produkci se objeví "velká" čísla.

Byla to neznalost programátora? Ano.  Byla to chyba programátora? Ano.

Programátor si myslel, že konstrukci rozumí a dokonce to i byla pravda - chtěl porovnávat reference (!!!) ). Co neznal, byly internals implementace poolu "malých" hodnot.

Byl jazykem překvapen? Byl. Má ideální jazyk programátora překvapovat? Nemá.

Zopakuje Filip Jirsák po stopadesáté první, že někdo nechápe rozdíl mezi referencí a hodnotou a s poolem to nemá co dělat? Nevíme, ale je to velmi pravděpodobné.
Když ono to z vašich komentářů opravdu vypadá, že netušíte, o čem píšete.
Tentokrát tuší, resp. ví docela přesně. Jen nějaký Jirsák tady jako modlitební mlýnek opakuje pořád dokola pár naučených frází, aniž by jim rozuměl  ;)

Idris

  • *****
  • 2 286
    • Zobrazit profil
    • E-mail
Re:Ideálny programovací jazyk
« Odpověď #269 kdy: 15. 05. 2019, 23:49:15 »
Filip má velmi efektivní selektivní vnímání ;)
Nikoli, já pouze vím – na rozdíl od vás – jak to funguje.
Určitě? :o