Nezhavarovatelnost je otázka definice havárie. Když někdo pěje chválu na nějaký vyšší programovací jazyk, že nemůže segfaultnout, dělá z vás blbce -- protože může-li něco segfaultnout, tak je to nízkoúrovňový jazyk...
Jde o to, jak se v daném jazyce propagují výjimky, tj. to např. dělení nulou, čtení neexistujícího souboru nebo klidně vybrání prvku z prázdného seznamu. Prakticky všechno, co pracuje s daty z vnějšku, může nějak selhat. Všechno, co používá něco, co může selhat, může selhat také (aspoň jsem to tak pochopil z článku). Ale jak to selhání vypadá v praxi (tj. jak po něm pokračuje běh programu) a čím se tak liší od výjimek v jiných jazycích, to jsem zatím nepochopil.
A co treba Java? Tam segfault nehrozi, maximalne nektera z velke rady exceptions, ktere ale jdou odchytit :o)
SIce se v mercury zabrani tomu aby program hodil segv, ale to, ze se programator u konstanty uklepne o jednu nulu a druzice skonci misto na obezne draze nekde v oceanu se stat muze i tam
To uz se pry jednou v NASA stalo, ze se programator uklep a program byl sice syntakticky spravne, ale delal neco co nemel ... a bylo po druzici
Myslim, ze to doslo k prepsani jedne carky jednou teckou a vzhledem, ze ten programovaci jazyk (IMHO Fortran nebo Cobol) byl spatne navrzeny, tak to kompilator nezjistil a raketa shorela pri startu.
nekde kolem roku 2k kvuli chybe ve vertifikaci modulu pri konstrukci rakety Ariane 5 na zaklade softwaru z Ariane 4 se stalo to same.
Byl to FORTRAN a konstrukce cyklu.
Cyklus ve FORTRANU vypadá třeba takhle
DO 12 I = 1, 10
cosi v těle cyklu, opakuje se 10x
12 CONTINUE
Mezery FORTRAN neuznává, proměnné se nemusí deklarovat, když začíná na I-N, je to integer, jinak real (float). Takže
DO 12 I = 1. 10
se pochopí jako
DO12I = 1.10
což je přiřazení 1.1 do prom. DO12I.
A kompilátor je kde???
(Kruci, jak se tady zadávají pevné mezery?)
V Mercury jsou také výjimky, které je možné podle potřeby vyhazovat a chytat. A konkrétně dělení v základní knihovně je deklarováno jako deterministické (aby člověk nemusel opravdu každé lomítko ve svém kódu explicitně oifovávat) a pro nulu vyhazuje výjimku. Nechtěl jsem o výjimkách ale mluvit z pedagogických pohnutek. Osobně se mi více osvědčilo "nepříjemné" situace v kódu ošetřovat explicitně, řádnou úvahou nad každým selháním (a tady Mercury pomůže), než vyhazováním a chytáním výjimek (na to je expert Java). Mám obavu, že při hojném užívání výjimek člověk snadno vyrobí kód špagetový ještě v jednom rozměru navíc: kde se která výjimka produkuje a kde se která výjimka chytá. A tak radši o výjimkách mlčím, aby si lidé nezvykli tyhle špagety zamotávát.
Správně jste pochopil, že všechno, co volá selhatelné, může selhat také. Výjimky jsou zavedeny proto, aby něco bylo z logického hlediska neselhatelné, ale v nárazu na skutečný svět přece jen nějak havarovalo. Osobně programy člením do dvou částí: v první fázi se vypořádám se vstupem a dostanu ho do struktur (pak už řetězec používám opravdu jako řetězec a nikdy ne jako seznam čárkou oddělených hesel, na to si zavedu seznam řetězců). Selhání (za běhu, např. výjimkou) na špatný vstup je tedy oznámeno brzo. Ve druhé fázi už vyhazuju prakticky jenom výjimku typu "Pro lenost nedoimplementováno.", a případně to dělení nulou, pokud jsem nějak nesprávně použil nějakou matematiku.
Když tedy budete uvažovat jen to řádné selhání predikátu (a nikoli selhání za běhu), rozdíl je právě v tom, že o tomhle logickém selhání Mercury umí dopředu ověřit, zda může či nemůže nastat. Např. budete tvrdit, že vezmete první prvek seznamu, ale Mercury vám řekne: a co když je seznam prázdný, tohle přece může selhat. Takže vás donutí přidat explicitní kontrolu, jestli je seznam neprázný. A pro tu neplánovanou větev můžete pro začátek klidně říct "Pro lenost nedoimplementováno." Většinou ale podobná pobídka kompilátoru stojí za úvahu: ušetřím si čas s pozdějšími problémy, když to pořádně doimplementuju už teď?