Ideálny programovací jazyk

Re:Ideálny programovací jazyk
« Odpověď #330 kdy: 16. 05. 2019, 18:15:02 »
Což ale dělá úplně něco jiného než porovnání referencí. To je typový problém. Hrušky a jabka.
V tom příkladu bylo uvedeno, že dlouhý kód může způsobit, že programátor použije chybný operátor a kompilátor mu v tom nezabrání. Tohle je přesně ten případ. Proč je použití toho operátoru chybné je jedno. Navíc oba dva případy jsou o tom, že programátor si myslel, že porovnává jeden typ (int), ale ve skutečnosti porovnával jiný typ. To je podstat toho příkladu. Jestli místo intu porovnává reference, float nebo double je úplně jedno, protože ve všech třech případech nelze pro porovnání hodnoty použít operátor == (i když v prvním případě z jiného důvodu než ve druhých dvou).

Obávám se, že jsem právě odstartoval další diskusi na 200 příspěvků, kde mne budou všichni přesvědčovat, že porovnávat floaty na rovnost je přece úplně normální.

WTF  :o


Re:Ideálny programovací jazyk
« Odpověď #331 kdy: 16. 05. 2019, 18:20:02 »
Pohádka? Spíš absurdní komedie říznutá špatným tripem. Furt se tu opakuje, že je to častá chyba, protože je to pro programátory matoucí. A vy teď napíšete že to není opravdová chyba, že jsou jenom programátoři zmatení. Kde seženu ten matroš? ::)
Aby to bylo pro čtenáře jednodušší, vzal jsem ty body v tom pořadí, jak jsou na obrázku. 1. bod – skutečná chyba. 2. bod – programátoři jsou z něčeho zmatení. 3. bod – skutečná chyba a  zároveň věc, kterou tu řešíme. Nic o zmatení u třetího bodu, který tu řešíme, jsem nepsal. Zpochybnil jsem ten seznam „nejčastějších chyb“ – když půlka věcí je něco, co ani nejde zkompilovat, těžko to vzniklo analýzou existujícího kódu. Takže to není žádný seznam získaný měřením, je to jen něčí dojem.
Proč by ten seznam musel vzniknout analýzou existujícího kódu? Stejně tak mohl vzniknout na základě pozorování bandy juniorů. Když začátečníci dělají pravidelně něco, kvůli čemu se jim kód nezkompiluje, tak to nejsou chyby? Co to teda je?

IMO, když to odchytí kompiler, tak to není zákeřná past. Ale chyba je to furt.


Re:Ideálny programovací jazyk
« Odpověď #332 kdy: 16. 05. 2019, 18:21:33 »
V tom příkladu bylo uvedeno, že dlouhý kód může způsobit, že programátor použije chybný operátor a kompilátor mu v tom nezabrání.
Já souhlasím, že je to problém. C++ umožnuje porovnávat float a double a přiřazovat do nich integery. Je to špatný design, C++ je zastaralé. Java je v tom špatném designu ještě dál než C++ a operátor ==  v Javě někdy porovnává hodnoty a jindy reference podle kontextu. Je to prostě blbě. Jak by to mělo vypadat správně?
Kód: [Vybrat]
    let a : f32  = 2147483647;
    let b : f64 = 2147483647;
    println!("{}", a == b);
Rust mi řekně hned 3x, že dělám 3 prasárny a opravdu to není dobrý nápad:
Kód: [Vybrat]
error[E0308]: mismatched types
 --> src/main.rs:2:20
  |
2 |     let a : f32  = 2147483647;
  |                    ^^^^^^^^^^ expected f32, found integral variable
  |
  = note: expected type `f32`
             found type `{integer}`

error[E0308]: mismatched types
 --> src/main.rs:3:19
  |
3 |     let b : f64 = 2147483647;
  |                   ^^^^^^^^^^ expected f64, found integral variable
  |
  = note: expected type `f64`
             found type `{integer}`

error[E0308]: mismatched types
 --> src/main.rs:4:25
  |
4 |     println!("{}", a == b);
  |                         ^ expected f32, found f64

