Pokud jsem to dobře pochopil, tak by to umožnilo mít např. Collection<int> namísto memory- a CPU-žravého Collection<Integer>.
Dále by to umožnilo nadefinovat např. typ ID, který by byl podkladově int (tedy primitivní typ s nejvyšší efektivitou), ale v kódu by nebylo možné ID zaměnit s jiným intem. Typicky při předávání parametrů do metod je riziko záměny ID s jiným intem (nebo longem) - stačí přehodit parametry - a kompilátor nemá šanci to odhalit. Takhle by šlo bez ztráty výkonu (v obou případech by se interně předával jen int) tyhle data od sebe bezpečně oddělit - užitečné i pro refaktoring, úpravy parametrů metod atd... Každá dodatečná ochrana na úrovni kompilátoru se počítá, je potřeba minimalizovat prostor pro chyby.
Jazyková rodina není to jediné, podle čeho se dají jazyky posuzovat. Java se drží principu, že samotný jazyk a jeho syntaxe má jen pár nejnutnějších věcí, a zbytek se dožene knihovnami nebo podporou generování kódu. Proto nemá Java např. speciální syntaxi pro listy, mapy, nemá přetížené operátory. Proto velmi dlouho neměla interpolované stringy, proto se lambda výrazy zaváděly tak opatrně. Proto neměla enumy a donedávna neměla recordy – a obojí bylo zavedeno jako „magie“ kompilátoru a překládá se to na standardní třídy. Zároveň Java velmi přísně dbá na zpětnou kompatibilitu.
Kotlin naproti tomu zpětnou kompatibilitu neřeší a co se týče „minimalismu“ jazyka, je na opačné straně, než Java – skoro platí, že na co se dá vymyslet syntactic sugar, na to Kotlin syntactic sugar má.
Oba přístupy mají své opodstatnění, oba si najdou své příznivce – a je nesmysl pokoušet se to míchat do jednoho jazyka, který by byl neslaný nemastný.
Mimochodem, to, že Java takhle vypadá a tím pádem se to odráží i v JVM, umožnilo, aby vůbec Kotlin/JVM vznikl. Kdyby Java měla v jazyce podporu pro kde co, nejspíš by to bylo i v JVM a pak pro Kotlin bylo velmi obtížné udělat to jinak. A týká se to i ostatních jazyků postavených nad JVM – ten jednoduchý základy Javy odrážející se v JVM umožnil vznik specializovaných jazyků nad JVM jako Groovy, Scala nebo právě Kotlin.
Chtít ve 21. století, aby se všechny číselné typy sčítaly operátorem + snad není přehnaný požadavek. To peklo je vycucané z prstu, kdo dokáže zamezit tomu, aby někdo vytvořil metodu add(), která odečítá nebo násobí? Co je na operátoru tak specifického, že se ho bojíme? Jenom to, že to někdo někdy odmítl nebo to neumí implementovat.
Chtít ve 21. století, aby se všechny číselné typy sčítaly operátorem + snad není přehnaný požadavek.
To vůbec nesouvisí se stoletím. Někomu vyhovuje sčítání číselných typů operátorem + i za cenu, že to někdo zneužije pro typy, které by jiní vůbec nepovažovali za číselné, nebo za cenu, že pro některé typy nebude + komutativní. Někomu zase vyhovuje, když je operátor + jednoduchá věc, na kterou se vždy může spolehnout, a záludnosti typu „dělá to něco jiného, než bych čekal“, si ponecháme až pro metody.
Mimochodem, když už se přetíží operátor * pro sčítání všech číselných typů, někoho možná napadne, proč nepřetížit i operátor *. A proč se omezovat na číslené typy na obou stranách, když třeba taková operace 6 * "ahoj" má také svůj význam.
ovsem + neni komutativni ani v Jave, ze? A taky se pouziva na necelociselne typy (a aby to bylo jeste "lepsi", tak jde o referencni typy).
V jakých případech není komutativní? Neceločíselné typy já řadím mezi číselné typy. Pro referenční typy se plus nepoužívá (s výjimkou toho Stringu) – možná vás mate to, že se nejprve dělá unboxing.
no je :) https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.18
to ze interne je to slozitejsi (unboxing + reseni strictfp a dalsi chutovky) neznamena, ze neni podporovan.
Ale pointa je jina - ta komutativita hodne hapruje celkove, obecne je docela tezke ji dosahnout
Prima. Tak si tu sekci teďka přečtěte. Zjistíte, že rozlišuje dva operátory – 1) operátor pro spojování řetězců a 2) operace pro sčítání a odčítání numerických typů. Přičemž pro numerické typy je komutativní, pokud operandy nemají vedlejší efekty. A nejprve se aplikuje unboxing, pak až operátor sčítání. Když máte metodu, která jako parametr dostává int, také nikdo netvrdí, že kompilátor na pozadí vytvoří přetíženou metodu akceptující Integer – pořád je tam jenom jedna metoda, jen kompilátor automaticky provede unboxing.
vyborne takze jsme si to precetli oba. O scitani numerickych typu je to tam napsano jinak - operator + je definovan pro hodnoty prevoditelne (unboxingem) na primitivni ciselne typ (coz je ovsem neco jineho nez to, ze je definovan pro primitivni ciselne typy). To zaprve (btw s tou metodou co uvadite je to naopak - pokud budu mit metodu akceptujici Integer, tak budu tvrdit, ze ta metoda akceptuje referencni typ!).
Zadruhe - pokud se podivame na definici pojmu "komutativita", tak to hapruje i u nekterych ciselnych typu v Jave.
Nikoli, operátor + (pro sčítání) je definován pro primitivní numerické typy. Ono by jaksi bylo zbytečné definovat ho pro referenční typy, když u nich kompilátor podle specifikace vždy nejprve provede unboxing, pokud se objeví jako operandy toho operátoru +. To, že se referenční typy mohou objevit jako operandy operátoru +, neznamená, že je pro ně operátor definován. (Kdyby byl, nemusí pro ně kompilátor provádět unboxing.) Je to stejně jako s tou metodou, jak jsem psal – metoda akceptující int (to není Integer) nemusí mít přetíženou metodu akceptující Integer, a ani žádnou takovou metodu nevyrobí kompilátor. Kompilátor prostě jen proveden unboxing, když je to potřeba.
Přímo v té vámi odkazované specifikaci je uvedeno, že operace sčítání numerických typů je komutativní (pokud operandy nemají vedlejší efekty, to je jasné). Takže pokud chcete rozporovat specifikaci, měl byste uvést nějaký důkaz, ne jen opakovat své tvrzení pořád dokola.
Zadruhe - pokud se podivame na definici pojmu "komutativita", tak to hapruje i u nekterych ciselnych typu v Jave.
Tak nebuď slušný a uveď příklad! Tohle miluji, někdo jen tak do tmy a pak několikrát opakuje, že to tak je, ale i přes žádost o uvedení přikladu to zopakuje. To neznamená, že ti nevěřím, ale ukázaná platí.
Jo, tohle není úplně dobrý příklad. Zaregistroval jsem i případ, kdy jistý matematický purista tohle porovnávání vs vracení dost řešil.
A propagaci NaNů, která je jednoznačně nekomutativní, Java nechává koňovi. Na nějaký payload se moc nehraje. Využít ho moc nejde, ale to v jazyce co zahodil i uint to není nějaké velké překvapení.
Tak to me mrzi, ze je to hloupe, kdyz to presne muzeme napasovat na definici komutativity:
https://en.wikipedia.org/wiki/Commutative_property#Mathematical_definitions
A jak jsem psal to neni az tak problem + jako spis == u FP, ale porad bych si tedy v CS nertroufl rict, ze je to komutativni operace, kdyz to "for all x,y in S" neplati minimalne u 2^60 pripadu.
Akorát že v definici komutativity není nic o Javovském operátoru ==. Problém vidím v tom, že jste si místo „stejnosti“ jen tak dosadil operátor ==. Takže já bych zůstal u toho, že operace sčítání (numerických hodnot) v Javě je komutativní, protože nezáleží na pořadí, výsledek je pořád stejný.
Vedle toho tu máme operátor ==, u kterého pro hodnoty NaN není možné říci, které chování je jediné logické – takže si autoři Javy museli jedno chování vybrat, tedy je to věc, kterou si musíte nastudovat, jak to v Javě funguje.
No právě proto to vytáhl. Jako příklad že vaše "že to někdo zneužije pro typy, které by jiní vůbec nepovažovali za číselné" už v Javě je i bez nějakého přetěžování.
Jinak "číselný typ" je trochu vágní pojem a krásné téma na flame. String je přímo ukázkový monoid, takže operátor + tu sedí jak prdel na hrnec. A podobných skvěle sčítatelných "nečíselných" typů není málo.
Tak si přečtěte ještě jednou tu citaci. Já jsem psal o číselných typech. Tj. operátor po spojování řetězců jsem dal úplně stranou. Operátor + se pro spojování řetězců používá tradičně, používá ho tak většina z jazyků, které žádné přetěžování operátorů neznají. Prostě je to jeden symbol použitý ve dvou významech, podobně jako kulaté závorky – jak už jsem psal.
"používá ho tak většina z jazyků, které žádné přetěžování operátorů neznají. Prostě je to jeden symbol použitý ve dvou významech," - je to jeden operator, ostatne ho takto popisuje i Java specification. A protoze je pouzit pro vice typu (stacilo by uz int a float), tak je to pretizeny operator jaksi z definice tohoto pojmu.
A vida - Javiste s tim nemaji problem, pouzivaji tento syntakticky cukr a to presto, ze je chovani + v Jave docela slozite.
Java zná dvě různé operace – spojování řetězců a sčítání numerických typů. Sám jste na příslušnou část specifikace odkazoval. Java nezná pojem „přetížený operátor“, takže těžko něco může splňovat tuto neexistující definici. A pokud byste chtěl použít nějakou obecnou definici přetíženého operátoru, zabřednete do spousty nejasností, třeba jestli „numerické typy“ může nebo nemůže být bráno jako jeden typ.
Plus se pro spojování řetězců používalo dávno před Javou. Ono zas tolik znaků na klávesnici nebylo. I když logičtější by bylo třeba &. || z SQL také není špatné. Ale, to, že za sčítání řetězců považujete jejich spojení, je dané jenom tím, že jste si na to zvykl. Klidně by to mohlo být třeba sčítání jejich bitových reprezentací.
Všimněte si, že jste vytáhl dva binární operátory.I když jste mohl klidně použít symbol, který je jinde použitý v úplně jiném významu. Treba Luovské ".." je pěkné.
Já bych řekl, že je to tím, že přetěžování operátorů je intuitivní a rozumné řešení. A jestli to slovo dokumentace používá je celkem jedno.
Jinak + je pro spojování řad velice intuitivní. Už školáci, když skládaji jablka vedle sebe, si to spojí se sčítáním. Ten & je tak logický, že bych si při překladu do češtiny musel dávat pozor, aby ta souvislost ten překlad vůbec přežila.
& jsme použil čistě jako symbol, nevybavuju si, jestli to nějaký jazyk používá pro spojování řetězců. || jsem uvedl jako příklad, kde už se to jako operátor spojení řetězců používá.
Nemyslím si, že by to většina programátorů z jazyků, které neznají přetěžování operátorů, vnímala jako přetěžování operátoru. Podle mne to vnímají tak, jak to popisuju já – jako dva různé způsoby použití jednoho znaku. Stejně jako třeba ty kulaté závorky.
Když školáci skládají jablka vedle sebe, spojí si se sčítáním počet jablek, ne jablka samotná. Žádný školák si nepředstaví, že když sčítáte jablka, dostanete na konci řadu slepených jablek.
Nevím, co je na spojce a nelogického – vždyť přesně tak se to v češtině (i angličtině) používá. „Vypište na výstup vedle sebe dvě slova, ‚ahoj‘ a ‚světe‘.“ Dokonce se naopak to a lidově používá pro sčítání – „dvě a tři je pět“.
Psal jste, že to & je logičtější. Takže jsem čekal že jste to někde viděl použíté. Mně by tenhle znak ani nenapadl a myslím, že nejsem sám.
No vidíte. Sám jste to napsal. To & dává smysl jen pokud ho četete tak, že by tam mohlo být i +. Zkuste "a zároveň" nebo něco jiného, co by sčítání být nemohlo, a podobnost s konkatenací řetězců je pryč. Přesně proto jsem vytahoval problém s překladem do češtiny.
Jinak k tomu, že to někdo nemusí vnímat jako přetěžování operátorů mě napadá podobnost s jistým sprostým M-slovem. Tam se programátoři obvykle podělají hrůzou a pak jim dojde, že už to vlastně dávno používají.
9. 10. 2023, 11:05 editováno autorem komentáře
Význam znaku v běžné řeči je ovšem „and“ nebo česky „a“, žádné „a zároveň“. Firma „Novák&syn“ je firma „Novák a syn“, ne „Novák a zároveň syn“. Stejně tak se v běžné řeči pro skládání věcí dohromady běžně používá slovo „a“ („and“ v angličtině), „plus“ má odborný význam. Neříkáte „byl tam Petr plus Pavel plus Lucie“, ale „byl tam Petr, Pavel a Lucie“, případně „byl tam Petr a Pavel a Lucie“. Nebo „kup housky a mléko“, ne „kup housky plus mléko“.
Proto by bylo & logičtější, protože je to přenesení významu toho znaku z běžné řeči do programovacího jazyka. Rozhodně to dává pro spojování řetězců větší smysl než +.