Ač tenhle folklor miluju, je nutné popravdě uznat, že to jsou všechno hračičky, protože se nikdy nepočítalo s tím, že by v takových jazycích někdo něco doopravdy programoval. Ale co takhle skutečné jazyky, které se běžně používají v reálných projektech? Je to jistě koledování si o flamewar, ale holt do toho skočím. Mí kandidáti na nejstrašnější reálný jazyk jsou:
- PHP
- Perl
- Java
Můj oblíbený sed také nemá příliš čitelný kód. Viz třeba sed calculator.
Perl 6 je nahodou velmi zaujimavy jazyk od zaciatku navrhnuty lingvistami. Da so v nom sice prasit to ano, ale to je dane jeho bohatou syntaxou... je to horuci kandidat na dalsi jazyk, ktory sa chcem naucit (ked bude viac casu).
https://en.wikipedia.org/wiki/Perl_6
Na abclinuxu o nom vychadza pekny serial http://www.abclinuxu.cz/blog/wamba/perl
Já mám jiný žebříček:
5. Assembler pro 8051, protože sedm!!! adresních prostorů už je hodně mimo.
4. ARM Assembler, protože u psaní si musí člověk ještě v druhé hemisféře bufferovat flagy, aby věděl, jestli se instrukce vůbec provede.
3. tcl, protože používá RPN
2. Java, protože v tom 99% věcí píšou ti, kdo trpí utkvělou představou, že jsou programátoři a ani autor se v tom pak nevyzná. A díky VM je pěkně nenažraná.
1. C#, protože upgraduje Javu vendor lock-inem.
:( :( :(
http://www.ftdichip.com/Products/ICs/FT51.html
http://www.silabs.com/products/mcu/8-bit/Pages/8-bit-microcontrollers.aspx
http://www.microchip.com/design-centers/8051-80c51-legacy-microcontrollers
http://www.nordicsemi.com/eng/Products/Sub-1-GHz-RF/nRF9E5
...
A viděl jsem to i v nějakých řadičích pro Ethernet, v managementu baterek,... Tomu zgarbovi se člověk nevyhne :( :( :( Holt patent už asi vypršel a je to levnější, než M0 nebo vlastní jádro.
Průšvih je, že tyhle věci nejdou programovat v C (omezeno HW) a z ASM mám husí kůži.
Dokonce se na x86 dá vystačit jen a pouze s instrukcí MOV, a existuje kompilátor:
https://github.com/xoreaxeaxeax/movfuscator
M/o/Vfuscator2 compiles programs into "mov" instructions, and only "mov" instructions. Arithmetic, comparisons, jumps, function calls, and everything...
Překvapuje mě ten assembler 8051. Mě naopak připadá úplně jednoduše pochopitelný, však to na průmce za pár týdnů zvládli i největší tydýtové :-) Ne doopravdy, oproti 8048 je to pokrok a v porovnání s takovou 68HC11, kde každý registr umí něco jiného a má to miliardu prapodivných instrukcí, je 8051 vzor ortogonality.
(OT: TCL nemá RPN, myslíš forth ne?)
mas pravdu +- nastejno, dokonce z80 a padesat jednicka maji spoustu veci podobnych (DJNZ a prepinani registrovych sad napriklad).
Jen na 8051 proste indexujes pouze pres R0 a R1 (trosku omezeni) a malinko slozitejsi je to pri adresaci externi pameti. Jinak klasicky akumulatorovy CPU (vetsina operaci jde pres A, druhy operand konstanta nebo je v R0-R7 popr. adresovany pres [R0] nebo [R1], coz se jen zapisuje malinko jinak pomoci @R0, ale to je jen malickost).
Jinak bezne operace: add,sub,rotace,and-or-xor,negace,mul pres pomocny registr B (specialitka),podminene a nepodminene skoky, nevim, fakt me to nepripadne tezke.
Za mě je nejhorší vlastnost assembleru 8051 (a bohužel i jiných) tohle:
mov r0,100
Co to asi tak udělá? Intuitivně by člověk čekal, že se do registru r0 strčí číslo 100. Ale ne, to by bylo moc jednoduché. Ono to vezme hodnotu z adresy 100 a ta se uloží do registru. Pokud chci do r0 uložit číslo 100, musím napsat:
mov r0,#100
Ani nespočítám, kolikrát jsem zapomněl napsat # a pak strávil moře času laděním a zjišťováním, proč to vlastně nefunguje. Opravdu by měl zajímalo, jaké myšlenkové pochody vedly tvůrce assembleru k tomu, že konstanta musí mít speciální prefix.
Oproti tomu Z80:
ld a,100
ld a,(100)
Úplně jasné na první pohled, první instrukce uloží do registru A konstantu 100, druhá instrukce hodnotu z adresy 100.
Ajo tak to zavisi na tom, na co jste si zvykl na zacatku. Ja zacinal na 6502 a tam bez #42 u konstant ani ranu, takze me zrovna toto nevadi (ale porad budme radi za to, ze se neprohazuje source a destination jako v gnu asu :).
Me spis matly [] pri prechodu na 8086, tam totiz nekdy NEznaci adresu, treba (pokud si vzpominam) u LEA. Navic to jeste "vylepsili" dvema rezimi assembleru u TASMu :)
Upozorňuji že pro 8051 existuje více assemblerů s různou syntaxí. Já jsem používal kousky se syntaxí od Intelu, stejně jako na 8080 a 8086, a přišlo mi to celkem v pohodě. Pozdější seznámení s kousky se syntaxí AT&T mě opravdu nepotěšilo.
https://en.wikipedia.org/wiki/X86_assembly_language#Syntax
Z80 je na tom ve srovnání s 8051 po stránce ASM dobře. Na to, že železo odvozovalo z I8080.
- Je tam pár registrů navíc. Mimo A, B, C, D, E, H, L, (HL), [F], [SP], [PC] jsou tam i speciální registry I, R, IX a IY
- Je tam k dispozici souvislých 64kB pro RAM a ROM a 256B pro periferie (ty se dají hodit i do paměťovýho prostoru, když na věc přijde). Bez omezení RAM na 128B, bez nutnosti do dalších 128B přistupovat nepřímo, bez prohazování registrů pro indexování paměti, s větším zásobníkem,...
- Bonus v podobě dvou index registrů IX a IY pro adresování (instrukce je přičetla k A a použila jako adresu do RAMky): LD B, (IX + A) apod.
- Booleovský procesor pracuje jenom s registrama. Ale vzhledem k tomu, že osmý registr je (HL), tak v podstatě obsáhne v jedné 16b instrkci (0xcb, 0xněco) prostor 65 543B (samozřejmě za cenu dvou cyklů ext. sběrnice + 2B instrukce, ale je to rychlejší, než načtení do registru, tam kombinování s konstantou a vracení zpět).
- Dá se zrychlit přerušení a šetřit zásobník, místo několika PUSH a POP jde prostě použít EXX a EX AF
- Je tam o dost zajímavější systém přerušení, tabulka vektorů kdekoliv v RAMce s podporou I registru. Většinou se ale nevyužíval, u nás tam cpali klony I8059A :(
A rozdíl je v tom, že Z80 nemá na sobě periferky a ty si člověk namapoval podle sebe. Ne tak, aby nějakýmu ožralovi vybraný SFR vyšly na bitově adresovatelný místo.
Dobry mindfuck. Vysvetleni: https://www.reddit.com/r/loljs/comments/2d4t2u/hold_your_horses_10101010mapparseint_yields_10/
Vic nez ten priklad s map me zarazi, ze parseInt( "10", 0 ) je 10 a ne NaN.
Řekl bych že je to jen o tom naučit se jazyk používat správně. Python nemá modifikátory přístupu, nechává na programátorovi aby přemýšlel nad tím jak bude k čemu přistupovat a bere se to jako super featura co nutí lidi víc přemýšlet o architektuře. PHP má taky svoje specifika některé věci neřeší a nechá je k řešení programátorovi. Ošetřit vstupy, případně typová kontrola v metodách, jaký je pak problém s operátory == a === přece vím co chci porovnat s čím a podle toho si vyberu jestli chci porovnávat striktně nebo z nějakého důvodu jen podle oka. Ano PHP je někdy nekonzistentní v názvech funkcí strpos, str_replace, nicméně kdo už to zná má to zažité, kdo ne tomu napovídá IDE přes autocomplete. Ale to určitě neznamená že by se v PHP nedal napsat přehledný a dobře čitelný kód.
Promiň, ale to co tam tam člověk sype, tak kus je volovina. Jako vzít nějaký jazyk a pindat, že nefunguje jako jiný jazyk je fakt blbost. Vymýšlet konstrukce které nefungují a pak předhazovat že nefungují ... to mi moc šťastné nepřipadne. To pak můžeme mít jazyk pouze jeden a bude pokoj. Navíc je to dost staré a některé věci už dávno neplatí. Jako příklad blbiny uvedu, že v jazyku, který nekontroluje dat. typy argumentů funkcí je blbost stěžovat si, že vyhodí error když se pokusí uvést dat. typ argumentu. To že se striktně nekontrolují typy argumentů může být i výhoda. Ale to už je na každém.
PHP je prostě dost benevolentní a je jedině na programátorovi, jak je dobrý a jak se s tím vypořádá. No a to je evidentně dost velký problém. PHP totiž nevede nikoho za ručičku jako třeba C ( Což je mimochodem dle mne krásný jazyk ) nebo Java a její NullPointerException.
Ale je to skutocne problem PHP? Vela ludi na nom zacina, pretoze je lahko dostupny.
A ak niekto chce kritizovat jazyk kvoli tomu, ze je dostupny pre ludi, ktori do sveta programovania este len vstupuju, tak... nech ide kade lahsie. Programator elitar nie je nic prijemne a ani chvalyhodne.
To je uz dost stary clanok a nemam pocit, ze by bol trefny. Ale ludia ho z nejakeho dovodu radi uvadzaju ako ukazku otrasnosti PHP.
Ja som v PHP programoval niekolko dlhych rokov, jednoduche, aj zlozite veci, ale nemam pocit, ze by som niekedy na vacsinu veci, o ktorych tam pise narazil. Ak pises ako prasa a spoliehas sa, ze ta bude zachranovat jazyk, tak pocitaj s tym, ze mozes mat v PHP problemy. Neviem co viac k tomu dodat.
>To je uz dost stary clanok a nemam pocit, ze by bol trefny. Ale ludia ho z nejakeho dovodu radi uvadzaju ako ukazku otrasnosti PHP.
a moje oblíbené
Osobně nechápu lidi, kteří obhajují jazyky, které zvládly posrat i tak základní věci jako je operátor porovnání.
To jako vážně nedokážeš pochopit co jsem napsal, že se musíš ještě separátně ptát, nebo to měla být řečnická otázka?
Psal jsem, že nechápu lidi, ne operátory. To že to posrali autoři PHP, to mi nepřijde tak divné, ostatně na to si člověk v PHP musí zvyknout. Že to ale někteří obhajují, jako dobrý nápad, to fakt nepobírám.
Nemám problém s existencí dvou operátorů, například jeden na porovnání obsahu a druhý na porovnání reference. To že v PHP je ale jeden operátor v podstatě nepoužitelný, protože má nepredikovatelné výsledky kvůli zběsilému přetypování, k jehož použití se musíš naučit celou zběsilou tabulku a modlit se, aby string nezačínal nulou a omylem nevypadal moc jako číslo v exponenciálním tvaru, to mi přijde jako sračka. A to že to lidi ještě obhajují, to prostě leží mimo hranice mého chápání.
Promiň, to ale skutečně nechápeš a proto ti připadá, že je to "zběsilé" přetypování, ale nemůžeš se divit, že když porovnáváš string a int, tak ti z porovnání vyleze nějaká volovina. To samé je ale i u funkcí na přetypování, nejen u PHP. Buď víš jak fungují a nebo se divíš a nadáváš na jazyk, To je celé.
Jo a k té tabulce. Taky můžeš kontrolovat, co porovnáváš a ne to tam naprat a když kompiler neřve 100 řádkovým výpisem, tak čekat, že to jako pozná za tebe, co jsi vlastně chtěl.
Neverim programatorum, kteri rikaji, ze jsou dost svepravni, aby zabranili chybe X, pokud X je mozne zabranit automaticky. Pokud to nahodou neni extremne schopny jedinec (ne typicky neni, ale pripustme tu moznost), tak je miziva sance, ze bude patlat neco v PHP.
(Ze v PHP jsou typy takove jake jsou je celkem jasne, na tom se snad dohodneme, ne protoze by pri tvorbe PHP meli tvurci jasno. Jsou tam protoze tvurci nemeli potuchu o tom, jak se to da delat jinak.)
To ale není o tom, že umím zabránit chybám a jsem nej nej programátor a blá blá blá. To je pouze o tom, ze se mi kompiler nesere do toho, co chci porovnat a co chci kam předat. Nic víc.
Alias: pokud chci mít jistotu, že porovnám dva integery, tak tam pošlu 2 integery a ne že tam vrazím "13w15" a 13 a pak se divím, že mi to benevolentní kompiler naparsoval podle svého a nepoznal, že chci porovnat "13w15" a 13 když použiju "=="
Ty jsi byl při tom když tvůrci PHP pracovali na typech a viděl jsi jim na obličeji tu strašnou bezradnost, jak vůbec nic neumí, neví, a jak se marně snaží z kolečkového křesla dosáhnout na klávesnici a nekontrolovatelně třesoucí se rukou vyprodukovat práci?
PHP je prostě z různých důvodů benevolentní, nikdo tě nenutí používat ==, klidně všude používej ===, nikdo tě nenutí porovnávat string s číslem. Chceš čistší kód bez zdánlivě (protože ten kdo ví jak se co chová zná i vyjímky a ví kde může být problém a čemu se vyvarovat) neočekávatelného chování, tak si ho tak napiš. Pořád je to jen o tom ohlídat si vstup a vědět co děláš a proč. Že jazyk umožňuje psát prasokód a ty pak píšeš prasokód, neni vina jazyku nebo vina retardace jeho tvůrců. Je to jen čistě tvoje odpovědnost jak pěkně si to napíšeš. Prasokód se dá napsat v každým jazyku, vždycky to jde udělat nesmyslně, žádný jazyk není blbuvzdorný.
Python taky nechává na programátorovi spoustu věcí, neřeší visibilitu, je jen na tobě jestli budeš dodržovat zapouzdření nebo ne, jestli využiješ vícenásobnou dědičnost. Někdo by to označil za prsárnu že jde dědit z více předků (viz. odpůrci v Javě), že z toho může vzniknout paskvil který vyhazuje vyjímky. Co když se použijí dynamické třídy a vícenásobná dědičnost, to je problém hned. Dělá to snad z pythonu špatný jazyk? Nikoliv, je to je o přístupu programátora který musí vědět co dělá a proč.
Vsem chybam v programu se da automaticky zabranit zakazem psani programu. Ergo neverte vsem programatorum. A neb cernibile videni v praxi. Kazdy pristup ma sve vyhodyba nevyhody, zakazovanim nevyhod blokujete i vyhody. At se to nekomu libi nebo ne, php jazyk se osvedcil a ukazal, ze jeho vyhody prevazuji nad nevyhodami.
Chcete tím říci, že se držíte doporučení, že proměnné se testují jen pomocí === a operátor == se používá jen tehdy, když je na jedné straně konstanta? Protože tak nás to učili. Mezi dvě proměnné nikdy nepsat ==. Pravidlo je to sice jednoduché, ale tak nějak nasvědčuje tomu, že s == opravdu nebude vše tak úplně v pořádku.
Alespoň takto si vykládám vaše "sám si pohlídal co mám v programu a co tam chci". To přesně popisuje explicitní konverzi nutnou při použití ===.
Ne. Budu psát o PHP ve kterém dělám nejčastěji. Jak jsem psal, operátor == používám i když porovnávám pole, ale jako když porovnáte "xyz" == "xyz" nebo 13 == 13 tak je to v pořádku. Tam u == je akorát nebezpečí, že pokud bude string začínat číslem, tak se přetypuje na číslo, ale jen po první písmeno a nebo pokud porovnáváte něco třeba s NULL nebo true/false a pár případů je lepší použít ===.
Op. == se dá využít třeba když Vám z parseru xml lezou stringy alá "1232345" a tak to můžete hned porovnávat s číslem, protože se to automaticky přetypuje.
Celkem hezky je to vysvětleno zde http://stackoverflow.com/questions/80646/how-do-the-php-equality-double-equals-and-identity-triple-equals-comp
Ale záleží na každém. Mě to tak vyhovuje, mám širší možnosti ale vždy je možno použít === kromě porovnávání OOP objektů. Takže se v jazyku nemusí zakázat 2 equeal operátory, stačí používat jen === pokud někdo chce.
No, tak hlavně že mi vysvětlíš co chápu a nechápu. Já si četl zdrojáky PHP, takže bych řekl, že v tomhle žádné pochybnosti nemám.
Z porovnání pomocí == lezou sračky, i když porovnáváš dva stringy, protože je to přetypuje na číslo, když jako číslo vypadají. A jako číslo vypadají i věci, které číslo nejsou (třeba MD5 hash 0e830400451993494058024219903391), o tom byl celý ten příklad s MD5. Taky nevím co furt pleteš kompilery, když PHP je interpretované.
No víš, on do processoru jde kompilovaný kód. Procesor nepracuje se stringy. To že se o to stará interpreter je věc jiná.
"Z porovnání pomocí == lezou sračky, i když porovnáváš dva stringy, protože je to přetypuje na číslo, když jako číslo vypadají. "
"Z porovnání pomocí == lezou sračky, i když porovnáváš dva stringy, protože je to přetypuje na číslo, když jako číslo vypadají. A jako číslo vypadají i věci, které číslo nejsou (třeba MD5 hash 0e830400451993494058024219903391), o tom byl celý ten příklad s MD5. Taky nevím co furt pleteš kompilery, když PHP je interpretované."
Já to risknu. Napíšu ti to tak, abys to pochopil, ale riskuji, že mě někdo chytí za slovíčko. Použil jsi == operátor, který neporovnává striktně a umožňuje automatické přetypování. Takže si otevři script a zkus použít === a pak zase klidně napiš. Jo a když už jsi teda procházel zdrojáky PHP :-)))) tak jsi určitě narazil na http://php.net/manual/en/function.strcmp.php
Díky za praktickou ukázku přesně té retardace, na kterou jsem narážel, že jí prostě nechápu. V tomhle jsem si nemohl přát lepší spolupráci. Zkus mi teď vysvětlit, proč si myslíš, že je tohle chování dobře a nesnaž se mi pořád podstrkávat, že nerozumím tomu, jak ten operátor funguje.
PS: Nepoužil jsem nic, linkoval jsem na příklad, kde se to někomu stalo, protože si myslel, že ví, kdy je bezpečné použít ==, stejně jako ty, když jsi tvrdil*, že můžeš porovnávat stejné typy.
*Viz:
>Alias: pokud chci mít jistotu, že porovnám dva integery, tak tam pošlu 2 integery
Což prostě takhle nefunguje a u == je opravdu velmi složité říct, kdy nebude mít žádné úchylné vedlejší efekty, i když zrovna skutečně porovnáváš stejné typy.
Retardaci předvádíš akorát tak ty. Takže ti to napíšu po 4 a naposledy.
Tak za 1
Pokud v PHP porovnáváš stringy, máš použít strcmp a nebo === protože když použiješ == tak se to díky tomu, že první znak je číslo, pokusí automaticky přetypovat na numerický formát. To tak ale není jen kvůli porovnávání ale je to použito z vazby automatického přetypování, které se používá nejčastěji při aritmetických operacích, jak jistě víš, když jsi si procházel zdrojáky PHP :-))))
za 2.
To, ze se ti výsledek funkce md5 jeví jako číslo, i když md5 vrací string, za to PHP určitě nemůže.
za 3.
Často používám == třeba u porovnání polí a neperu do toho stringy
Automatické přetypování je v PHP proto, že PHP nekontroluje tak silně datové typy a tak má sadu těch pravidel pro přetypování pro porovnání podle prvního argumentu. Pokud to nechápeš nebo nechceš využívat, tak použij ===. Případně UTFG
> Retardaci předvádíš akorát tak ty. Takže ti to napíšu po 4 a naposledy.
Tak za 1
Pokud v PHP porovnáváš stringy, máš použít strcmp a nebo === protože když použiješ == tak se to díky tomu, že první znak je číslo, pokusí automaticky přetypovat na numerický formát. To tak ale není jen kvůli porovnávání ale je to použito z vazby automatického přetypování, které se používá nejčastěji při aritmetických operacích, jak jistě víš, když jsi si procházel zdrojáky PHP :-))))
Tak tedy znova a naposledy:
Je mi naprosto jasné, jak to funguje. Vím i proč to tak funguje. Četl jsem zdrojáky PHP v C. Viděl jsem o tom diskuze. Dokázal bych naprogramovat program, který se stejně chová, složit o tom operu, nebo tu myšlenku sdělit včelím tancem. Prostě to chápu. Vím kde se to vzalo, jaké jsou výhody a nevýhody. Pokud o tom budu ještě chvíli diskutovat, možná to pochopení dokonce geneticky předám na své děti.
O tom se ale nechci bavit. Zajímá mě, proč si někdo myslí, že je to dobrý nápad. Místo toho se, jak už je s PHP uživateli typické, chováš jako neschopný porozumět psané větě a pořád mi cpeš něco, co mě vůbec nezajímá.
> To, ze se ti výsledek funkce md5 jeví jako číslo, i když md5 vrací string, za to PHP určitě nemůže.
Tak určitě.
" proč si někdo myslí, že je to dobrý nápad."
Třeba proto, že si mohu vybrat, jestli chci porovnání s přetypováním podle předem známého algoritmu, a nebo chci striktní porovnání?
" Místo toho se, jak už je s PHP uživateli typické, chováš jako neschopný porozumět psané větě a pořád mi cpeš něco, co mě vůbec nezajímá."
To ti trošku ujelo. Takovými de..lními výroky se snad prezentovat nechceš, ne?
@ Ondra Satai Nekola
Tak pane Nekola, ze zdejších diskuzí vím, že si rád kopnete "do ležícího" nějakou tou rádoby trefnou poznámkou, to jste se ale spletl, já "neležím", vím co píšu, ale jsem tam pána asi úplně nepochopil, i to se stává a pravděpodobně, kdyby pořád nepoužíval peprných výrazů, tak by Vás to nezmátlo a nenutilo "si kopnout".
Popravde ani ja v tom nevidim problem. Niekto sa tu snazi tvrdit, ze PHP je tak crippled, ze sa v nom nedaju ani poriadne porovnavat dve hodnoty, lenze v praxi to tak vobec nie je. Kto si skusi urobit v PHP dva tri projekty, zisti, ze ono to ziaden problem nesposobuje.
Modelove priklady su pekne, ked chceme niekomu nieco strcit do tvare, ale prax je prax.
Máte špatně postavenou otázku. Není to o tom jestli dotyčný je nebo není schopný pochopit jak operátory v PHP fungují. Otázka zní jestli když "0e1" == "0e2" vrátí true, tak jestli je jazyk navržený tak aby byl predikovatelný a praktický. Vždyť se má jednak o jazyk pro ne-programátory. Pro ti PHP je i VBA mana seslaná z nebes.
" Vždyť se má jednak o jazyk pro ne-programátory"
Asi jste myslel "jednat". Ok. PHP je často podceňované a pak, až si na něm nějaký bourák, který je zvyklý že ho compiler jazyka vede za ručičku, vyláme zuby, protože PHP nechá spoustu věcí na jeho uvážení, se pak najednou objevují články, ve kterých se kňourá, jak je PHP na nic ...
Jsou prostě věci, které si překladač má pohlídat, ale to by se na ně muselo myslet už při návrhu jazyka. Jenže ten vznikal hodně chaoticky (však to byl jen primitivní preprocesor, do kterého se později nacpalo OOP a C-like funkce), takže výsledek vypadá jak vypadá. Už jen kvůli tomuto chaosu (jazyk, sémantika, knihovny) se PHP na skutečně velké projekty nepoužívá a když už nějakým omylem jo, tak to pekelně bolí :-)
jinak neber si to osobně, ale potkal jsem již stovky vývojářů a z tohoto vzorku vyplývá, že PHP nějak přitahuje skutečné ....chaotiky.... Ne nutně programátorská prasata, ale lidi, co si kód po sobě moc nečtou, netestují, nedokumentují, nasazují na "produkci" ad hoc patche atd. Ostatně i dnes narazím na kód s "podporou" SQL injection. Těžko říct, jestli je v PHP příčina či důsledek...
"PHP na skutečně velké projekty nepoužívá a když už nějakým omylem jo, tak to pekelně bolí :-)"
https://en.wikipedia.org/wiki/Programming_languages_used_in_most_popular_websites
Víš co? Tak otevři oči a podívej se, v čem jsou napsané největší a nejrozšířenější frameworky. Ano, je chyba PHP, že když v tom začne někdo něco patlat, tak PHP ho klidně nechá. Ale já v benevolenci problém nevidím. Naopak, ono to má i své výhody.
"jinak neber si to osobně, ale potkal jsem již stovky vývojářů a z tohoto vzorku vyplývá, že PHP nějak přitahuje skutečné ....chaotiky.... Ne nutně programátorská prasata, ale lidi, co si kód po sobě moc nečtou, netestují, nedokumentují, nasazují na "produkci" ad hoc patche atd. "
Promiň, ale to evidentně o PHP moc nevíš. Myslím že se tesutje atd tak jak v jiných jazycích.
Nazor jsem snad predvedl jasny - PHP neni designovane lidmi, kteri k tomu maji dostatecne znalosti a rozhled.
A doplnim - dulezity je nejen jazyk a knihovny a tooling, ale i kultura kolem. A tak prestoze slusne se da psat skoro ve vsem (jen nekde snaze, jinde hure), tak proste jsou ekosystemy, kde se na kvalitu proste dba vic a ekosystemy, kde se spis bastli. Jak je to kolem PHP je videt z toho, jak se trebas chudak David G snazi evangelisovat veci, ktere uz jsou jinde brane jako samozrejmost.
Ok. To je aspoň nějaký názor. Sice ho nesdílím, protože PHP je cílovka mnoha a prvoprogramátorů, ale je to lepčí než ty výkřiky.
Vysvětlím. Mnoha, protože programovat si webísky a nejlépe ve WP je populární a jednoduché, prokousat se základy třeba Javy nebo C, ale i Clojure asi není tak jednoduché a ty kompilery pořád řvou a tak. A prvoprogramátorů, protože je PHP tak benevolentní, že jim to každý poradí, ať v tom začnou ale přitom ani neví, co to znamená "datový typ" - prostě píšou. Za 10 už to něco vypisuje. To je ale omyl. PHP je právě v té benevolenci tak těžké. A znova píši: Netvrdím že je PHP nej nej jazyk. To určitě ne. Třeba LUA mi učarovala, ale v PHP se živím spoustu let a tak tuším jak to je. Ale začal jsem na C, mikroC a PIC asembleru, pak Matlab i Simulink a až pak PHP, MYSQL, Javascript (resp. ECMAScript), pak Java JSP a Android Java spousta projektů a nyní testuji LUA a Clojure a Cofeescript + dělám s Node.js Tak si troufám tvrdit, že aspoň trošku rozhled mám.
To nerozporuju, že se používá na weby (i když zrovna Tebou odkazovaná statistika moc o PHP nepíše :-), ale když k sobě budeme upřímní - to je sice hodně viditelná oblast vývoje, ale zdaleka ne oblast jediná. Dále to nic neříká o tom, že založení produktu na PHP skutečně hodně bolelo (i ten slavný FB si PHP musel ohnout, tou bolestí jsou zde samozřejmě peníze) a když už to konečně běží, tak to nechali, přece nebudou začínat znovu na zelené louce.
Mimochodem je Ti jasné, co se musí stát, abys udělal jeden jediný "hit" třeba na tom FB? Tvůj CPU udělá několik milionů cyklů v nativním kódu psaném v C/C++, dále v interpretru JS ve Tvém prohlížeči, pár subrutin (v C) se spustí na každém routeru, kterým projde request atd. Takže jak toto chceš porovnávat?
Ale no tak, o kus výš říkáš, že máš rozhled, tak se na to podívej zrovna na ty weby:
1) máš datovou vrstvu, na tu saháš asi přes SQL že - první jazyk
2) máš logiku, ok pokud je to jednoduchá aplikace, asi to máš přímo v PHP - druhý jazyk
3) máš dynamické GUI u klienta, to je většinou JavaScript - třetí jazyk
4) k tomu takové ty nutné obezličky kolem - XML, CSS, HTML, SVG - další jazyky (ne Turingovsky kompletní, ale evidentně jazyky)
Takže tvrdit, že se weby píšou jen v PHP je kravina. Navíc se čímdál víc nahrazuje nodejs (to je +- stejná cílovka). Lidi, co dělají weby v dalších jazycích (C#, Java) jsou s množinou PHPčkařů disjunktní.
No a mimo dynamické weby PHP skoro neuvidíme, což se tedy já vůbec nedivím :-)
Hele, pochybuji že bych někdy napsal že se weby dělají jen v PHP. Jenom za dnešní práci na webu jsem sahl na PHP, JS, HTML, Grunt, SASS/Compass a SQL a nějaké obrázky. Takže klid.
Ale celkem jsi to popsal, nicméně podíl PHP na webech je dost vysoký a neklesá. I ten XYZ.js má svoje problémy a ne všechno na js je ideální. To C a Java jsou těžkopádnější na web, ty si myslím jsou spíše na desktop, ale proč ne, dneska máme výkonu dost, ale považ pro jednu web firmu držet 1000 webu na PHP hostingu a na JVM. Ale co, třeba i to se změní. Ony se spíš ty technologie vybírají podle účelu a pro mini a poloweby - ideální na PHP - je nejvíc. Jako můžeš se i na hlavu postavit, ale zatím to tak nějak je. Celkem nechápu co řešíš ...
Tak ja myslim, ze jsme se nakonec shodli na tom, kde vsude se PHP (ne)pouziva. Akorat jsme se neposunuli v tom, ze ja tvrdim, ze nasazeni PHP na vetsi projekty je proste porod (a nekdy hodne drahej), na coz jsi ty odpovedel tabulkou, kde je PHP zmineno u FB a dalsich 2-3 "svetovych" webu, tot vse. Ze se ta dve tvrzeni nevylucuji, na tom se taky shodneme? :)
S tim hostingem atd. - jasne, mas pravdu, to nerozporuju, ale nevim, jestli jde o pricinu nebo dusledek. Jako ze kdybych potreboval udelat dyn. web a nemel svoji virtualku, tak bych mozna (mozna) kvuli cene zbastlil backend v PHP, protoze asi v CR rozumnej hosting s necim jinym neni tak beznej. Tot vse, proste znouze ctnost.
Nie, PHP tak nejak nepritahuje skutocnych chaotikov. PHP pritahuje ludi, ktori s programovanim zacinaju, pretoze je lahke sa k nemu dostat (ci uz vyukove materialy alebo nastroje) a tak je logicke, ze vacsia ci mensia cast kodu je prasacka. To, ale neznamena, ze sa PHP nehodi na nic ine, nez domovsku stranku pubertakov. Pristupnost jazyka masam predsa nevypoveda o jeho kvalite.
"0e1" == "0e2" nedokazuje, ze PHP je nepredikovatelny a neprakticky jazyk, pretoze tento vysledok dostanes vzdy prave kvoli tomu co bolo spomenute. A kedze bolo uz aj niekolkorat vysvetlene o co ide a ako to spravne pouzivat, tak tuto diskusiu nechapem. Pripada im to uz len ako hate a kopanie za kazdu cenu. Taka nabozenska debata.
A jak mam vedet jestli mi funkce vrati objekt nebo string. Na objekty totiz naopak === pouzit nesmim, ty se netrojrovnaji i kdyz maji stejnou hodnotu. Takze univerzalni porovnavaci operator neni ani == ani ===, ale musim si ho napsat sam jako funkci. Jeden z prikladu vrcholne nekonzistence jazyka.
Dobře, ať tedy do toho netaháme objekty, přirozené porovnání se chová takto:
'10' == '0x0a' -> false
0.0 == 0 -> true
PHP '==' hodí v prvním případě true. PHP '===' hodí v druhém případě false.
Takže podle vás při implementaci přirozeného porovnání potřebuju nejprve zkontrolovat typ hodnoty a pak vybrat '==' nebo '===' (nebo strcmp).
Abych lépe ukázal kam toto přetypování vede, aneb vrchol konzistence porovnání a indexace:
function mycompare($xe,$ye) {
$x = eval("return $xe;");
$y = eval("return $ye;");
$a = array();
$a[$x]=1;
$a[$y]=2;
echo "$xe==$ye:".($x==$y?'yes':'no')."\t";
echo "$xe===$ye:".($x===$y?'yes':'no')."\t";
echo "\$a[$xe]==\$a[$ye]:".($a[$x]==$a[$y]?'yes':'no')."\n";
}
mycompare('10','"10"');
mycompare('10','10.0');
mycompare('10','"0xa"');
A výsledek:
10=="10":yes 10==="10":no $a[10]==$a["10"]:yes
10==10.0:yes 10===10.0:no $a[10]==$a[10.0]:yes
10=="0xa":yes 10==="0xa":no $a[10]==$a["0xa"]:no
Defenzivní programování ti nic neříká? Sám svoje chyby nevidíš a někdo by ho po tobě měl vidět. Code review sice najde plno chyb, ale je to o lidským faktoru a ne vždycky je poblíž někdo, kdo se v jazyku vyzná a má zrovna čas/chuť to po tobě skouknout. Párový programování zase málo kdo zaplatí.
Takže parťákem, který tě aspoň trochu hlídá, musí být počítač. Kompilátor, unit testy, CI, statická analýza, generátor kódu,... Cokoliv. Čím víc, tím líp, protože víš, že ti někdo aspoň trochu kreje zadek a můžeš víc energire věnovat práci, než hlídání, co vlastně je v proměnné a jestli číslo náhodou není "žirafa". Chápu, že dotaz od kompilátoru "Jsi si jistý, že porovnání signed a unsigned hodnoty je korektní?" nebo "Jsi si jistý, že do proměnné typu litry můžeš narvat galony?" je občas otravný, ale lepší je to schytat decentně od kompiléru, než od zákazníka, který zuřivě cupuje fakturu za tvůj soft, nebo od pojišťovny, co proplatila škodu a vymáhá to po tobě.
Nelíbí se ti to? Kup si sešit formátu A4 a propisku. Tam si můžeš psát cokoliv a nikdy nebude protestovat ani v případě, že při ladění algoritmu piškvorek sám proti sobě budeš podvádět.
Jo, to je jistě skvělé, o tom bez debat, ale pokud přijímáš vstupy od uživatelů, tak si musíš jejich vstupy zkontrolovat a upravit jak je nutno a neznám, ale možná se pletu, kompilátor, který by mi při psaní kódu řval na všechno co mi tam může od uživatele přijít, když si nejsem schopný zajistit, že tam kde mám porovnám stringy je porovnám jako stringy a tam kde chci porovnávat čísla je porovnám jako čísla a to buď tak, že vím, jak program pracuje s přetypováním a nebo použiji striktní porovnání.
Celé toto vlákno vzniklo z toho, že někdo porovnal string který obsahoval čísla se stringem a nepoužil (bylo to PHP) strcmp nebo striktní === a najednou z toho byla žumpa PHP, bahnno a bažina ztracených lidských nadějí. Celé je to ale z toho, jak PHP zachází se stringy a je schopno je automaticky přetypovat. Kdo o tom ví, tak ho to asi nepřekvapí a když chce porovnávat něco se stringy tak si dá bacha.
Každopádně i v PHP pokud porovnáš "str1" == "str1" tak to funguje správně, problém je jenom se stringy, které obsahují čísla. Ale pokud vím správně, tak i v ostatních jazycích, pokud porovnáváš, tak si musíš převést hodnoty na stejný datový typ, jinak ti to prostě projde jako FALSE. Takže nebýt líný a zajistit typovou konverzí datové typy jaké chci porovnat. To je celé.
PS: i na boolean a NULL je v PHP ideální použít striktní === protože true by mohlo být více věcí, i 1. Objekty s isinstanceof případně převést na pole a porovnat jako pole.
"Ale pokud vím správně, tak i v ostatních jazycích, pokud porovnáváš, tak si musíš převést hodnoty na stejný datový typ, jinak ti to prostě projde jako FALSE."
obecne neni pravda, vetsinou to ve staticky typovanych jazycich ani nezkompilujes :)
PHP sezere vse a garantuji ti, ze driv ci pozdeji s timto pristupem narazis, to je jistota.
Ale nekdo tu psal o defenzivním programování. Ok, proč ne. Ale to, že na to čumí 2 lidi ještě neznamená, že chybu najdou a s ohledem na bezpečnost výsledku si nejsem jistý, jestli je nejlepší volba mít programátora, na kterého pokud nezařve kompiler, tak se nestará ....
většina programátorů se imho stará teprve až když něco zdechne. Otázka je, jestli je lepší aby to padalo pokud možno při kompilaci, nebo až za provozu. To že by menší kontrola ze strany kompilátoru vedla k větší odpovědnosti je čistá iluze, navíc předpokládající, že veškerý kód v projektu je od těch odpovědných, další iluze.
Jo, ale předpoklad, že tím, že spoustu chyb odhalí kompliler, tak je včechno ok, je taky iluze. A předpokládat, že když kompiler vyhazuje warningy tak je bude každý opravovat je taky iluze. Už vidím nějakého lempla, kterému už v existujícím projektu vyskočí 80 warningů a on je všechny poctivě projde i se včemi závislostmi, když to šéf chce mít odpoledne na webu a co bylo nikoho nezajímá. Ale to se děje všude. Akorát PHP tolik neřve u kompileru. O to víc ale člověk musí vědět co dělá. Jak se k tomu kdo postaví? To je na každém. Jinak víme, že warningy se dají potlačit directivou. A i v tom benevolentním PHP to lidi dělají, že si je i vypnou a tím je pro ně vše ok. To mě vede k tomu, že to nebude o jazyku. Leda že by jazyk stál za takovým výtečníkem a zrovna fackoval :-)
Warningy ti snad rovnou sviti v IDE, kdyz pises? A pokud tam mas nejake zlute podtrzeni a vykricnicek, tak bys snad kouknout mohl.
Jinak nic te neochrani pred vlastni blbosti. Ale je rozdil k tomu ty pomocniky mit a nemit. To mas uplne to same jako kontrakty, unittesty, integracni testy... Vzdy najdes situaci, kde nezaberou. A vzdy je muzes vypnout. Ale pomahaji. A kdyz je vypnes, tak si dusledky zaslouzis...
První linie je parser pro syntax highlight, ten reaguje ještě než dopíšu řádek i bez kompilace.
Druhá linie je kompilátor s volnou -Wall.
Třetí linie je CppUnt nebo něco podobnýho (v závislosti na jazyku), kde si projedu funkci, vstupní hodnoty a kritický místa.
Čtvrtá linie je pan Jenkins.
Pátá linie je code review.
Šestá linie jsou logy a výjimky v kódu.
Sedmá linie jsou tesťáci.
Pochlub se, jaký máš pastičky na broučky?
Btw, platí zlatý pravidlo, že kód s warningama se nikdy nekomituje do ostré. Protože warning je převlečená chyba.
Ne, jsou nedokonalí programátoři. Nikdo totiž nevymyslel nic lepšího. Teda mimo generátor kódu, kde taky může být chyba.
Mozek má omezenou kapacitu. Dokáže bufferovat a kombinovat maximálně sedm věcí. U blbýho volání funkce xQueueReceive ve FreeRTOSu máš tři parametry (typ, význam), návratovou hodnotu, potom typ dat ve frontě, význam předávanýho parametru, musíš si hlídat velikost fronty atd. a při tom myslet furt na to, co chceš dosáhnout. Proto první linie, která našeptává a upozorňuje, že pvBuffer má být pointer, že třetí parametr je timeout a jeho proměnná ještě nebyla deklarována, že je překlep v handle fronty,... Můžeme se tak soustředit na to co děláme, na to, co na řádku není (typ dat ve frontě) a ne na to, jak to vlastně napsat a jestli on ten timeout náhodou nebude string. Ono je to takový osvobozující, myslet na algoritmus a ne na to, co s tím kompilátor nebo interpretr provede.
Jenomže ono se toho v PHP zase tolik zvláštního neděje, až na to, že pokud někdo použije == na string který začíná čísly, tak se přetypuje na číslo a pokud chce porovnávat booleany, tak je lepší striktní === protože i samotná existence objektu může být hodnocena jako true.
Takže celý problém vlastně je to kolem toho, že si někteří jinak geniální programátoři nedokážou zapamatovat, že když
1. porovnávám stringy, je nutno použít === nebo strcmp
2. když porovnávám s boolean je jistější použít ===
3. když si chci být jistý že porovnávám stejné typy, tak si je přetypovat.
No to jste teda hvězdy.
Jinak PHP má spoustu skvělých funkcí a vlastností vhodných pro webařinu ale to samozřejmě nevíme, protože pliveme kvůli možnosti vybrat si permisivitu porovnání při větvení toku programu.
Cela tato debata sa mala skoncit uz vcera okolo obeda, kratko potom ako zacala. Lenze to by tu niektori nesmeli viest nabozenske vojny proti jazykom, o ktorych niekde poculi, pripadne ich skusili a neviedli ich za rucicku.
Zvlast usmevne to bolo v tejto diskusii pri pripade Javascriptu a rovnakej "chyby" pri pouziti funkcii map a parseInt... To co sa zdalo ako chyba a nekonzistentnost jazyka sa ukazala ako neznalost pouzitia funkcie parseInt. Rovnako ako v pripade == a === v PHP. Len s tym rozdielom, ze o Javascripte sa nabozenska debata neviedla, stacila ta o PHP...
Tak ono je to s těmi staticky a dynamicky typovanými jazyky jako s přístupem k firewallu. V jedněch je vše zakázané a pohybujeme se co si povolíme a v druhých je vše povoleno a hlídáme si co je potřeba ohlídat. Pak to chytne nějaký začátečník a protože je vše zakázané tak ho to nebaví. A nebo chytne ten druhý, vše je povolené, tak večírek začíná, ale pak, až opravdu dojde na lámání chleba, tak ho to vyplivne a je naštvanej. Co je lepší? Nevím. Určitě bych na PHP pár věcí vylepšil, ale nějaká "žumpa" nebo "nejhorší jazyk" to určitě není
1. Naprostá dieta, ráno a večer po šálku čaje během tří dnů, přičemž se všem bez rozdílu toho, nač si stěžují, podává aspirin pro pocení.
2. Podává se, aby si nemysleli, že je vojna med, v hojných porcích chinin v prášku, čili takzvané "lízání chininu".
3. Vyplachování žaludku dvakrát za den litrem teplé vody.
4. Klystýr, při použití mýdlové vody a glycerínu.
5. Zabalení do prostěradla namočeného ve studené vodě.
Dr. Grünstein
Bud za ty tooly rad. Ony pomahaji tobe, neni to zadna buzerace, stejne jako neni buzerace dodrzovani stabni kultury, kontrola kodu pres commit hooky apod. Proste pokud nechces zbytek zivota travit hledanim chyb na produkci (kde za tebou stoji zakaznik, lamentuje a priste to zkusi jinde), tak se nejde spolehat na vlastni usudek.
Ostatne i v aute mas ABS, pasy, pasivni ochranu, i kdyz prece vsichni jsou skveli ridici, co by chybu nikdy neudelali :)
To bude na mě. No už jsem viděl i horší věci. Zrovna mě napadá, jeden človíček po kterém se mi dostal projekt do ruky, přímo u výběru z databáze počítal s tím, že když se nevybere správně, tak se do proměnné nic nepřiřadí a pak v šabloně, až se zavolá hodnota k výpisu tak to padne - ale protože na produkci není zapnutý debug mode tak to jen ukončí výpis bez keců. To bylo srandy, když jsem dostal za úkol tam něco upravit a zapl jsem si debug mode. Potkal jsem to pak po něm vícekrát a bylo mi řečeno, že to tak prostě dělá :-( A spoustakrát mi bylo třeba kvůli ceně a času explicitně zakázáno dělat testy. Pro žádnou z těch firem jsem dlouho nakonec nedělal, ale z něčeho člověk živ být musí. Takže nějakých 80 warningů ..... who cares? :-D
Vy jste asi nikdy nespolupracoval s indickými "programátory". Když jsme od nioch přebírali projekt, tak při buildu to vyplivlo několik tisíc warningů a oni se ještě divili, že se nám to nelíbí.
A to bylo to nejmenší - například když se nám nedařil build, tak jsme zjistili, že oni pro build produktu používali stále stejný adresář, který nikdy nemazali, a že tam mají jeden object file, bez kterého to nejde sestavit, od kterého neexistuje zdroják a o kterém ani nikdo neví, co má dělat.
Nenajdou. Je to jejich mentalita.
1) Koloniální minulost, pořád vaše blahorodí, bude to včas, ale nic se neděje. Posledně jsem se připletl k projektu, kde se dělaly SW testy v Indii. Po 3/4 roce "testování", kdy bylo 80% testů hotovo, jsme zjistili, že jsou napsány testy pokrývající 60% featur a testovaný výrobek ještě neměli připojený.
2) Kreativita na nule. Pokud ind nedostane checklist, tak přešlapuje na místě a sám nic nevytvoří. Když ho nevedeš za ručičku, dostaneš v lepším případě nesmyslný slepenec.
3) Milují procesy. Jsou jima posledlí. Je to horší, než němci. Univerzální výmluva byla, že podle procesu je napřed potřeba mít certifikaci na rádio, i když zařízení bezdrátovou část neobsahovalo. Prostě nebylo nic, zasekli se na jedné eventualitě.
4) Pokud se mezi nima najde mladý a snaživý svazák, je to jenom proto, že ještě nebyl povýšen. Mají zažitý kastovní systém, kde se dá za život postoupit o jeden stupeň, víc ne. Jak ho jednou někdo povýší, přestane se snažit a flinká to, životní mety dosáhl, tak proč se dřít.
Moje zkušenosti za šest let práce s nima jsou takový, že bych si od nich nenechal ani ořezat tužku.
Ne, takto
if ( true === $variable )
"obecne neni pravda, vetsinou to ve staticky typovanych jazycich ani nezkompilujes :)"
No to sice nezkompiluješ pokud špatně přiřadíš do proměnné, ale pokud i ve staticky typovaném jazyce máš něco string a chceš to porovnat s int nebo float ..... tak to musíš přetypovat. Jde mi o to, že pokud to programátor nepohlídá, tak klidně může porovnat var int x s var float y a taky mu z toho něco vyleze a mám ten pocit, že při překladu to ani třeba Java ani C nehlásí. Možná se pletu, nějakou dobu už jsem v tom nepsal, ale nevzpomínám si, že by to kompileru nějak vadilo.Třeba v C je to tuším základní výuková úloha, co se stane, porovnáme li string a int. Ale C jsem už fakt dlouho nedělal a takhle ve vteřině přesně nevím.
Nic ti nebrání udělat to i v PHP, pokud chceš mít jistotu co ti tam leze. Ono je to totiž ten rozdíl tím, že v PHP máš často input jako string a tak s ním i pracuješ, ale pokud počítáš nebo porovnáváš, je ideální přetypovat na správnou hodnotu.
Naproti tomu ve stat. typovaných jazycích to řešíš už na začátku když to dáváš do proměnné.
Ale ve stat. typovaných jazycích se ti to ale může stát taky, třeba v Jave ti může přijít proměná z ArrayListu a vůbec "nevíš" co tam je a už musíš přetypovat. Nebo v C ze struktury a jsi na tom samém, musíš si ověřit, co tam je.
Celé se to stalo tak, že někdo náhodou provnal string "15" == 15 a ono toprošlo, protože nepoužiil strcmp nebo striktní ===. to je celé.
Ok, tak ty kompilery warningují, když někdo porovnává třeba string a int. Taky už vím, proč si to nepamatuju. Protože jsem zvyklý přesně vědět co kde a s čím porovnávám. Proto jsem tyto warningy asi dost často nevídal aby se mi to vrylo do paměti.
Nicméně to se strukturami a ArrayListy platí dál. Dynamicky typovaný jazyk prostě není na hovno jenom proto, že si nějaký začátečník nepohlídá, co mu kam leze a co kam strká.
To je trochu odvážné tvrzení.
Netvrdím, že je to svatý grál, ale rychlost vývoje u mnoha projektů celkem jasně ukazuje, že určitý rozdíl stále zůstává. Na internetu se dá najít mnoho porovnání, kdy probíhal paralelně vývoj v javě a nějakém dynamickém jazyce. Ještě jsem nečetl jediný článek, kde by bylo napsáno, že vývoj v javě byl rychlejší.
Kdyby to byla pravda, dynamické jazyky by už dávno byly mrtvé.
Označit mne za obránce PHP je mimo. PHP neumím ani číst a nikdy se ho nehodlám učit.
Reagoval jsem na následující:
"Dneska uz prakticky zadna vyhoda, jen nevyhody.
Nejcastejsi namitky (ukecanost deklaraci a malo svobody) uz davno staticky typovane jazyky daly stranou..."
Nikde nevidím odvolávku na moderní a up-to-date.
Pouze jsem přinesl několik věcných argumentů na zjevně namachrovaný a generalizující výrok (rozumím kontextu ve kterém byl použit). Že jsem jako protiargument použil zrovna Javu je jednoduché, je to jeden z nejrozšířenějších staticky typovaných jazyků. Pokud někdo útočí na velmi rozšířené PHP, nemůže se odvolávat na nějaké obskurnosti, ale musí vytáhnout podobně rozšířený jazyk.
Že to skončí hloupými osobními útoky je smutné, zvláště od osoby, která to podle mne nemá zapotřebí.
No jo, když tady není vidět kdo na co odpovídá... a i kdyby bylo, je to uprostřed obludného flameware kde už padlo tolik blbostí....
Jinak souhlasím s tím, že dynamické jazyky stále mají místo. Už jenom z toho důvodu, že v praxi překvapivě často stačí kód který není korektní ve všech možných situacích - externí omezení prostě takové situace vyloučí, ale vyjádřit to typovým systémem je úkol na PhD (pokud to vůbec jde).
Jenomže to jsou jiné argumenty a skutečně nemá smysl se bavit o konceptu z osmdesátých let minulého století (Java, C++, Delphi).
Co se týče ukecanosti a svobody... takhle z hlavy mě napadají Haskell, F#, Scala, ocaml (no, tohle už má docela léta).
Vlastně ani nevím zda existuje nějaký imperativní (nebo imperativně-OOP) jazyk s opravdu dobrým typovým systémem...
Otázkou je, co je to dobrý typový systém? Například typové systémy se silnými vyjadřovacími schopnostmi mají obvykle horší typovou inferenci.
Nebo typové systémy pro relační databáze mohou být v některých situacích horší než typové systémy pro XML nebo pro numerickou matematiku, v některých situacích zase mohou být lepší.
Aby ta analogie s auty byla úplná, je potřeba ještě dodat, že to auto s jedním posilovačem má zaroveň omezovač výkonu motoru. Takže je možné jet pomalu a relativně bezpečně nebo rychle, ale s rizikem v nebezpečných situacích. ;)
Tyhle diskuse jsou docela zábavné a nic nelze brát dogmaticky a absolutně. Pochybuji, že nějaký zapřisáhlý odpůrce Javascriptu, který odkazuje na absenci typové kontroly, najednou začne milovat Typescript jenom proto, že tam typová kontrola a další věci najednou jsou.
Navíc kolem Javascriptu vznikl poměrně velký ekosystém linterů a dalších nástrojů, který toho poměrně hodně odchytí a při dobrém nastavení lze výrazně posunout tu hranici určující bezpečnost. Jak je to u ostatních dynamických jazyků nemám přehled, používám je spíš vyjímečně, ale nemám důvod si myslet, že situace je zásadně jiná (až na PHP). :D
A že typy taky nejsou všechno ukazují různé lintery pro staticky typované jazyky, třeba go jich má bezpočet.
Ano, přesně takový dojem mám taky. Některé jazyky jsou prostě špatné, áááno. Zrovna v případě JS s jeho hyperaktivní komunitou na každý pseudoproblém existuje tisíc a jedno řešení. Navíc kritici často ani neví, že jazyk samotný prochází vývojem, používají patnáct let starý standard a pak argumentují úplně z cesty. S PHP zkušenosti nemám, tam nemůžu soudit.
Vykašli se na to oni jsou prostě uzavřený v krabici a nechtěji z ní vylézt. PHP je špatný protože mu nerozuměj a kompiler je neupozorní na chyby, takže je to jazyk k ničemu a nikdo v něm nedělá velký projekty, protože dřív nebo pozdějc tam programátor udělá chybu což u krásných super jazyků nejde tam se dá udělat jen krásnej kód kterej nikdy nemá bugy a neočekávatelný chování (třeba sonda co sebou mrskla o Marz kvuli zbastlenýmu kodu v super neomylnem jazyko Java pro opravdové programátory)
Milí hateři co třeba Python? Neřeší vizibilitu, můžete klidně setovat vnitřní stav objektu zvenku = pěkná prasárna. Nechá vás dědit spoustu tříd jen tak, klidně i dynamicky takže nevíte kdy může nastat problém. Ani na jedno z toho neupozorňuje kompiler. A dovolí si v celým vláknu se 160 příspěvkama něco říct proti Pythonu? NE
Nadávat na PHP je zkrátka stejně populární jako PHP samo, je to jen lenost naučit se něco víc a dostat se na vyšší úroveň a dát si práci s návrhem. Spoléhat se na to že si můžu kód prasit jak chci a vůbec nepřemýšlet o struktuře a architektuře protože na všechno mě upozorní kompiler, vede jen ke špatnému návrhu. Až budete mít někdy možnost podívejte se na Javské zdrojáky business logiky v bankách. Je to opravdu "osvěžující" zážitek.
U PHP bylo dynamické typování zvoleno pokud vím právě proto, aby to bylo snazší pro ne-programátory. Jak se ukazuje, záměr nějak nevyšel. Míst "nemusím se starat o složité věci typu typy" se z toho stalo "musím přesně vědět jakého typu co je, a znát hromadu quirks které to přináší". A to je jeden z důvodů, proč považuji PHP za špatně navržené. Resp. návrh zjevně neproběhl :/, a výsledek vypadá jako když pejsek a kočička vařili dort.
Jen drobnosti:
1. Například v Javě String na int přetypovat nejde. Musí se použít funkce, která (definovaným způsobem), provede konverzi. U primitivních typů můžete použít explicitní přetypování, Java pak konverzi provede na pozadí za vás. Vždy je to ale konverze.
2. Přetypování objektů v Javě hlídá typy. Takže když mi z ArrayListu přijde String a já to zkusím přetypovat na Integer, tak to hodí exception. Při kompilaci se o tom tedy nedozvím, ale za běhu mi to jasně řekne, že je problém a kde. Stále o řád lepší situace než když to akorát tiše vrátí něco jiného, než čekám.
3. Již řadu let umí Java typovat i seznamy (viz Generics). Takže mohu ArrayListu říct, že prvky budou Integer. A on mi to pak ohlídá všude už při komplikaci a pak i za běhu. Takže do něj ten String ani nepůjde vložit. Java obecně má snahu používat datové typy a vyždímat z toho aparátu maximum.
4. Java umí implicitní konverze. Takže vám dovolí porovnat int 0 s double 0.0 a výsledkem je shoda. Má pravidla, kdy kterou konverzi použije implicitně a kdy ne (na to upozorní už překladač). Takže například int na double vám převede, ale double na int už ne. Pořád mu to můžete přikázat přetypováním, teprve pak konverzi double na int udělá.
5. V C stringy neexistují. Implementují se jako pointer. A to jsou čísla. Pokud pointer přetypujete na číslo, tak výsledkem bude adresa, na kterou to ukazovalo, nikoliv hodnota, která tam byla uložena. Ano, je to oblíbený chyták na nové studenty. Není náhoda, že řada lidí pointery nenávidí.
Dá se říci, že co se "bezpečnosti při práci s typy" týká, tak PHP a Java jsou opačné extrémy. Oba poměrně snadno zvládnutelné. Je to pak o tom, zda vám víc vyhovuje "jedu si na vlastní triko" nebo "svěrací kazajka". Je ale dobré znát oba. Já osobně preferuji tu svěrací kazajku. Jsem "úzkostný typ" a dává mi to pocit sucha a jistoty.
Pokud v C porovnáváš int a float, int se implicitně přetypuje na float a porovnáváš dva floaty. Máš to ve specifikaci jazyka a není tam důvod, aby to řvalo.
String v C nemáš, takže se nestane nic. Máš jenom ukazatel na pole znaků, zakončený nulou. Porovnání intu s jakýmkoliv ukazatelem vyhodí zasloužený warning. Pokud je ukazatel dereferovaný, vezme prostě první znak a přetypuje na int. Tohle je jedna z věcí, kdy tě nevaruje, ale hvězdičky a pravý šipky se do programu zásadně nedávají, pokud nevíš, co to udělá.
A pole znaků do jednoho charu nenarveš, tam tě to taky upozorní, ať to omezíš na jeden znak, nebo si těch znaků uděláš celý pole.
Porovnání signed a unsigned jenom tak mimochodem taky bliká oranžově...
Pises to fakt takto?
if ( true === $variable )
To je jedna z nejvetsich prasaren, neprijde Ti to? Prece ten jazyk ti v "if" vyraz prevede sam na booleovske hodnoty, a ty jsou primo true nebo false. To bys taky mohl psat
if (true === (true === $variable)) a porad dal a dal.
Mno za toto se vyhazovalo od zkousky, a jestli je to v PHP takto nutny delat (nenapada me duvod), tak je to hooodne spatne navrzenej jazyk, ver mi.
"Mno za toto se vyhazovalo od zkousky"
To záleží kam jsi chodil do školy. To se tak píše proto, protože kdyby ti to ujelo (== nebo === ujelo do = ) tak ti to vyhodí chybu místo toho, aby ti to přiřadilo hodnotu do proměnné a prošlo to jako TRUE protože by se z toho nejednou stal pravdivý výraz (jenom proměnná s hodnotou). A taková chyba se fakt blbě hledá. Ale piš si to jak chceš
https://make.wordpress.org/core/handbook/best-practices/coding-standards/php/#yoda-conditions
http://stackoverflow.com/questions/6524276/how-can-i-define-certain-posts-only-if-a-variable-equals-a-certain-number
Nevím kam míříš, ale na ty odkazy jsi se asi nedíval.
Tak jinak Pokud chceš napsat
if ( $var == 1 ) a upíšeš se na if ( $var = 1 ) tak se to rovná if ( $var ) a to je TRUE.
Pokud to píšeš if ( 1 == $var ) tak to nepřehlédneš, protože ti kompiler/engine zařve, že se snažíš o blbost.
Jde pak ale o to, že if ( $var = 1 ) se při hledání problému snadno přehlédne a pro překladač to není chyba. Nejen PHP, ale ani C ani myslím Java tě neupozorní. A hledat takovou chybu po nocích je fakt zábava.
Na odkazy jsem se dival, chapu proc to tak asi musite psat, ja myslel jinej duvod. Kdyby tam dali priklad if (42 == $var) tak neni pochyb o tom, co a jak se dela a proc, ale u True je to (pro ==) naprosto zbytecny vubec psat.
Jinak Java ti samozrejme pri kompilaci zarve (az na jednu vyjimku souvisejici s jednim datovym typem), kazde slusne C o tomto vypise warningy, C++ samozrejme jakbysmet, PHP by taky mohlo psat warningy ne? (nejaky strict rezim to nema???)
Java pozná, C nepozná, PHP nepozná a ani nehlesne
--------------PHP---------------
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
?>
<html>
<head>
<title>Online PHP Script Execution</title>
</head>
<body>
<?php
if ( $var = 1 )
{
echo "nepoznal";
}
?>
</body>
</html>
----------------C------------
#include <stdio.h>
int main()
{
int cislo;
if ( cislo = 1 ) {
printf("Nepoznal\n");
} else {
printf("Poznal!\n");
}
}
Pro TRUE je assigment problém úplně stejný a to jestli tam máš == je jedno. Psal jsem ti, že je to kvůli tomu, když se upíšeš.
Aha, tak to je zajímavé, mě to vypsalo pouze : main a Nepoznal ale zkoušel jsem to online
http://www.tutorialspoint.com/compile_c_online.php
Ok. Moje chyba, každopádně pro benevolentní PHP to platí.
Ono se v tom online toolu da pres Project -> Compile Options to "-Wall" pridat do nastaveni prekladace, jinak to skutecne nepise. Potom uz jo, ted jsem to schvalne otestoval:
main.c:9:1: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Ale to je jedno, ta debata je o necem trosku jinem a obratit operandy u == v PHP evidentne ma vyznam, tak proc to nepouzit...
Jj, já už C dlouho nedělal a když jsem to zkoušel online u Javy tak to zařvalo, u C ne. Ona je tam i ta konzole v tom online toolu, tak jsem to pak po Vašem příspěvku zkusil na localhostu , přidal co jste psal a bylo hotovo. Moje chyba.
Ono v PHP ta konstrukce obrácených operandů je tam fakt jenom proto, aby se člověk neupsal někde v 1h v noci (nebo když kopíruje definici a řekne dopíšu tam == a mám podmínku) a pak to nehledal do rána, ale spousta lidí to nedělá, taky jsem to dlouho nedělal a pak jsem to objevil v nějaké článku alá "Mastering PHP ... " a začal jsem to používat. Za ty roky co dělám PHP jako výdělečnou činnost musím uznat, že 1 nebo 2 x se mi to upsání fakt stalo. Vtipné je že v začátcích, tak že by to nemělo být v "masterig ..." ale spíš v "At first .....". Ale třeba WP to má v Coding style, jen nevím kolik lidí si to přečte a používá, moc se s tím nesetkávám ...
Porovnání s true není prasárna proto, že je potřeba řešit porovnávací znamínko. Je to prasárna, protože true nemusí být true a pokud je, zvyšuje to režii už tak drahýho porovnání... Jednoznačně definovaná bývá hodnota FLASE a ne vždycky počítač pochopí, že chceš (x != FLASE) a myslí si, že chceš (x == JednaJedináDefinovanáHodnotaTRUE)
Třeba v C nejsou booleovský hodnoty, jazyk bere jako nesplněnou podmínku ("false") nulu, zbytek jako "true". Když chceš tyhle hodnoty používat, musíš si to definovat, nebo použít <stdbool.h>. Tahle knihovna definuje false=0, true=1.
A teď si představ:
int tlaciskoStisknuto() {
return PORT_A_IN & BIT14;
}
int zkontrolujTlacitko() {
if(TRUE == tlacitkoStisknuto()) {
rozsvitLED();
}
}
První funkce je korektní, vrací nenulovou hodnotu, pokud je tlačítko stisknuto a nulu, pokud ne. Ale program fungovat nebude. Právě kvůli zmršené podmínce se LEDka nikdy nerozsvítí. A jsou dvě možnosti, jak to opravit:
1) Úprava funkce pro detekci tlačítka. Vyžaduje dvě podmínky místo jedné (2x zahodit pipeline procesoru,...)
int TlacitkoStisknuto() {
int retval = false;
if((PORT_A_IN & BIT14) == BIT14) { // Trvas na pouzivani porovnavaciho operatoru, ale TRUE tady nefunguje
retval = true;
}
return retval;
}
2) Místo TRUE ve vyhodnocení použít BIT14. Je to porušení abstrakce hardware, takže si jako blbec musím hlídat, abych to v případě změny v programu změnil všude a ještě je to blbě z pohledu architektury.
3) Udělat to tak, jak se má. Prostě neporovnávat s TRUE.
int tlaciskoStisknuto() {
return PORT_A_IN & BIT14;
}
int zkontrolujTlacitko() {
if(tlacitkoStisknuto()) {
rozsvitLED();
}
}
Tenhle kód funguje spolehlivě, hardware je abstrahovaný, je rychlejší, rychlej napsaný, splňuje specifikaci jazyka.
U ostatních jazyků tu opičárnu s mezipřevodem hodnoty vyhodí kompilátor během optimalizací, pokud si to nevynutíš tím porovnáním s true.
A sorry, ale je jednodušší si pamatovat univerzální pravidlo "s TRUE se neporovnává, to smím jen vracet z funkce", než si pamatovat, jak se chovají ve stejné situaci dva různý operátory v závislosti na tom, jestli s TRUE porovnáváš int, float nebo instanci třídy... :/
Obdoba toho Vašeho
int zkontrolujTlacitko() {
if(tlacitkoStisknuto()) {
rozsvitLED();
}
}
je v PHP velmi velmi častá konstrukce. Ale PHP často manipuluje se stringy a == a === ulehčuje práci a proto je to asi zamontované tolik do toho jazyka.
Ale == a === jsou prostě specifika PHP, jsou situace kde se to dá z výhodou použít a kdo nechce, tak nemusí. Stačí používat === a nebo přetypovávat jako v jiných jazycích.
Vemte třeba konstrukci - velmi často používané pro zjištění jestli se řetězec vyskytuje v zadaném
strpos() - vrací pozici hledaného textu v řetězci - false pokud pozici nenajde
if ( strpos("hledaný", "prohledaný") !== false ) {
// do something
}
Ale ta funkce --vždy--- něco vrací, takže if ( strpos("hledaný", "prohledaný") ) použít nejde. buď vrátí pozici anebo false. Nulu vracet nemůže, protože string jako pole začíná s pozicí 0, takže pro výskyt na pozici 0 ( mohlo by při == být FALSE) a je to fakt jednoduší než psát reguláry ... kdyby vracel NULL je to to samé jako s false ....
A kde je v tomto komentáři jediný argument pro použití
if(TRUE == něco)
(resp. s jiným porovnávacím znamínkem)?
Btw, víš, že už starý hloupý Basic s číslama řádků měl rozlišený typy proměnných? Hned bylo vidět, jestli pracuješ se stringem (a$) nebo s číslem (b). Jenom takový šílenosti, jako PHP a JS, to dokážou pomíchat dohromady.
"A kde je v tomto komentáři jediný argument pro použití
if(TRUE == něco)
(resp. s jiným porovnávacím znamínkem)?"
Zde
"Vemte třeba konstrukci - velmi často používané pro zjištění jestli se řetězec vyskytuje v zadaném
strpos() - vrací pozici hledaného textu v řetězci - false pokud pozici nenajde
if ( strpos("hledaný", "prohledaný") !== false ) {
// do something
}
Ale ta funkce --vždy--- něco vrací, takže if ( strpos("hledaný", "prohledaný") ) použít nejde. buď vrátí pozici anebo false. Nulu vracet nemůže, protože string jako pole začíná s pozicí 0, takže pro výskyt na pozici 0 ( mohlo by při == být FALSE) a je to fakt jednoduší než psát reguláry ... kdyby vracel NULL je to to samé jako s false ..."
Prostě ta funkce nemůže při nenalezení vracet 0, protože by to mohlo vypadat že string hledaný je na pozici 0. Takže ty příklady, co jsi psal, kde se vracela 1 nebo 0 neplatí, protože v PHP když vrátíš int nak je to true, jako kdyby if ( $var ) { ..... proto striktní === baby to byla 0 od FALSE
V silně typovaných jazycích (dobře, například v Javě) podobná funkce vrátí -1, takže test bude na <0 nebo něco podobného. Neříkám, že je to lepší, podle mě moc ne :-)
Asi nejlépe to řeší jazyky, které dokážou z funkce vrátit víc hodnot - Lua, Forth atd. Takže vrátí jak logickou hodnotu (našel, nenašel), popř. ještě index od-do (protože se většinou dá hledat i podle regexpu).
ale to jen pro doplnění
Aha, díky, na -1 jsem úplně zapomněl. C už dlouho nedělám ale i tam se to myslím používá. Proč to tak není v PHP fakt nevím. Je možné že tou dobou když to dělali, tak všechny štvalo, že že se vrací 0, -1 nebo tak a tak asi použili tyhle booleany :-)
Ale jo, určitě je lepší vracet více hodnot. V PHP taková funkce asi není ale u user defined funkcí to jde.
> Ale ve stat. typovaných jazycích se ti to ale může stát taky, třeba v Jave ti může přijít proměná z ArrayListu a vůbec "nevíš" co tam je a už musíš přetypovat. Nebo v C ze struktury a jsi na tom samém, musíš si ověřit, co tam je.
Jak já mám rád jazyky, kde to vím :) Nebo úplně přinejhorším, kdy to třeba "musím" ověřit, jinak mě kompiler nepustí dál... Mimochodem, u trošku složitějšího projektu bych se osobně bez pořádných typů totálně ztratil. Nechci říct, že by to úplně nešlo, ale trvalo by mi to výrazně déle a bylo by v tom velké množství chyb.
Nevím jaké velké projekty děláte ale podívejte se na to takhle:
V PHP můžete mít třeba z XML velké jednoduše získané pole z různými dat. typy uvnitř. Jsou to třeba typicky výrobky a jejich atributy. Začnete to třídit (protože bývá rychlejší třídit to v kódu než to prát pokaždé do databáze a pak to nějak i kolikrát i šíleně muset JOINOVAT a GROUPovat a pak to zase třídit v kódu - měřil jsem, vím)
Vy s tím polem můžete manipulovat, přesýpat atd, ale přetypovat stačí jen ty hodnoty, které použijete v nějaké porovnání, což může být jenom třeba 1/10 ze všech které tam jsou. Typicky nějaké ID (číslo, ale z XML jako string ...). Pak dojde na databázi a tam třeba s PDO enginem natypujete jaké typy tam perete na jaké sloupce a je to. Vtip je v tom, že pokud z toho XML použijete jen ID a třeba jméno výrobku, tak Vás zajímají jen 2 proměnné a tedy 2 přetypování. Ve stat. typovaném jazyce by jste celou strukturu musel dopředu natypovat při načtení XML, jinak by platilo to, co jsem psal výše.
Tak tohle zrovna není dobrý příklad - kdo mi brání napsat si deserializaci, která mi z toho XMLka vytáhne jen to, co potřebuju? Jinak celý XML DOM jde krásně staticky natypovat, takže ho taky můžu krásně celý načíst a pak elegantně přes nějaké "lens" procházet (to je něco jako XPath, až na to že funguje na jakoukoliv datovou strukturu). DOM jde udělat staticky typovaný.
Nedávno jsou musel naprogramovat něco ve stylu "přečti XML, modifikuj, pošli zpátky". Velmi elegantní - zoom na část odpovídajícím kritériu, nastav optiony tak, jak potřebuju, pokud něco není, automaticky vytvoř... ta výhoda statického typování je třeba mimo jiné v tom, že při modifikaci se nebudu snažit dát do DOMu objekty, které tam nepatří - protože mi to kompiler odchytí.
Upřímně nevidím jedinou výhodu dynamicky typovaného jazyka - kromě toho, že ve staticky typovaných jazycích musí člověk začít tím, že se zamyslí nad tím, co bude dělat. U dynamicky typovaného to není zas až tak nutné...
On to dobrý příklad je. Víš, psal jsem vlastní parser na XML, které mělo zanoření i 40 levelů, bylo tam tolik hodnot že to server ani po úpravě velikosti paměti prostě nedokázal načíst, protože se to prostě nevlezlo na ramku, tak se to načítalo sekvenčně, Vím co je Parser XML a proto ti taky píšu, že když ti přijde třeba 150 výrobků, použiješ 1 funkci SimpleXML, projedeš to na 1 či 2 foreach a uděláš co potřebuješ, přetypuješ jen to co musíš a nebo použiješ v PHP automatické přetypování. Nevím kdo by ti kvůli takové easy task platil vývoj vlastního parseru abys tam přetypovával každou hovadinu kterou třeba ani nepoužiješ, jenom proto, aby ti neřval parser.
" Ty si fakt myslíš, že ve staticky typovaných jazycích něco jako SimpleXML neexistuje?"
Já ale nepsal o tom jestli existuje nebo ne, já psal o tom, jak lze v PHP lehce pracovat s rozsáhlými datovými atd poly aniž by jsi musel znát datové typy obsažených proměnných. A použil jsem k tomu jako ilustrativní příklad input v podobě XML. Nic víc.
Ilustrativní, ne přesný. Šlo prostě o to, že ty třeba v Javě nebo C, i když máš strukturu, arrayList, cokoliv, tak musíš předem znát, co tam bude za datové typy a v C myslím ještě i délku u chars[]. V PHP tě to nezajímá, tam máš prostě pole, a až něco z umístnění potřebuješ, teprve se staráš o datový typ. Ty si v C nebo v Javě můžeš dopředu vytvořit strukturu aniž by jsi věděl jaké tam budou datové typy?
Myslím, že v Javě je možné to natypovat na Interface, ne? Ale jinak za "rozumný" statický systém myslím systém, kde máš algebraické datové typy, takže můžeš říct "a v tomhle poli bude A nebo B nebo C". Přiznám se, že vůbec netuším, na co by mi bylo pole "a může tam být cokoliv". Když parsuju XMLko, tak je tam na začátku pouze "text", když si to naparsuju, tak je tam "to, co jsem tam naparsoval". V obou případech vím, co tam je a vůbec nepotřebuju strukturu "pole, kde může být cokoliv".
A k velikosti projektů a ztrácení: teď zrovna píšu nějaký websocket server, který má teď momentálně pár stovek řádek. Momentálně komunikuje dvěma různými protokoly. Víš jak je super, že ti kompiler nedovolí přiřadit "uuid akce" jako "uuid zprávy" (obojí je UUID, ale stačí tomu dát jiný typ a kompiler se postará), ... víš jak je úžasné, že napíšeš do kódu "decode" a vybere se správná dekódovací funkce dekódující ten typ, který potřebuješ - a ne, že se sekneš a vybereš funkci, která dekóduje něco úplně jiného? Že nemůžeš poslat zprávu kanálem, který je určen pro něco jiného?
Víš jak je super, že když změníš někde nějaký typ nebo uděláš nějaký větší refactoring, tak ti to při kompilaci napíše, cos všechno rozbil? A ve výsledku nemusíš na spoustu věcí psát testy, protože ti toho spoustu odchytí kompilátor. A to jde udělat i v C++ - nedávno jsem potřeboval upravit aplikaci, aby fungoval na big-endian stroji - jenže se s tím trochu nepočítalo při návrhu. Trocha hraní s typy a kompiler mi přesně řekl, kde musím přidat konverzi.
Tak je to asi takový rozdíl jako střílet s puškou bez zaměřovače a puškou s automatickým naváděním nábojů. Kung-fu mistr zenu to zvládne s tou první, já s velkou radostí použiju to druhé a budu s tím mít výrazně lepší výsledky než 99% těch, co používají první metodu.
Ano, povedlo se mi se v relativně krátkém kódu splést a omylem několikrát přiřadit ty uuid někam jinam, než jsem měl. Tak jsem to natypoval, "uuid akce" a "uuid zprávy" byl jiný typ a teď VÍM, že tento typ chyby nenastane. A můžu ti to dokázat. Zatímco v tvém dynamickém kódu to nevíš, a já ti musím věřit, protože o tom nedokážeš vůbec nic.
"Tak je to asi takový rozdíl jako střílet s puškou bez zaměřovače a puškou s automatickým naváděním nábojů"
To ale není příměr k tomu těm jazykům, spíš je to odraz tvých pocitů.
"natypoval, "uuid akce" a "uuid zprávy" byl jiný typ a teď VÍM, že tento typ chyby nenastane"
A když já v PHP udělám
$a = array(
"uuid akce" => "1000",
"uuid zpravy" => "11111"
);
dajToTam($a["akce"], $a["zpravy"] );
Tak se v dajToTam taky nespletu a nemusím vytvářet milon deset nových datový typů abych si ohlídal co mi kam leze. To ale o jazyku nic nevypovídá. jen o tom, že pokud ti kompiler nezařve, tak nemáš ohlídané co kam leze. A na vstupu z venku to musíš ohlídat vždy. A nebo nemusíš ale pak se občas divíš ....
Tak ale tady není stěžejní co jsi napsal, ale tam kde přiřazuješ ty datové typy. No odněkud se ti vzít musí. Někde je musíš deklarovat a definovat. Já to udělal v tom poli. To je pro mne kritické místo. Pro tebe je kritické místo tam, kde vezmeš input a rozhodneš se, že tohle bude actionid a támhle to bude msgid. Já to rozhodl v tom poli, ty nevím kde .. někde to tam bude ......
No to víš že nezmění. Jenom jsi to obalil do funkce. Ale jak jsem psal. Já můžu podělat to přiřazení když ty IDčka přiřazuji k indexům v poli, ty to můžeš podělat když IDčka přetypováváš - prostě stejně jako já je můžeš prohodit a pak už nezáleží na tom, jaké máš datové typy v parametrech funkce - typy parametrů funkce se vyslovují k tomu, jaké tam pereš datové typy proměných, ne k tomu, jestli je v poroměných to které správné IDčko. Chápeš?
stringy třeba z toho xml - prostě nějaký input do programu
// uuid_zpravy = 111, uuid_akce = 222
uuidzpravy u_zpravy = uuid_akce;
uuidakce u_akce = uuid_zpravy;
funkce (uuidzpravy prom1, uuidakce prom2 )
{
// Jak ti pomůže kontrola datového typu?
}
Jenomže explicitní typecast je vědomá věc. Osobně dávám typecasty až po tom, co dostranu warning a zkontroluju si, že je všechno v pořádku.
Tvůj příklad je o něčem jiným. Ty ses dostal na tuhle úroveň:
SetAttribute("Height", 120);
SetAttribute("Color", Gray);
a když omylem napíšeš
SetAttribute("Color", 120);
tak žiješ ve sladké nevědomosti.
ST kompilátor na to jde jinak:
typedef int Height;
typedef enum Color { ... };
...
void SetColor(Color color) {...}
...
SetColor(120); // Kompilator je lehce nastvany, protoze 120 není barva
Pravděpodobnost záměny tohoto typu je stejná, ale liší se možnosti jejího odhalení před ránou pěstí od zákazníka.
A ještě jedna věc - na základě typu proměnné si můžu přetížit funkce a operátory. Místo, abych si pamatoval funkce heightToString(), widthToString(), sizeToString(), colorToString(), massToString(),..., stačí bohatě jedna, toString() a kompilátor si vybere podle známýho typu, nebo řekne, že neví, jak z toho ten string udělat. Typy dat si rozmyslím předem a pak už jenom píšu algoritmus nezávisle na typu. Ty můžeš klidně použít massToString na baru a divit se, že dostaneš pro černou místo "black" hodnotu "0kg"...
A když se rozhodnu, že místo výčtu budu používat strukturu RGB nebo název ve stringu, změním to na jednom místě, většina projde a kompilátor si řekne, kde je problém ("modul x.cpp, line y: cannot compare structure with integer"). Kdežto ty v podobné situaci něco změníš na 49 místech a dalších 51 zůstane netknutých... A pokud jsou operátory, funkce a metody definovány pro nový typ, kompilátor si je zvolí automaticky, ani nemusím sahat do kódu.
Ne, nic takového jsem nepsal. Resp. pokud si pod pojmem hodnota představíš spíš typ. Myslel jsem přesně to, co pisatel výše. Prostě eliminuješ spoustu chyb typu prohození parametrů. A výsledkem toho pak třeba je, že po půl dni kódování program konečně přeložíš, spustíš - a on funguje.
Z tvého příspěvku ....
"Víš jak je super, že ti kompiler nedovolí přiřadit "uuid akce" jako "uuid zprávy" (obojí je UUID, ale stačí tomu dát jiný typ a kompiler se postará),"
Ale jde o to přiřazení. Já ti ukázal jak to jednoduše vyřeším v PHP a pokud to nespletu při přiřazení tak je to ok. A už jsem ti psal, že typová kontrola (viz. výše) ti přiřazení správných hodnot nezajistí. Stále jsi mi neukázal, jak zařídíš to, že do tvých nových datových typů nepošleš špatné hodnoty a když už, tak "ti kompiler nedovolí přiřadit "uuid akce" jako "uuid zprávy" (obojí je UUID, ale stačí tomu dát jiný typ a kompiler se postará),""
Protože ty přijímáš odněkud vstup a to že ho přetypuješ jak chceš ti správné hodnoty nezaručí. Jen správné typy. A mě kompiler v PHP sice nezahlásí špatný datový typ u parametru funkce, ale to je jedno, protože pokud jsem přiřadil po inputu správné hodnoty v tom poli, tak je to správně a žádný kompiler řvát nemusí ani koontrolovat datové typy.
Ale tak do toho pořád se točíme v nějaké tvé abstrakci, tak ukaž kousek kódu, já kousek napsal a hned víme, tak se pochlub ....
> Protože ty přijímáš odněkud vstup a to že ho přetypuješ jak chceš ti správné hodnoty nezaručí. Jen správné typy. A mě kompiler v PHP sice nezahlásí špatný datový typ u parametru funkce, ale to je jedno, protože pokud jsem přiřadil po inputu správné hodnoty v tom poli, tak je to správně a žádný kompiler řvát nemusí ani koontrolovat datové typy.
?? Takže používat přilbu je na nic, protože když spadnu z mostu, tak se stejně zabiju? Rozumíš co znamená "eliminuješ spoustu chyb typu prohození parametrů"?
"Takže používat přilbu je na nic, protože když spadnu z mostu, tak se stejně zabiju? Rozumíš co znamená "eliminuješ spoustu chyb typu prohození parametrů""
Já se nevykašlal na kontrolu, jen je na mě co si zkontroluji a jak
- v tvém příkladu ->
jakou přilbu si vezmu a jak si ji nasadím je na mě. Ty si nasazuješ pořád stejnou přilbu datové kontroly, já si mohu jednou nasadit přilbu kontroly dat. typu, jindy zase kontrolu dat. typu + kontroly rozsahu a hodnot. a nebo klidně žádnou protože když budu na 100m skále a pode mnou nic, tak taky mohu dojít k názoru, že mi přilba akorát přidává váhu a blbě se mi leze a tím mám větší šanci že spadnu a ze 100m výšky mi opravdu nepomůže. Aspoň vidíš, jak je ten příměr špatný, protože se dá ohnout jak kdo chce a k ničemu nevede. Nic víc
Jo, jde o přiřazení. Ale jak v tom vtipu, jak byly přijímačky k policajtům. Přišlo tam 10 uchazečů a dostali tu dětskou skládačku, jak dáváš tvary do děr. Dva byli přijati pro nadměrnou inteligenci, osm pro nadměrnou sílu.
Tady prostě z jedné funkce lezou čtverečky, ze druhé kolečka. Kolečko nenarveš do čtvercové díry, čtvereček nenarveš do kulaté díry. Bez vědomýho použití nadměrné síly (typecast) nebo opracování (konverzní funkce).
Tobě ty tvary lezou z želatiny a chybí ti tam ta deska s tvary pro vstupní parametry funkcí, proměnný jsou taky jenom univerzální kyblíky na želatinu. Cokoliv nacpeš kamkoliv.
Ach jo. Přilba ti pomůže v 70% když s sebou třískneš na silnici. No jo, ale jak ti pomůže, když spadneš ze skály? Nepomůže. Ergo přilba je na nic. Navíc nechápu proč dáváš tak nesmyslné případy, proč bych nastavoval uuid přímo v kódu?
Jinak já to mám ještě vtipně tak, že mám datové typy "Zpráva" a "Akce", ta UUID se deserializují přímo ze zdrojových dat a k "raw UUID" nikde není přístup. Takže k tomu prohození prostě nedojde. Nikde.
"Navíc nechápu proč dáváš tak nesmyslné případy, proč bych nastavoval uuid přímo v kódu?"
A kde ho nastavuješ? Ve věštící kouli? Tak se předveď, pořád jenom tvrdíš že je to jinak a jinak a jinak no a tak jak to teda máš tak skvěle že to nikde nenastavuješ a přesto to máš v kódu?
Dekóduju ho z nějakého vstupu... a zhruba tak následovně:
data Message = Message MsgUUID Text
parseJSON obj = Message <$> obj .: "uuid" <*> obj .: "content"
data Action = Action ActionUUID [Step]
parseJSON obj = Action <$> obj .: "uuid" <*> obj .: "steps"
(Řádka "data" definuje objekt, který má 2 nepojmenované položky. To druhé je funkce, která parsuje Json vstup v poněkud zkrácené notaci, v zásadě si to představ jako Message{obj["uuid"], obj["content"]}). Případně můžu vygenerovat nové, pokud někde potřebuju.
A můžu si v kódu dělat co chci, ale pokud vyloženě někde neřeknu "převeď ActionUUID na MsgUUID", tak se mi prostě nikde nestane, že bych do funkce, které očekává UUID zprávy poslal UUID akce. Tohle je navíc poměrně primitivní, člověk ani nepotřebuje moc silný typový systém, v C++ by to šlo taky. Samozřejmě, pokud se rozhodneš, že si uškodíš, tak ti taky nikdo nebrání, ale při normálním používání ti tohle prostě eliminuje obrovskou třídu chyb. A to je navíc trošku vyšší dívčí - chápu, že v PHP neřešíš, že by sis splet 2 UUID, tam je řešíš, že jsi schopen tam narvat místo UUID číslo a dokud to někdo nespustí, tak si toho nikdo nevšimne.
No vidiš a já mám místo
Message{obj["uuid"], obj["content"]})
tohle
$a = array(
"uuid" => "1000",
"content" => "11111"
);
Jaký je v tom rozdíl? Pokud ani jeden z nás neposere to prvotní přiřazení, tak je to ok a pokud máš funkci
funkce ( uuid )
a napereme tam
funkce( Message->content )
resp.
funkce( $a["content] )
Tak to je programátorova chyba.
Dále, kompilátor v tvém případě zařve a ale za běhu, až tam ( do obj["uuid"]) někdo něco pošle co tam nemá být (jiný dat typ než v obj[uuid] čekáš) , program buď padne, nebo to ošetříš vyjímkou ......... jakkoliv ...... a uvnitř funkce funkce( Message->uuid ) po úspěšném předání uuid pak musíš ověřit, jestli je proměná v určitém rozsahu třeba, nebo jestli je uuid validní atd., nehledě na to že C pokud vím ti lehce ze stringu při přetypování, třeba v Message{obj["uuid"], obj["content"]}), lehce udělá číslo z bitů na dané adrese (to kdyby ti někdo do uuid poslal třeba "ahoj" místo "12345" - což by se ti na webu PHP klidně mohlo u formuláře nebo XML stát ... ) .....
No a mě to nepadne, ale zase si ve funkci funkce( $a["uuid] ) budu muset ošetřit že uuid je správné jaké chi - typ - rozsah hodnot prostě všechno, ale jak jsem psal, do té doby mne to nezajímá .... jinak taky reagovat vyjímkou ...... něčím ....
> Tak to je programátorova chyba.
No vidíš, a překladač tuhle chybu odhalí. A o tom to je. A protože já tyhle chyby dělám docela často (obzvláště, když má nějaké funkce víc parametrů), tak jsem moc rád, že za mě překladač tyhle chyby odhalí.
> Dále, kompilátor v tvém případě zařve a ale za běhu, až tam
Pokud tam uživatel pošle špatná data, tak je to chyba uživatele, ne programátora a těžko na to něco přijde při kompilaci - ale na druhou stranu, lze napsat program, který ten vstup validuje, a pokud tam uživatel dá číslo, tak se to bude chovat slušně.
> jestli je uuid validní
což přesně předchozí kód dělá.
Jinak, protože to zřejmě vůbec nechápeš (a to nemyslím špatně, já jsem to taky objevil poměrně nedávno), kompletní produkční kód, který vypadá následovně:
instance FromJSON Message where
parseJSON = withObject "Message" $ \obj -> Message <$> obj .: "uuid" <*> obj .: "content"
Tak je cca. ekvivalentní následujcímu kódu v nějakém jazyku bez typové kontroly:
parseJSON (Json json) {
Object obj = toObject(json);
if (obj == null) return (null, error("Message object expected."));
Json val = obj.lookup("uuid");
if (val == null) return (null, error("UUID key not found"));
(UUID uuid, res) = UUID.parseJSON(val);
if (res != ok) return (null, res);
val = obj.lookup("content");
if (val == null) return (null, error("content key not found"));
(Text text, res) = Text.parseJSON(val);
if (res != ok) return (null, res);
return Message(uuid, text);
Ta funkce nehází žádné výjimky, všechno kontroluje, všechno konvertuje, pokud nesedí data, vrátí chybu. Zkus se zamyslet, jestli takovýhle kód píšeš (a kolik chyb tam uděláš, kolik věcí zapomeneš zkontrolovat). Já ten kód výše píšu naprosto běžně a prostor pro chybu je výrazně menší.
"Tak to je programátorova chyba."
Jo, to je ta benevolence PHP. Spoléhá na programátora že ví co udělal.
"Pokud tam uživatel pošle špatná data, tak je to chyba uživatele"
A proto nám některé ty programy tak často padají nebo přetěkají - napadá mě buffer overflow útok na Apachi to tuším bylo .....
"jestli je uuid validní"
Nekontroluje, kontroluje jenom jeho datový typ. Ale to nevadí, to už je jenom procedura na ověření vstupu že uuid nemáš třeba 12345678910 [ int (11) ] a nebo nějaké opravdu existující - nevím jak ty, ale na webu platí, že žádným vstupním datům nesmíš věřit viz SQL Injection třeba
Tak jako ale ty jsi ten kód, obalil do funkce, a říkáš jak je to rychlé a mě jsi tu hodil střeva té funkce a říkáš jak je to na prd ..... Navíc to co jsi napsal není správně
$myjson = parse_decode ( $input_data );
Tolik mi stačí, abych s tím v PHP mohl manipulovat jako s polem pokud nebudu ověřovat validitu a když pak zkusím zavolat klíč pole, který tam není, tak to taky vyhodí chybu jako tobě v "parseJSON = withObject "Message" $ \obj -> Mess" .
A samozřejmě taky to převede do datových typů a pak, až někdy budu chtít manipulovat třena s uuid, tak si ověřím, jestli tam je, takže ty, každou tu hodnotu, která přijde musíš někde v tom parseJSON = withObject nadefinovat, já ne, až to někdy budu potřebovat, tak si to z toho pole vytahnu a nebo taky ne a nemusím nikam na začátek deklarovat a oddeklarovat když to nechci a zase deklarovat když to budu zase chtít. Ti píšu, to je jenom o jiném přístupu k věci .... Tebe ta kontrola datového typu zavazuje to všechno minimálně deklarovat hned na prvním místě. Já nemusím, ale zase si to pak musím ověřit sám. Jako nevím jak ti to vysvětlit, jde o to, že já sice nemám statickou typovou kontrolu vstupů (A netvrdím že je to špatně) jen k tomu musíš přistupovat jinak. Zkus si třeba napsat tohle
function mojeFunkce( $var ) {
}
> Jo, to je ta benevolence PHP. Spoléhá na programátora že ví co udělal.
A můžeš mi vysvětlit, co by mi to mělo přinést? Že dokážu vylézt na stěnu bez jistícího lana a občas se při tom nezabiju?
> Nekontroluje, kontroluje jenom jeho datový typ. Ale to nevadí, to už je jenom procedura na ověření vstupu že uuid nemáš třeba 12345678910 [ int (11) ] a nebo nějaké opravdu existující - nevím jak ty, ale na webu platí, že žádným vstupním datům nesmíš věřit viz SQL Injection třeba
No právě - kontroluje:
> decode "[\"ba4f7c4b-3957-4aa5-9b9e-6a269873ceb1\"]" :: Maybe [UUID]
Just [ba4f7c4b-3957-4aa5-9b9e-6a269873ceb1]
> decode "[\"ba4f7c4b-3957\"]" :: Maybe [UUID]
Nothing
> $myjson = parse_decode ( $input_data );
> decode "[1,\"test\",null]" :: Maybe Value
Just (Array [Number 1.0,String "test",Null])
Chceš flexibilitu? Nikdo ti nebrání...
> Zkus si třeba napsat tohle
dosomething (Number num) =
dosomething (String test) =
... a warning od překladače, že jsem neošetřil všechny možnosti...
dosomething _ =
> ti přijde uuid v JSON v jiném datovém typu než čekáš nebo tam vůbec nebude? Prostě to někdo zmrví?
Výsledek (abych byl teda přesný) je buď "Nothing" nebo "Just value" (ať žijí jazyky s algebraickými typy). To znamená, že následně když chci ten výsledek použít, tak to musím "rozbalit" a nějak pořešit to, že to může vrátit Nothing. Jinak mě k té hodnotě překladač nepustí. Takže VÍM, že jsem chybový stav nezapomněl ošetřit..... Anebo to natvrdo přiřadím, ale pak mě překladač varuje "tady neošetřuješ návratovou hodnotu!".
> Nehledě na to, že kdyby ti těch parametrů přišlo 150 a používal jsi je na 25 místech, což na webu není nic neobvyklého, tak z toho porodíš . . .
Dobře, tak jen taková ukázka, kam vedou extrémně silné typové systémy (protože ty pořád vidíš tu Javu). Máš JSON pole objektů, vytáhni z toho seznam atributů "jmeno". Můj kód je tohle:
pointer = _Array . traverse . _Object . key "jmeno" . _Text
vratJmena = toListOf pointer
A nebo ještě větší magie - najdi ta jména a prohoď je v existující struktuře, aby byla obráceně:
otocJmena = over pointer Text.reverse
A tahle magie prostě nejde bez silného typového systému. A fakt to nespadne, když to narazí na číslo místo jména. Nevím, co myslíš pod pojmem "flexibilita", ale mě tohle připadá extrémně flexibilní v dobrém slova smyslu. A chápu, že ti na FP vadí tisíce funkcí... ale když místo 10ti řádků kódu to napíšu na 1 a ještě ke všemu s plnou kontrolou všech možných chyb, tak to za to stojí, nemyslíš?
No to pozor, už několikrát jsem psal a myslím i tobě, že proti jiným jazykům nic nemám. V C jsem pravda nedělal ani skoro nepamatuji, Android J ještě nedávno ale živí mě PHP a ten jazyk má spoustu výhod ale taky pár nevýhod. Uznávám. A tisíce funkcí mě na FP fakt nevadí. PHP jich má tak bžilión ...
Jde o to, že si nemyslím, že je PHP na prd, protože nemá typovou kontrolu.
Jo kdyby jsi třeba napsal, == a === je v PHP na prd, protože si v kódu po někom nemůžeš být jistý tím, že programátor věděl co dělá a neflákl to tam z neznalosti, nebudu mít jinou možnost než napsat, OK, je to prostě tak a je to nevýhoda takového principu porovnání.
Podívej:
Vždy jsem ti psal, že si musím v PHP pohlídat, co mi přišlo za dat. typ a hodnotu do proměnné. Prostě to ošetřit. Sám.
Ty mi ukazuješ že je všechno na jeden řádek, ale ejhle, jak jsme vzali kód, tak jsem zjistili, že ty sice tak jako já nemusíš, ale zase musíš psát kontroly a vyjímky na použité funkce a když "Rozbaluješ proměnou", nebo jak to píšeš, tak dát bacha, aby jsi do funkce nepředal Nothing místo toho uuid. Upozorní tě na to kompiler, ale to je při překladu, při běhu aplikace, při nějakém dementním vstupu(třeba neúplný ten JSON), ti to padne, pokud jsi poctivě neošetřil všechno, co by takhle mohlo nastat. A jsi zhruba tam kde já s PHP, protože se nad tím taky musíš zamyslet a ošetřit a ovyjímkovat všechny možné error stavy.
Pravda tobě pomáhá kompiler, samospásný ovšem taky není.
Ale pozor, necpu ti PHP ani netvrdím, že je nejlepší. Nejlepší jazyk jaký jsem měl při svém omezeném rozhledu vidět, byla LUA. Ale Celkem mám rád i C a Javu, i Javascript i SASS. Jde ale o to, že každý ten jazyk má něco do sebe, ale také nějaké nedostatky. Některý více, některý méně.
> že ty sice tak jako já nemusíš, ale zase musíš psát kontroly a vyjímky na použité funkce a když "Rozbaluješ proměnou"
Ty asi nerozumíš psanému textu. Pojem "ošetřit" v tomhle případě znamená udělat něco, aby to nevyletělo na výjimku. Neošetřit znamená, že to vyletí na výjimku. Já nemusím dělat ani o ň víc, než ty v PHP. Ale to, kde to neošetřím mi pěkně vypíše kompiler.
> nebo jak to píšeš, tak dát bacha, aby jsi do funkce nepředal Nothing místo toho uuid.
To nejde... když funkce bere UUID, tak musí dostat UUID a ne nějaké Nothing.
> Upozorní tě na to kompiler, ale to je při překladu, při běhu aplikace, při nějakém dementním vstupu(třeba neúplný ten JSON), ti to padne, pokud jsi poctivě neošetřil všechno, co by takhle mohlo nastat
A kompiler ti v podstatě řekne, že jsi neošetřil všechno, co by mohlo nastat, případně, kde jsi to neošetřil.
> A jsi zhruba tam kde já s PHP, protože se nad tím taky musíš zamyslet a ošetřit a ovyjímkovat všechny možné error stavy.
No právě že nejsem, protože mě přesně překladač řekne, co jsem kde zapomněl... takže se nad tím můžu zamýšlet podstatně méně a řešit jiné věci než to, kde jsem zapomněl co zvalidovat... Ta funkce pro parsing té Message je produkční kód. Dělá to to, co jsem rozepsal. Pokud ty nepíšeš takovýmhle způsobem dekódování JSONu, tak já mám kód, který validuje vstupy a ty ne - a když už jsme u toho provnání, tak co když někde v kódu budeš porovnávat nějakou část JSONu s číslem a v tom JSONu bude místo čísla md5 hash začínající "0e"... Takže jsme fakt někde úplně jinde. PHP je hračka a ještě ne moc dobrá.
"Já nemusím dělat ani o ň víc, než ty v PHP"
Však to jsem ani netvrdil. Ty tvrdíš že já toho musím dělat více, já říkám že oba musíme ošetřit errorové stavy a kontrola datových typů všechny errorvé stavy neodchytí (To bylo totiž původně jestli si vzpomínáš tvůj argument na začátku,že když dáš datový typ uuid na proměnou tak je hotovo a vše zařídí kompiler - klidně se podívej zpět).
"To nejde... když funkce bere UUID, tak musí dostat UUID a ne nějaké Nothing."
A to je právě to. Psal jsi, že pokud budeš mít v JSON něco jiného než to uuid, tak to tam dá hodnotu Nothing a to asi validní uuid není, že?
"Výsledek (abych byl teda přesný) je buď "Nothing" nebo "Just value" (ať žijí jazyky s algebraickými typy). To znamená, že následně když chci ten výsledek použít, tak to musím "rozbalit" a nějak pořešit to, že to může vrátit Nothing" __o příspěvek výše__
"A kompiler ti v podstatě řekne, že jsi neošetřil všechno, co by mohlo nastat, případně, kde jsi to neošetřil."
Jo? A když spustíš program na ostro a něco se vyskytne, tak ti to taky zahlásí kompiler? Nebo uživatel?
Mám spíš pocit, že kompiler ti zahlásí rozpory jenom v mu tu dobu známých souvislostech.
Ale pojďmě konkrétně:
Ty musíš na žádost kompileru ošetřit
1. abys uuid variable = Nothing z parseru (pokud bude v JSON něco blbě) nevložil do funkce xyz ( uuid varible ), nebo že při parsování máš něco Nothing a nepokračuješ, whatever ....
a já si mohu dát do xyz ( variable ) co chci, ale ! pak si to musím zvalidovat minimálně na datový typ (pokud to potřebuju). To je taky jeden řádek.
A to je taky to co se ti snažím vysvětlit, že kontrolu na error stav musíme udělat oba dva, ty při parsování resp. jeho výsledku, já až při použití uuid ve funkci. Rozdíl je v tom, že já s PHP, když se za dva dny rozhodnu že uuid ve funkci nepoužiju, tak nemusím oddělávat deklaraci datového typu v parseru JSON jak tam máš nebo v definici nového datového typu aby mi tam nezůstával balast po věcech které už nepoužívám.
Druhý výhoda dyn. typovaného jazyka je, že si můžu lehce předávat do funkcí co chci a nemusím všechno typovat, a můžu až uvnitř funkce řešit co s tím budu dělat. Můžu lehce plnit pole a procházet ho aniž bych někde musel jediným slovem zmínit datový typ.
Nebo taková hezká věc, ten uuid ti probublá dolů pěti funkcemi (zanoření - atomizace) až k té tvojí xyz( uuid variable ) a pak se rozhodneš, že bude jiného datového typu (třeba se změní zákazníkův požadavek - u webu naprosto běžné) a jdeš u všech to musíš změnit. I v parseru JSON. Já ne, jen tam kde ho používám .............
Ale jako neříkám že hlášky kompilátoru jsou k ničemu, jen v dyn. jazycích je prostě k věcem jiný přístup, tak to už pak není taková killer feature.
Ostatně jak tu někdo psal, třeba v té stat. typ. Jave nikdy nikdo nepoužil killall java protože po kompilaci je bez program chyby a já přidám známé NUllPointerException, kdy program projde kompilátorem, ale při běhu se stane, že ne vše je ideální jako při kompilaci a až dojde na vstupy z venku, třeba databáze, tak to najednou začne lítat.
" takže se nad tím můžu zamýšlet podstatně méně a řešit jiné věci než to, kde jsem zapomněl co zvalidovat... "
Ano méně se zamýšlet se nad tím, co přesně program dělá je opravdu výhoda ;-) Ne, nepodezřívám tě z toho že by jsi nebral kód vážně, ale jde o to , že u dyn. typovaného jazyka tolik a furt ty typy u všeho neřešíš, takže jim zase tolik pozornosti věnovat nemusíš. Ale je fakt že to záleží na tom co zrovna píšeš.
A neboj se, třeba z té Javy a C jsem si odnesl pár věcí které používám a souvisí to s větší typovou kontrolou pro co dělám + taky mám rád přehled o tom co mi kde lítá akorát PHP to po mě nevyžaduje, je to jen na mém uvážení.
Třeba konkrétně v PHP je možnost do funkce udávat dat. typy --- ale jenom objektů. Takže na ten tvůj příklad, mohl bych si Javovsky udělat class Uuid {} kam bych to uuid dal přes getter() nebo konstruktor a pak si napsat funkci xyz( Uuid variable) a PHP by mě upozornilo pak na to že tam rvu něco jiného. Ale ono to není tak často potřeba .....
Opět ale dodávám, proti FP nic nemám, proti stat. typovaným jazykům taky ne, jen tvrdím, že dyn. typovaní jazyk nejsou na prd.
> Ty tvrdíš že já toho musím dělat více, já říkám že oba musíme ošetřit errorové stavy a kontrola datových typů všechny errorvé stavy neodchytí
Když odchytí 90% errorových stavů, tak ty toho musíš 10x tolik....
> A to je právě to. Psal jsi, že pokud budeš mít v JSON něco jiného než to uuid, tak to tam dá hodnotu Nothing a to asi validní uuid není, že?
Mě se nechtělo zabíhat do detailů, ale když to někde uprostřed dekódování selže (není tam správné UUID), tak selže CELÉ to dekódování, ne že to do té struktury narve Nothing - to totiž nejde. A celkový výsledek dekódování následně je buď Nothing nebo (Just message), já si to z ní musím rozbalit, abych to mohl dál používat. A v té struktuře ta položka "uuid" je prostě UUID, žádné Nothing. Když to chci jinak, můžu, ale já to většinou chci takhle.
> Jo? A když spustíš program na ostro a něco se vyskytne, tak ti to taky zahlásí kompiler? Nebo uživatel? Mám spíš pocit, že kompiler ti zahlásí rozpory jenom v mu tu dobu známých souvislostech.
Kompiler ti řekne: funkce "decode" může selhat (tzn. vrátit "Nothing"), ale ty variantu Nothing neošetřuješ.
> 1. abys uuid variable = Nothing z parseru (pokud bude v JSON něco blbě) nevložil do funkce xyz ( uuid varible ), nebo že při parsování máš něco Nothing a nepokračuješ, whatever ....
Ne, vzhledem k tomu, že ta Message byla definovaná jako "Message UUID Text", nikoliv jako "Message (Maybe UUID) Text", tak ta první položka ve struktuře Message může být jen a pouze UUID a nic jiného. Já to nemusím nikde validovat - já to vím, kdekoliv v kódu a nikdy tam nic jiného přiřadit nelze.
> Nebo taková hezká věc, ten uuid ti probublá dolů pěti funkcemi (zanoření - atomizace) až k té tvojí xyz( uuid variable ) a pak se rozhodneš, že bude jiného datového typu (třeba se změní zákazníkův požadavek - u webu naprosto běžné) a jdeš u všech to musíš změnit. I v parseru JSON. Já ne, jen tam kde ho používám .............
Datová deklarace:
data Message = Message UUID Text
parseJSON (Object obj) = Message <$> obj .: "uuid" <*> obj .: "content"
Hádej, co přesně musím změnit, pokud budu chtít UUID změnit na Int?
> a já přidám známé NUllPointerException, kdy program projde kompilátorem, ale při běhu se stane, že ne vše je ideální jako při kompilaci a až dojde na vstupy z venku, třeba databáze, tak to najednou začne lítat
A já to zrovna ukazuju příklad typového systému, kde k NullPointerException dojít nemůže.
> Ne, nepodezřívám tě z toho že by jsi nebral kód vážně, ale jde o to , že u dyn. typovaného jazyka tolik a furt ty typy u všeho neřešíš, takže jim zase tolik pozornosti věnovat nemusíš
A to je velká chyba, protože ty typy tam stejně při runtimu jsou. A speciálně u jazyků se silnými typy se z toho typového systému stane nástroj, který prostě používáš. Jednak k psaní korektního kódu, ale především proto, aby ten překladač psal kód za tebe. Všimni si, kolik kódu za mě napsal překladač, když jsem mu tu jednu řádku napsal. Nebo to procházení té JSON struktury - kolik foreach cyklů a kontrol jsem si ušetřil.
> Opět ale dodávám, proti FP nic nemám, proti stat. typovaným jazykům taky ne, jen tvrdím, že dyn. typovaní jazyk nejsou na prd.
Já jsem dlouho programoval v Pythonu. A můj závěr z posledních 2 let programování v Haskellu je, že na prd jsou. Třeba jenom konkrétně ta práce s JSONem je totálně o něčem jiném.
Hele jde jenom o to, co od toho jazyka čekáš. Pokud je třeba někdo konzervativní, tak mu třeba vyhovuje C nebo já nevím, každého věc.
"Kompiler ti řekne: funkce "decode" může selhat (tzn. vrátit "Nothing"), ale ty variantu Nothing neošetřuješ."
A co když mě to nezajímá? Co když mě tam zajímá jenom jestli je to int tak to použiju a jinak ať se mi do toho kompiler neser..... To bych pak musel dávat ignory na hlášky kompileru, myslím že to jde pomocí @ .... nějak u stat. typ jaz. A pak když se změní podmínky to zase validovat, protože to nic nevypíše a tak ..... Jako celkem s tím nemám problém, je to prostě jiný styl práce v kódu .... ale ať jen nekecáme
I se všema kontrolama komplet i s parserem a s hláškama do loggeru, stačí zkopírovat do scriptu a pustit, klidně jsem zaběhl do detailů. Čas: 5,5 minuty
"Mě se nechtělo zabíhat do detailů, ale když to někde uprostřed dekódování selže (není tam správné UUID), tak selže CELÉ to dekódování, ne že to do té struktury narve Nothing - to totiž nejde"
$json = json_encode( array(
'uuid' => 1111,
'content' => "5555"
) );
>>>>>>>>
if ( NULL == ($jsonData = json_decode($json, TRUE)) ) {
// ERROR MESSAGE
}
if ( ! isset($jsonData['uuid']) || ! isset($jsonData['content']) ) {
// ERROR MESSAGE
}
if ( ! is_numeric($jsonData['uuid']) || ! is_numeric($jsonData['content']) ) {
// ERROR MESSAGE
}
function exampleFunction( $uuid, $content ) {
if ( ! is_int($uuid) ) {
$uuid = intval($uuid);
}
if ( ! is_int($content) ) {
$content = intval($content);
}
// Done
}
exampleFunction( $jsonData['uuid'], $jsonData['content'] );
Netvrdím že je to nutně skvělé nebo lepší, jen to není žádný problém.
@janek
ale to dalsi pouziti (Java-8 style pseudokodem)
Optional<Configuration> foo = parse(configFile)
Optional<ConfigActions> actions = foo.map(Configuration it -> actionsFrom(it))
(slo by to lepe, napriklad bez Configuration u it, protoze typova inference, tady to mam jenom kvuli citelnosti zacatecniky)
"slo by to lepe, napriklad bez Configuration u it, protoze typova inference, tady to mam jenom kvuli citelnosti zacatecniky"
Tak to mě zas tolik nevadí, je to čitelnější a kompileru zase tolik moc času zrovna takové věci nezaberou si myslím. . . Jinak jestli to chápu, tak i v Javě je potřeba občas se zbavit "tvrdého" typování?
Javu 8 fakt nevím, když jsem dělal poslední měsíc JSP na 7, tak Java 8 zrovna vyšla ....
@janek
Ne, to neni o zbaveni se statickeho typovani. To je o tom, ze vetsinou nemusis typy ani explicitne psat, protoze compiler je odvodi.
Zrovna v Jave tohle ma daleko do dokonalosti, ale zase pseudokodem:
Integer a = a.length;
Map<String, String> m = getParameters();
sout( a + m) //chyba, nejde scitat integer a mapu
muzes v rozumnejsich jazycich napsat
def a = a.length; // ze je to Integer je jasne; a je typem Integer, jen jsi to nemusel psat
def m = getParameters(); // to same, ze predpokladu, ze mas deklarovane getParameters s prislusnou hodnotou navratoveho typu
sout( a + m ) //stale chyba pri kompilaci
Kdyz neco takoveho tvuj jazyk umi, tak se dostanes +- do stavu, kdy pises typy jenom v hlavickach funkci (coz by casto nebylo potreba, ale je to dobra dokumetace, navic se nemuze rozejit s kodem jako normalni dokumentace). Pritom neprijdes o typovou bezpecnost. A kod je obvykle citelnejsi.
Netvrdím že je to nutně skvělé nebo lepší, jen to není žádný problém.
Zapomněl jsi validovat, že $jsonData je objekt a ne array. Jak bude vypadat kód, když tam přidáš dalších 5 políček? Zvládneš to změnit, když se zákazník rozhodne změnit ty typy?
Kompletní ekvivalentní kód v haskellu, tentokrát pro změnu s autoderive:
data Message = Message { uuid :: Int, content :: Int } deriving (Generics, FromJSON)
json = "...."
case decodeEither json of
Left err -> report error
Right msg -> exampleFunction (uuid msg) (content msg)
Dělá to to samé co tvůj kód (včetně validace, že to je objekt). Doba napsání cca. 60s. Jo, mimochodem, ten fakt, že překladač ví, jaké typy v té Message pak znamená, že ten parsing za tebe tu funkci "parseJSON" klidně napíše.
Promiň, ale zkopároval jsem to do online IDE ale jaksi to nejede ......... ?
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:4:10: parse error on input `->'
sh-4.3$ main
sh: main: command not found
sh-4.3$ ghc -O2 --make *.hs -o main -threaded -rtsopts
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:4:10: parse error on input `->'
sh-4.3$ main
sh: main: command not found
Ale jinak ten kód vypadá hezky .....
https://gist.github.com/ondrap/a23a41162c536ea64f35ab677add6259
cabal install --only-dependencies
cabal configure
cabal build
Jo, tak jsem to zkusil hodit na vitruál, ale dostal jsem se do nějakého dependecy pekla s base 4.8.2.0. Asi bych musel instalovat jinou verzi haskellu a to už se mě nechce, ani v tom nedělám, takže na to prdím, chtěl jsem to zkusit, možná ještě zkusím, ale teď už nemám čas ...
Díval jsem se na ten zdroják, konečně jsme dali kódy a můžeme se bavit o něčem konkrétním.
Jako pěkný kód, akorát si nejsem úplně jistý, jestli ta výhoda které využíváš s přispěním statického typování není spíš v tom, že ten jazyk umí dobře a sám reagovat vyhazováním vyjímek a zpracováním erorr messages i v případě že se někde zmrví datové typy, než tím že je ten jazyk stat. typovaný. Protože tam máš vysoko úrovňové funkce, které si samy poradí s přetypováním a chycením a vyhozením vyjímky a ekvivalent v PHP by to byly funkce nějakého frameworku.
třeba deriving (Generic, FromJSON)
nebo
case eitherDecode jsdata of
Left err -> error err
Třeba ve stat. typ. Jave, kdyby jsi poslal do xyz( Int a ) String x, tak to padne a musíš to ošetřit v kodu aby se do funkce neposlal. Jestli chápeš co tím myslím - je to jako bych si importoval pro PHP něčí knihovnu JSON a zavola udelejTo( array("int", "int") ) a už vzal jen výsledek.
Ale hezký kousek kódu a aspoň jsem si poprvé spočítal 5*5 v konsoli Haskellu :-)
Jako osobně si myslím, že následujících 5 -10 let bude patřit pre a pos kompilerům a i s rozmachem moderních FP jazyků. Ale nehodí se úplně na všechno a spousta věcí běží na starších technologiiích a nikdo to do vánoc přepisovat nebude, tak se uvidí, jestli i "tradiční jazyky" s něčím přijdou. Ten Haskell je hezký ale pustil jsem se do LUA, tak to hned nevzdám ....
Třeba tohle, je to total pseudokod ale myslím že to přelouskneš jak nic. Ani se nepokouším to spustit, je to jen názornost ....
ArrayList<Array> full = new ArrayList();
full[0] = [0,1,2,3];
full[1] = [0,1,2,3];
full[3] = [""];
count = 0;
for (full) {
for (full[i]) {
count = count + full[i][k];
}
}
"a pokud mas ArrayList, tak musis pretypovat, takze si beres zodpovednost sam"
Ok, já Vím, ale to je to na co jsem narážel, že ne úplně vždy stat. typování pomůže.
Ten tvuj priklad je spatne. Jeste jenou
- bez castu se to ani neprelozi
- kdyz castujes, tak je to na tvoje triko
"ne úplně vždy stat. typování pomůže"
Taky ti nepomuzes, kdyz napises
def infinity = () : infinity
sout (infinity)
Pointa je v tom, ze, dobre udelane, prakticky nikdy neuskodi a hodne casto pomuze.
Aha, vyhodil jsem z dependencies ty verze od base, teď by se to mělo zkompilovat pod čímkoliv.
> Jako pěkný kód, akorát si nejsem úplně jistý, jestli ta výhoda které využíváš s přispěním statického typování není spíš v tom, že ten jazyk umí dobře a sám reagovat vyhazováním vyjímek a zpracováním erorr messages i v případě že se někde zmrví datové typy, než tím že je ten jazyk stat. typovaný
Ono fígl je v tom, že v tom kódu se vůbec žádné výjimky nevolají. První výjimka, která se vůbec zavolá, je to volání "error", což je jen jinak řečeno "spadni" :) . Tzn. že veškerý tok informací je kontrolovaný přes typy funkcí a v haskellu je obvyklé psát funkce tzv. "totální" - tzn. že to nikdy žádnou výjimku nevyhodí.
To statické typování tady má několik funkcí. "Manuálně" napsaná instance dekódování (rozepíšu, bude to jasnější):
parseJSON (Object obj) = do uuid <- o .: "uuid" content <- o .: "content" return (Message uuid content) parseJSON _ = Fail "Object expected"
Co to dělá? Operátor ".:" je normální funkce, která zkusí najít klíč v objektu, pokud se nepovede, vrátí "Fail". A když najde, tak na výsledek zavolá funkce "parseJSON". Funkce "parseJSON" je součástí tzv. TypeClass, tzn. překladač ví, že chceš parsovat nějakou Json hodnotu do konkrétního staticky typovaného výsledku a najde ti odpovídající funkci (takže nepotřebuješ "parseInt", "parseString" apod. - stačí prostě parseJSON). No a zároveň to běží v tom "do" bloku, aneb v Monadu, což je něco jako "programovatelný středník".
Takže klasické - představ si, že chci zničeho nic dekódovat ne jednu zprávu, ale pole zpráv. Díky statickému typování jsem schopen napsat instanci pro
instance FromJson a => FromJSON [a] where parseJSON (Arrray arr) = mapM parseJSON arr parseJSON _ = fail "Array expected"
aneb - pokud máme parseJSON pro typ a, pak umíme parsovat i "pole a". A funguje to pro jakýkoliv typ a - protože ta funkce parseJSON se vybere podle typu, který to má vrátit. A teď mi stačí někde deklarovat, že chci "uuids :: [UUID]" - a jsem hotový.
Jinak ta kontrola chyb, aniž by se použily výjimky je postavena na tzv. Monadech, což zhruba funguje takto:
uuid <- o .: "uuid"
Ta pravá strana výrazu vrací buď "Success value" nebo "Fail errtext". Pokud to běží v do bloku, tak když to vrátí Success, tak se do uuid uloží ta hodnota. Pokud to vrátí Fail, tak se celý "do" block ukončí a vrátí to ten Fail. Tohle je mimochodem kompletně "programovatelné" chování a dají se s tím dělat docela zajímavé věci :)
Jj vypadá ten kód zajímavě. I když toto je proti klasikům Java a C úúúplně někde jinde. Dokážeš si představit nasazení Haskellu třeba na projektu jako je WP nebo Facebook? Nemyslím jenom po stránce syntax, ale i takového toho workflow a príce v teamu? Třeba zátěž serveru,protože ty funkce jsou docela vysokoúrovňové - nebo komplexní - a to nese režii a taky co se týče údržby kódu a stability?
Ano. Ta typová kontrola je taková, že něco rozbít je docela složité. Navíc díky "immutability" a "pure funkcím" máš zpravidla velmi dobrou představu, co který kus kódu dělá. Jediné, co je tragicky pomalé, je kompilace, ale dá se s tím žít (akorát to na notebooku teda žere brutálně baterky). Jinak to má velmi slušnou výkonnost - není to tak výkonné jako Java/C++, na druhou stranu to ale pořád funguje velmi slušně - má to velmi slušně napsaný multithreadovaný runtime. Facebook mimochodem haskell používá a jsou s tím velice spokojeni.
Pokud to není systémové programování, nebo naopak nějaký hard-realtime systém nebo něco na embedded platformách, tak to je IMO velmi dobrá volba. Pro psaní web services ideální. Lépe udržovaný kód jsem nikde neviděl - vezmi si třeba ten příklad, co jsem dal. Zákazník se rozhodne přidat do struktury další položku. Nebo změnit typ položky - změníš typ a kompiler ti napíše, kde všude jsi to rozbil. I pokud kódu vůbec nerozumíš a jenom slepě opravíš to, kde si to stěžuje, tak máš velmi dobrou šanci na to, že ten kód pak bude fungovat.
Aha, jo, tak to je zajímavé, já to psal ve spěchu, ale myslel jsem to tak, že vlastně ty funkce které jsi tam použil, to je něco jako v PHP třeba map + jako mapUdelejNecoSPolem + typová kontrola built-in a i když to nehodím do foreache, ten processor, resp. nějaký ten engine to stejně musí prolézt ...
Když v tom píšeš web services, zkoušel jsi nějakou tunu requestl za sec.?
No, mám dělat nějaké služby a jejich logiku dělat asi v pythonu, to se mi moc nelíbí a chtěl jsem na to vzít LUA, že bych to nějak spáchal, ale normálně jsi mě nalomil ti řeknu a přemýšlím že bych ten čas obětoval a zkusil bych se poučit ten Haskell. Ono to nepoběží na normal hostingu tak si tam budu moct vrazit cokoliv ... Tak to asi vyzkouším. Ale na PHP jsem nezanevřel :-D Díky
Haskell je super, na web services velmi dobré a posune tě to v programování někam úplně jinam. Má to jedinou nevýhodu: je to brutálně jiné programování, než na jaké jsi zvyklý. Na začátku to fakt bolí. A to učení nejde vůbec rychle. Ale jde to - opravdu to jde bez toho, aby člověk znal teorii kategorií a IMO ti ta teorie zas tak moc k ničemu nepomůže. Důležité je zkoušet, programovat, číst články, tutorialy, snažit se je pochopit, na stackoverflow člověk většinou dostane velmi dobrou odpověď. Ale připrav se na to, že z toho, co v programování umíš, toho moc nepoužiješ. Ale IMO výsledek stojí za to - a posune tě to, i když se třeba vrátíš a budeš programovat třeba v Javě - tyhle jazyky postupně přejímají různou funkcionalitu z FP a najednou pochopíš, k čemu to je a jak to použít.
Někteří lidé prostě mají názor, že účelem programovacího jazyka je pomáhat nejenom v produkování kódu, ale také v odhalování chyb. A jedním z hlavních zdrojů chyb je to že programátor udělá něco jiného než chtěl, tedy že neví co udělal.
Samozřejmě, opravdoví programátoři programují alespoň ve Fortranu, když už tedy rovnou nezadávají strojový kód v hexadecimální formě. Opravdoví programátoři neupravují cizí kód, maximálně dělají binární patche.
My obyčejní smrtelníci jsme rádi za každou pomoc.
"Samozřejmě, opravdoví programátoři programují alespoň ve Fortranu, když už tedy rovnou nezadávají strojový kód v hexadecimální formě. Opravdoví programátoři neupravují cizí kód, maximálně dělají binární patche.
My obyčejní smrtelníci jsme rádi za každou pomoc"
Ale no tak, nač ten rádoby ublížený ale ve skutečnosti zesměšňující tón? To jako že když někdo nepotřebuje pořád jenom čumět do konsole kompileru a má rád i jiné metody programování tak je podle Vás nějaký namyšlený blb?
Stat. typované jazyky nejsou špatné, jen se v nich pracuje jinak než v dyn. typovaných
To si jako myslíte, že v PHP je nšco jinak na 1 < 2? Nebo že "delete" == "delete" neplatí? Nebo že je v PHPP nějaký rozdíl v cyklech? Nebo že když dám o jednu proměnou méně do funkce, že mi to v PHP projde? Nebo že když se odkážu na proměnou která neexistuje, že to PHPku nevadí? Zkoušel jste to někdy?
Mě na tom PHP třeba baví to, že se nad tím musím fakt zamyslet a jenom čumět do toho, co mi kompiler napíše. Ono je to ale trošku jinak. Oni totiž programátoři PHP a Javascriptu většinou mají zkučenosti se stat. typovanými jazyky a na C, Javysty atd. nepindají. Ovšem naopak, na PHP a dyn. typ. jazyky má pindy pořád někdo .... a často proto, že neznají jazyk a pak se diví. to je celé. Zažívám to dlouho, místo jiné, scénář stejný ....
Nehledě na to, že kdyby ti těch parametrů přišlo 150 a používal jsi je na 25 místech, což na webu není nic neobvyklého, tak z toho porodíš . . .
Co se ti vlastně stane, když v
instance FromJSON Message where
parseJSON = withObject "Message" $ \obj -> Message <$> obj .: "uuid" <*> obj .: "content"
ti přijde uuid v JSON v jiném datovém typu než čekáš nebo tam vůbec nebude? Prostě to někdo zmrví?
Message bude return 0 nebo error a pak zavoláš
myFunction ( Message->uuid ) ?
Nebo ti
instance FromJSON Message where
parseJSON = withObject "Message" $ \obj -> Message <$> obj .: "uuid" <*> obj .: "content"
vyhodí vyjímku a to ti tam chybí, tak jak tady ne ?
arseJSON (Json json) {
Object obj = toObject(json);
if (obj == null) return (null, error("Message object expected."));
Json val = obj.lookup("uuid");
if (val == null) return (null, error("UUID key not found"));
(UUID uuid, res) = UUID.parseJSON(val);
if (res != ok) return (null, res);
val = obj.lookup("content");
if (val == null) return (null, error("content key not found"));
(Text text, res) = Text.parseJSON(val);
if (res != ok) return (null, res);
return Message(uuid, text);
Čtu tohle vlákno už dlouho a vaše obhajiba PHP mi silně přimíná hádky z dob mého dětství, jestli je lepší Basic nebo Pascal. A pro Basic byl argument, že se v něm snáze naprogramuje Pythagorova věta.
Vy pořád tvrdíte "Přece vím, co dělám". Opravdu vždycky víte, co děláte? Pak asi programujete jen tu Pythagorovu větu a nic složitějšího.
Byl jste někdy v situaci (ve které jsem já teď), že dostanete kód s více než miliónem řádků a máte tam něco změnit? Váš předchůdce si tam nějaké berličky typu
$a = array(
"uuid" => "1000",
"content" => "11111"
);
sice zavedl, ale zapomněl se o tom zmínit a vy vůbec netušíte, kde, kolik a jakých takových berliček je v tom kódu schovaných. I v takové situaci si troufáte tvrdit "Přece vím, co dělám?"
Víte co bych dal za to, kdyby to bylo napsané v silně typovaném jazyku, který má tuto podporu zabudouvanou standardními metodami a já nemusel tyhle berličky hledat v miliónu řádků kódu?
$a .... to není berlička, to je jenom ukázka přiřazení, kde místo dat. typu klidně můžu použít třeba indexy abych pohledem viděl co tam mám ale to jen vyplynulo z kontextu kdy andy napsal, že díky datovému typu ověří správnost hodnot a já mu chtěl ukázat, že datovým typem ověří jenom datový typ, ne správnost přiřazení hodnoty do proměnné.
"Vy pořád tvrdíte "Přece vím, co dělám". Opravdu vždycky víte, co děláte? "
A Vy si myslíte, že typová kontrola Vám zabrání dělat chyby? Zabrání Vám akorát použít jiný datový typ tam kde má být jiný. Nic víc.
--- ale toto pak bývají častí chyb lidí, kteří "přijdou" od stat. typovaných jazyků a nemají správné návyky, tak prdnou proměnou do funkce a pokud kompiler či co neřve, tak se tím ani nezabývají a pak se díví a nadávají na jazyk.
Nevím jestli si to uvědomujete v těch tunách řádků, ale pokud Vám přijde např. response JSON, tak ho někde přijmout musíte, i kdyby jste měl řádků bžilión .... Vy máte tak skvělý jazyk, že inputy nepřijímáte a jen tak se objevují kde potřebujete?
"Čtu tohle vlákno už dlouho a vaše obhajiba PHP "
Ano, je to až silně vtipné, jak vždycky někdo přijde s příkladem (netvrdím že zrovna Vy), který je jako v PHP na hov.. a oni to řeší automaticky ale kdyby programovali v PHP, tak by věděli že to žádný problém není.
A jestli si myslíte, že ve stat. typovaném jazyce nejdou nadělat obezličky a hovadinky, že se jenom divíte, tak jste hodně, pardon, naivní.
Takže popořadě:
- Typová kontrola nezabrání napsání chyby. Typová kontrola upozorní, že je něco blbě, aby sis tu chybu opravil.
- Typová kontrola nenajde všechny chyby. To, že neprostestuje proti děliteli typu int32 neznamená, že někdo nemůže zkusit dělit nulou (která do toho typu patří). Na to jsou zase jiný techniky, jako třeba asserce (i když to je pro patly sprostý slovo) a unit testy (to je zase pro patly urážka).
- Typy dat dovolí věci, který bys jinak těžko dělal. Třeba automatickou volbu funkce z několika stejnojmenných, přetížení operátorů...
To je krásná ukázka omezeného myšlení člověka, který celý život bastlí v PHP a vůbec netuší, jak se takové věci dělají "správně" :)
Například pokud každý výrobek má id a jméno, tak mám abstraktní třídu AbstractProduct s těmito atributy, pracuji nad kolekcí AbstractProduct a nic přetypovávat nemusím...
Nebo pokud nepotřebuji s produkty vůbec pracovat jako s objekty, tak mám každý produkt prostě jako mapu "název atributu" => "hodnota atributu" a nemám vůbec žádný problém.
To je spíš ukázka omezeného myšlení člověka, který dělá s jazyky staticky typovanými.
"Například pokud každý výrobek má id a jméno, tak mám abstraktní třídu AbstractProduct s těmito atributy, pracuji nad kolekcí AbstractProduct a nic přetypovávat nemusím..."
I na ty aprametry kolekce a třídy byl někde input - z databáze, XML, whatever a buď si to natypuješ a pošleš do objeku jako co to má být a nebo string a zase nic nevíš a typuješ až pak. To se ani nebavím o tom, že to co jsi tu popsal je správně, proč ne, ale v PHP to úplně klidně můžeš udělat taky.
"Nebo pokud nepotřebuji s produkty vůbec pracovat jako s objekty, tak mám každý produkt prostě jako mapu "název atributu" => "hodnota atributu" a nemám vůbec žádný problém."
No to nemáš, ale v PHP to funguje úplně správně. Akorát když máš pole složené ze záznamů více datových typů. tak ti nevadí, že jsi to v deklaraci nemusel vyjmenovat.
> To je spíš ukázka omezeného myšlení člověka, který dělá s jazyky staticky typovanými.
Vedle jak ta jedle. Já dělám s obojím :D V PHPku sice už jen výjimečně, ale zato dělám často v Javascriptu který je na tom z hlediska typovosti podobně a jeho (ne)typovost je vysoko na seznamu věcí co mě na něm iritují.
> I na ty aprametry kolekce a třídy byl někde input...
To jsem nějak nepochopil, v čem je problém...
Celkově jde o to, že ty se tady snažíš tvrdit, jak jsou silně typované jazyky špatné, že v nich musíš nějak komplikovaně "typovat" (což jsem úplně nepochopil co je, ale podle toho jak se o tom vyjadřuješ to bude nejspíš nějaký komplikovaný rituál trvající několik hodin a zahrnující černého kohouta a krev panny).
Tak jsem ukázal, že i pole různorodých objektů se ve staticky typovaných jazycích dá udělat úplně jednoduše. Pointa je, že i tam se dá to typování s trochou snahy obejít, pokud fakt překáží. Ale v PHP [a podobných] silnou typovou kontrolu nevynutíš a přitom v drtivé většině případů je užitečná.
"Celkově jde o to, že ty se tady snažíš tvrdit, jak jsou silně typované jazyky špatné"
To je mýlka pane. Já se nic takového tvrdit nepokouším a ani si to nemyslím, jen tam prostě člověk k řešení některých věcí přistupuje jinak. To je vše. Já se akorát snažím obhájit PHP, že není na hovno. Aby jste věděl, začal jsem s C a Matlab scripty, pak PHP, pak Java a pak Javascript a ty "webové volovinky". A právě javascript je taky hezky benevolentní jazyk, ale začal jsem ho mít rád až jsem se odbrzdil z Javy, přijmul že security je v něm 0 a začal ho brát benevolentně. A od té doby ho mám rád. Že bych v něm byl nějaký Nio to netvrdím, ani v PHP nejsem nějaký super Bůh, ale vidím i krásy těchto jazyk a je mi líto, že na ně ostatní plivou ale co hůře, často jen kvůli nepochopení. Mají své chyby, zmíním jednu o které hovořil Douglas Crockford a tou jsou ==a ===, že si pak člověk není jistý, kdy to tak programátor myslel a kdy jenom nevěděl co přesně dělá. Ale s tím se dá žít a není to myslím chyba jazyka.
dělám často v Javascriptu který je na tom z hlediska typovosti podobně a jeho (ne)typovost je vysoko na seznamu věcí co mě na něm iritují.
Je opravdu takový problém nahodit třeba Flow a typy prostě začít používat?
Takže kontrolovat buďto absolutně všechno, nebo vůbec nic? A spolehnout se na korektní validaci vstupů. kterou si napíšu a můžu tam mít chybu? Nestačí něco mezi, dle vlastního uvážení a nastavení kompilátoru?
Ten validátor bude v PHP? Jak ošetříš, že se vstupní hodnota správně interpretuje, když tam může být cokoliv? Jak tam zajistíš korektní vstupy, aby to korektně prošly všechny podmínky? Jo aha, zařadíš pre-validátor napsaný v PěkněHloupéPrasárně...
Za sebe, pokud kompilátor upozorní na 10% chyb, furt je lepší mít opravechých 10%, než žádnou.
Kompiler tě upozorní jen na chyby syntaxe ne na chyby logické. K tomu aby se odchytaly chyby použiješ unittesty nebo integralni testy a záleží jen na tom jak dobře si je napíšeš. V žádném jazyku není ochrana která vychytá všechno a pak už je to jen na míře spokojenosti. Dokud nepíšeš řídící program pro jadernou elektrárnu, tak se prostě ty chyby co by mohly nastat kdyby.. (s malou pravděpodobností) prostě neřeší.
Nikde a nikdy. Vývoj takovýho sw je neuměrně drahej a náročnej. Když se spokojim s tim že web pujde 99,9% uživatelům uplně v pohodě, nemusim dělat ani nějaký extra vyfikundace. To 0,1% prostě schytá chybu a dostanou třeba 404.
Když chci neprůstřelnou validaci vstupů napíšu si jí neprůstřelně, a pak ji musím neprůstřelně otestovat. Tobě snad stačí že kompiler ti zařve že porovnáváš string s intem, tak to opravíš a je to v pohodě? už tam nemůže bejt žádná logická chyba? ... A ne skutečně si nebudu psát prevalidátor v jiném jazyku.
Když budu chtít tak si v PHP napíšu skript co mi projde celej kód a bude hledat kde se porovnává int se stringem a vyhodí mi warning :P
Pořád to neznamená že by PHP bylo horší než jiný jazyky.
Ad ty chyby co by mohly nastat kdyby.. (s malou pravděpodobností) prostě neřeší... se spokojim s tim že web pujde 99,9% uživatelům uplně v pohodě, nemusim dělat ani nějaký extra vyfikundace. To 0,1% prostě schytá chybu - přesně tomu říkám LAMPání nebo "vývoj" (ty uvozovky jsou záměr). Dovedené do důsledku to vypadá takhle:
http://www.zive.cz/clanky/rozhovor-nezkroceni-vyvojari-a-kovbojove/sc-3-a-162156/default.aspx
BTW představte si že píšete mzdovou agendu nebo účetnictví. Spokojíte se s tím že to v 99.9% případů pojede správně, a zbytek možná spadne na nějakou chybu nebo udělá něco úplně mimo mísu? Takový styl "vývoje" vám projde jen a pouze na webu.
Chápeš rozdíl mezi webem a řídícím systémem jaderný elektrárny?
Můžu ti říct že ve druhým případě se používají uplně jiný paradigmata, takový aby k chybě nemohlo dojít, a tam by sis neškrtnul ani s vývojem bez uvozovek.
Když se na webu stane že uživatel chce použít produkt velmi nestandardním způsobem a výsledkem je že se mu vypíše chybová hláška, tak je všechno v pořádku a nemusím vymýšlet systém pro odchytnutí chyby která nastane s pravděpodobností 1:10000000
Samozřejmě můžete udělat web pro zákazníka, na takové úrovni že bude opravdu vychytaný, ale nikdy nevychytáte uplně všechno. Bude to stát hodně práce ošetřit všechny cobykyby co vás napadnou a pak to třeba nechat betatestovat. Zákazník kterej ale chce přidávat na svuj web fotky a spravovat pár textů se pak asi bude divit až mu vystavíte fakturu na 10x vyšší částku a moc tomu nepomůže až mu bude popisovat jak moc bizardním chybám ste zabránil už dopředu.
1) je to je otázka nabídky a poptávky, web který bude teoreticky 100.00% bez chyby bude extrémně drahý se zvyšující se složitostí = zákazník to ani nechce
2) cobykdyby a chyby které mohou nastat jen s malou pravděpodobností se v businessu neřeší, píše se tak Windows i jádro Linuxu i OS pro iPhone i každá jiná aplikace co se má za účelem zisk
3) rozhovor jakýchkoliv dvou lídí co se baví o nějaké věci má to dokázat že ta věc je špatná neberu jako relevantní důkaz = asi dáte hodně na pověry, já teda ne
4) kdo tvrdí že napsal trochu složitější program který je bez chyb lže, takže si to lampání a vývoj v uvozovkách strčte za klobouk pane dokonalý ;-*
Je jedno jestli děláte mzdovou nebo webísek bráškovi. Buď se ujistíte co si do výpočtu pouštíte - povolíte to co potřebujete a zbytek ošetříte errory a vyjímkami a nebo se na to více či méně vysere.e. Vtip je akorát v tom, že u mzdové si to málo kdo dovolí osr...., jinak je správný postup pořád stejný
Jasně, a teď si začneme cucat % z prstů, že?
"Ten validátor bude v PHP? Jak ošetříš, že se vstupní hodnota správně interpretuje, když tam může být cokoliv? "
A když ti v JSP přijde z requestu rozparsovat string tak s tím uděláš co? Budeš ho muset úplně stejně jako v PHP rozhodit a přetypovat na co potřebuješ. A protože tam budeš mít striingy, int a floaty, a budeš chtít mít indexy v poli jiné než 0 - 25 tak to dáš do ArrayListu + ( i protože to nebudeš chtít do každé funkce předávat každý argument sólo) a pak zase budeš někde iterovat přes A..List a zase bude dělat kontroly ... A si tam kde s PHP. A to má Java striktní typovou kontrolu.
A nebo si do ArrayListu navalíš jen parsované stringy s hezkými indexy, ale stejně až je chceš použít, provádíš typovou kontrolu případně konverzi. V Javě primárně proto aby program nepadal, v PHP protože to musíš mít správně. Výsledek stejný.
A nevím, no ale pokud máš proměnou int a někdo ti do ní pošle něco co tam být nemá, tak ti to padne i když ti to na tvůj vstup při programování kompilátor schválil, protože jsi tam měl hezky integer. A proto stejně u každé proměnné kterou z odněkud přebíráš musíš provést kontrolu a když tak přetypovat a nebo vypsat hlášku. Jasně, můžeš chytat error probubláním někde nahoře, ale uživateli nechceš zobrazit celý errortrace a hláška "Něco se posralo" toho taky moc neřeší, takže ideálně vyhodit svůj error hned === kontrole hned.
A to je ten případ PHP. Tam si do proměné narveš co chceš, a kontroluješ až tě to zajímá. A to díky tomu, že nemá takovou striktní typovou kontrolu. Nevím, každému možná vyhovuje něco jiného. Zodpovědnost ale zůstává. PHP prostě zachází se stringy jinak než C/C++ nebo Java, jiné striktní tak moc neznám, a proto i při větvení to má tročku jiné pravida. Ale opět dodávám. Není problém použít strcmp nebo === striktní porovnání.
Teoreticky ano, ale vzpomínám si, že když jsme kdysi museli manipulovat s velkými poly a měřil se čas a využitá paměť kvůli paralelním procesům, tak jsme předávali do funkcí přes odkaz do paměti & a tak se obešlo vytváření toho pole pero scope funkce a manipulovalo se přímo s ním.
To už je jen otázka návrhu. Já si kontroluju vstupy na vstupu a ne v průběhu aplikace. Většinu toho co by jinak zachytil kompiler zjistíš hned po spuštění. Něco ti tam zbyde s nim nebo bez něj, pak stejně uděláš testy a záleží jen na tom jak je uděláš kvalitní. Je to jen o tom co chceš a kolik si ochotnej tomu obětovat. Apple taky v testovacím případu vynechalo otestování nastavení data na 1.1.1970 protože se to týká minima uživatelů. Vyčlenění lidí aby udělali kvalitní test a přepsání aplikace aby to nedovolila by bylo dražší než těch pár tisíc placek co jim přijde na reklamaci.
V interakci s člověkem co neni němec se podělá jakejkoliv sw a nemůže za to jen PHP
Méně konzistentí jazyk jsem nevidel. To v tom perlu nebo pythonu alespoň každá (syntaktická) konstrujce funguje vždy (jen někdy není pro začátečníky hned jasné co dělá). Naproti tomu v PHP některé konstrukce někde povolené jsou a jinde tě za to kompilátor seřve. Je to dané tím, že PHP je slepenec různých nápadů. Zkuste si třeba v PHP 5.1 dát do statického konstruktoru proměnné třídy pole, které obsahuje lambdu.
Dost divná věc je přetypování číselných řetězců na číslo při ukládání do pole. S tím se dá si pěkně naběhnout. Nejhorší je pak k php polím přistupovat z Cčkového rozšíření: PHP api totiž přetypuje při uložení do pole, ale při výběru z pole ne. Takže pseudokód:
array_set(my_array, my_key, my_value);
my_copy_of_value = array_get(my_array, my_key);
selze pokud napriklad my_key odpovida retezci "1".
No PHP 5.1 je už trošku mimo ne? To by jste taky mohl nadávat na implementace v lin. kernel 1.3 ....
"Zkuste si třeba v PHP 5.1 dát do statického konstruktoru proměnné třídy pole, které obsahuje lambdu."
Co je to "konstruktor proměnné třídy"?
"Dost divná věc je přetypování číselných řetězců na číslo při ukládání do pole"
Nějaký konkrétní příklad? Pokud to teda není z PHP 15 let starého ... ať nemarníme čas
Mě nezajímá co se autor rozhodl, že zakáže, protože uprasil kompilátor. Já po jazyku požaduji, aby mi při psaní neházel klacky pod nohy. Jednak normální jazyky dovolují i ve statické inicializaci volat funkce (alespoň konstruktory objektů), a druhak je lambda celkem statická věc (zkompiluje se na stejnou funkci, obzvlášť v PHP, které nemá (nemělo?) closures).
no sice jsme na rootu s linuxovou komunitou, ale proč k PHP nepřihodit
http://www.hovnokod.cz/vb
třeba http://www.felix-colibri.com/papers/db/eco_tutorial/eco_tutorial.html takto to ještě vypadá jednoduše ale když tam chceš udělat neco jako SQL s pár joinama tak z toho vyleze maglajz horší než helloword v brainfucku.