Re:Ideálny programovací jazyk
« Odpověď #333 kdy: 16. 05. 2019, 18:22:24 »
V tom popisu ale není nic o tom, že se ty hodnoty mají porovnávat operátorem ==.
Mně už zbývá v hlavě jediná otázka: připomíná mi tohle spíš Havla nebo Goebbelse? Nějak se nemůžu rozhodnout.
Já vám pomůžu – zkuste si do češtiny přeložit tyhle dvě věty (uznávám, je to docela dlouhé):

Citace
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1), or the boolean literal true or false (§3.10.3), or a character literal between '\u0000' and '\u007f' inclusive (§3.10.4), then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.

Bude fajn, když se o ten překlad podělíte s ostatními, abychom věděli, o čem se tady podle vás bavíme.

Nebo samozřejmě můžete v té citaci zkusit najít jinou část, kde se mluví o operátoru ==.

Re:Ideálny programovací jazyk
« Odpověď #334 kdy: 16. 05. 2019, 18:38:36 »
Java je v tom špatném designu ještě dál než C++ a operátor ==  v Javě někdy porovnává hodnoty a jindy reference podle kontextu. Je to prostě blbě.
Ano, Java opravdu porovnává podle kontextu. Když dostane hodnoty, porovnává hodnoty. Když dostane reference, porovnává reference. Stejně jako C, které když dostane hodnoty, porovnává hodnoty, když dostane pointery, porovnává pointery, a když dostane hodnotu a pointer, klidně je také porovná. Když Java dostane hodnotu a referenci, kompilátor zařve. Pravda, poslední věc se změnila s i implementaci autoboxingu/unboxingu, kdy kompilátor nejprve zkusí provést autoboxing/unboxing a zařve teprve, když to není možné.

Takže je chyba v autoboxingu/unboxingu? Než se zavedl, byly diskuse plné komentářů o tom, jak je Java zastaralá a ukecaná a jako příklad se často objevovalo právě převádění mezi „malými“ a „velkými“ typy. Takže se zavedl autoboxing a autounboxing. Jak byste to řešili vy? Zakázali boxing u operátoru ==? Rozbili zpětnou kompatibilitu a zakázali úplně operátor == pro reference? Nebo jinak?

Rust mi řekně hned 3x, že dělám 3 prasárny a opravdu to není dobrý nápad:
Po dlouhé době něco, s čím mohu souhlasit.


Re:Ideálny programovací jazyk
« Odpověď #335 kdy: 16. 05. 2019, 18:53:55 »
Stejně jako C, které když dostane hodnoty, porovnává hodnoty, když dostane pointery, porovnává pointery, a když dostane hodnotu a pointer, klidně je také porovná.

No jistě, protože porovnává adresu - hodnotu v pointeru. :D

Když dostane pointer a hodnotu, tak ti vynadá kompilátor.

Re:Ideálny programovací jazyk
« Odpověď #336 kdy: 16. 05. 2019, 19:01:52 »
Ano, Java opravdu porovnává podle kontextu. Když dostane hodnoty, porovnává hodnoty. Když dostane reference, porovnává reference. Stejně jako C, které když dostane hodnoty, porovnává hodnoty, když dostane pointery, porovnává pointery, a když dostane hodnotu a pointer, klidně je také porovná. Když Java dostane hodnotu a referenci, kompilátor zařve. Pravda, poslední věc se změnila s i implementaci autoboxingu/unboxingu, kdy kompilátor nejprve zkusí provést autoboxing/unboxing a zařve teprve, když to není možné.

Takže je chyba v autoboxingu/unboxingu? Než se zavedl, byly diskuse plné komentářů o tom, jak je Java zastaralá a ukecaná a jako příklad se často objevovalo právě převádění mezi „malými“ a „velkými“ typy. Takže se zavedl autoboxing a autounboxing. Jak byste to řešili vy? Zakázali boxing u operátoru ==? Rozbili zpětnou kompatibilitu a zakázali úplně operátor == pro reference? Nebo jinak?
Je potřeba dívat se na to v historickém kontextu. Java vypadá tak, jak vypadá, kvůli rozhodnutím z minulosti (primitivní typy, boxing/unboxing...) a držení zpětné kompatibility. To není kritika, byl to prostě historický výjoj. Kdyby se dělala Java znovu od nuly, určitě by vypadala jinak než teď. Stejně jako by vypadalo jinak i C, kdyby se dělalo znovu od nuly. Ale obojí je nereálné, Java i C jsou etablované jazyky a nová Java ani nové C nebude, existující kód nikdo přepisovat nechce.

Jenomže ten historický vývoj nutně vedl ke kompromisům v designu jazyka, Java (stejně jako C(++)) si s sebou táhne spoustu špatných věcí z minulosti. A tahkle je to taky potřeba vnímat, operátor == je v Javě neintuitivní a špatně použitelný, snadno vznikne chyba. Takže je potřeba každému nováčkovi říct "Hele, dávej si pozor na operátor ==, protože nefunguje tak, jak bys čekal, dělají se v tom často chyby. Někdy to porovnává hodnoty, jindy reference, záleží na kontextu, pravidla jsou složitá. Radši to vůbec nepoužívej, když nebudeš muset". No a to je všechno, není potřeba to nějak víc řešit.

Re:Ideálny programovací jazyk
« Odpověď #337 kdy: 16. 05. 2019, 19:15:11 »
No jistě, protože porovnává adresu - hodnotu v pointeru. :D
Stejně jako při porovnání referencí v Javě, kdy se také porovnává adresa – hodnota v referenci.

Když dostane pointer a hodnotu, tak ti vynadá kompilátor.
Nikoli.

Re:Ideálny programovací jazyk
« Odpověď #338 kdy: 16. 05. 2019, 19:19:45 »
Je potřeba dívat se na to v historickém kontextu. Java vypadá tak, jak vypadá, kvůli rozhodnutím z minulosti (primitivní typy, boxing/unboxing...) a držení zpětné kompatibility. To není kritika, byl to prostě historický výjoj. Kdyby se dělala Java znovu od nuly, určitě by vypadala jinak než teď. Stejně jako by vypadalo jinak i C, kdyby se dělalo znovu od nuly. Ale obojí je nereálné, Java i C jsou etablované jazyky a nová Java ani nové C nebude, existující kód nikdo přepisovat nechce.

Jenomže ten historický vývoj nutně vedl ke kompromisům v designu jazyka, Java (stejně jako C(++)) si s sebou táhne spoustu špatných věcí z minulosti. A tahkle je to taky potřeba vnímat, operátor == je v Javě neintuitivní a špatně použitelný, snadno vznikne chyba. Takže je potřeba každému nováčkovi říct "Hele, dávej si pozor na operátor ==, protože nefunguje tak, jak bys čekal, dělají se v tom často chyby. Někdy to porovnává hodnoty, jindy reference, záleží na kontextu, pravidla jsou složitá. Radši to vůbec nepoužívej, když nebudeš muset". No a to je všechno, není potřeba to nějak víc řešit.
Kdybyste si nalistoval diskusi asi tak pět stran zpět, psal jsem tam to samé :-) Teda až na to, že nesouhlasím, že pravidla jsou složitá – jsou naopak velmi jednoduchá, když se porovnávají primitivní typy, porovnávají se hodnoty (nic jiného porovnat nejde), když se porovnávají objektové typy, porovnávají se reference (protože objekt je pro Javu blackbox, neví nic o tom, jestli existuje něco jako hodnota toho objektu).

Re:Ideálny programovací jazyk
« Odpověď #339 kdy: 16. 05. 2019, 19:22:57 »
Kdybyste si nalistoval diskusi asi tak pět stran zpět, psal jsem tam to samé :-) Teda až na to, že nesouhlasím, že pravidla jsou složitá – jsou naopak velmi jednoduchá, když se porovnávají primitivní typy, porovnávají se hodnoty (nic jiného porovnat nejde), když se porovnávají objektové typy, porovnávají se reference (protože objekt je pro Javu blackbox, neví nic o tom, jestli existuje něco jako hodnota toho objektu).
Ne ty tady od začátku píšeš, jak je porovnání v Javě udělané skvěle, jednoduše, každý to hned pochopí a chyby se v tom nedělají. To je prostě demagogie, obhajuješ špatný design, pravděpodobně z neznalosti.

Re:Ideálny programovací jazyk
« Odpověď #340 kdy: 16. 05. 2019, 19:24:05 »
Když dostane pointer a hodnotu, tak ti vynadá kompilátor.
Nikoli.
-Wzero-as-null-pointer-constant

BoneFlute

  • *****
  • 2 046
    • Zobrazit profil
Re:Ideálny programovací jazyk
« Odpověď #341 kdy: 16. 05. 2019, 19:30:44 »
Bazírovat na tom můžete, smutné je, že nemáte pravdu.

Kód: [Vybrat]
class Integer:
    def __init__(self, value):
        self.value = value

a = Integer(1024)
b = Integer(1024)
print(a == b) #False
Co jsem udělal? Vzal jsem ten původní kód, který rozpoutal celou debatu. Kód, který se údajně v Javě chová úplně nemožně. Napsal jsem to samé v Pythonu, který se prý chová úplně jinak. A výsledek je co? Výsledek je naprosto stejný.

Python se chová přesně tak, jako se chová Java, dělá přesně to, co kritizujete.

Jistě budete argumentovat tím, že v Pythonu to můžete dál vylepšovat. Můžete do třídy dopsat přetížení operátoru:
Kód: [Vybrat]
def __eq__(self, other):
    return self.value == other.value
Ano, můžete. V Javě to také můžete dál upravovat, můžete přetížit metodu equals() (resp. ve třídě java.lang.Integer už ta metoda dávno přetížená je).

Zase špatně: Výsledek není stejný. Python se nechová jako Java. https://gist.github.com/BoneFlute/6c9f56a6b4c164b2fc2f246662daa7a8

Re:Ideálny programovací jazyk
« Odpověď #342 kdy: 16. 05. 2019, 19:31:05 »
Když dostane pointer a hodnotu, tak ti vynadá kompilátor.
Nikoli.
Jak by řekl klasik: Tak to tady asi máte nějaký zkažený vzduch!

Kód: [Vybrat]
$ cat test.c
#include <stdio.h>

int main() {
  int a;
  int *ap;

  if(ap != 1) {
    puts("nerovna!");
  }

  if(ap != a) {
    puts("nerovna!");
  }

  return 0;
}

$ gcc test.c
test.c:7:9: warning: comparison between pointer and integer ('int *' and 'int')
  if(ap != 1) {
     ~~ ^  ~
test.c:11:9: warning: comparison between pointer and integer ('int *' and 'int')
  if(ap != a) {
     ~~ ^  ~
2 warnings generated.

Re:Ideálny programovací jazyk
« Odpověď #343 kdy: 16. 05. 2019, 19:34:39 »
Ne ty tady od začátku píšeš, jak je porovnání v Javě udělané skvěle, jednoduše, každý to hned pochopí a chyby se v tom nedělají. To je prostě demagogie, obhajuješ špatný design, pravděpodobně z neznalosti.
Demagogie je vkládat mi do úst něco, co jsem nikdy nenapsal. Nikdy jsem nepsal, že je to skvělé. Napsal jsem, že je to jednoduché, a na tom trvám. Že to každý hned pochopí jsem nepsal – psal jsem, že je to jedna z prvních věcí, které se programátor v Javě musí naučit. Že se v tom chyby dělají málokdy jsem napsal a také na tom trvám.

Váš názor, že je to špatný design, vám neberu, ale nesdílím ho. Když vyjdu z předpokladů, že Java má primitivní typy (což je dané historicky a není reálné to v dohledné době změnit) a zároveň nemá přetěžování operátorů (což je záměr, přispívá to k tomu, aby jazyk jako takový byl jednoduchý a předvídatelný), vychází mi z toho, že o dost lepší řešení neexistuje. O něco lepší by bylo operátor == pro objekty úplně zakázat, ale to opět bylo v době vzniku Javy nemyslitelné.

Pokud máte lepší řešení, které splňuje výše uvedené předpoklady, sem s ním. Pokud si myslíte, že některý z těch předpokladů není nutné dodržet, můžete k tomu předložit nějaké argumenty.

Re:Ideálny programovací jazyk
« Odpověď #344 kdy: 16. 05. 2019, 19:36:21 »
Když dostane pointer a hodnotu, tak ti vynadá kompilátor.
Nikoli.
Jak by řekl klasik: Tak to tady asi máte nějaký zkažený vzduch!
„Vynadá“ jsem chápal tak, že to vůbec nepůjde přeložit. Protože když v Javě porovnáváte reference pomocí ==, také dostanete varování. Takže v tom rozdíl nevidím.