Virheen käsittely
M-lausekkeen arvioinnin tulos tuottaa jonkin seuraavista tuloksista:
Yksittäinen arvo tuotetaan.
Esiin tulee virhe, joka ilmaisee, että lausekkeen arviointiprosessi ei voinut tuottaa arvoa. Virhe sisältää yksittäisen tietueen arvon, jonka avulla voidaan antaa lisätietoja siitä, mikä aiheutti keskeneräisen arvioinnin.
Virheet voidaan luoda lausekkeen sisältä, ja niitä voidaan käsitellä lausekkeen sisällä.
Virheiden esittäminen
Virheen esittämisen syntaksi on seuraava:
virhe-raising-expression:
error
lauseke
Tekstiarvoja voidaan käyttää virhearvojen lyhenteinä. Esimerkkejä:
error "Hello, world" // error with message "Hello, world"
Täydelliset virhearvot ovat tietueita, ja ne voidaan muodostaa käyttämällä -funktiota Error.Record
:
error Error.Record("FileNotFound", "File my.txt not found",
"my.txt")
Yllä oleva lauseke vastaa seuraavaa:
error [
Reason = "FileNotFound",
Message = "File my.txt not found",
Detail = "my.txt"
]
Virheen esittäminen aiheuttaa nykyisen lausekkeen arvioinnin pysähtymisen, ja lausekkeen arviointipino purkautuu, kunnes jokin seuraavista tapahtuu:
Tietuekenttä, osan jäsen tai let-muuttuja – yhteisesti: merkintä – saavutetaan. Tapahtuma on merkitty virheeksi, virhearvo tallennetaan kyseisen merkinnän kanssa ja välitetään sitten. Tämän syötteen myöhempi käyttö aiheuttaa samanlaisen virheen. Tämä ei välttämättä vaikuta muihin tietueen, osion tai let-lausekkeen syötteihin (elleivät ne käytä merkintää, joka on aiemmin merkitty virheeksi).
Ylimmän tason lauseke on saavutettu. Tässä tapauksessa ylimmän tason lausekkeen arvioinnin tulos on virhe arvon sijaan.
-
try
lauseke on saavutettu. Tässä tapauksessa virhe siepataan ja palautetaan arvona.
Virheiden käsittely
error-handling-expression -lauseketta (tunnetaan epävirallisesti nimellä "try-lauseke") käytetään virheen käsittelemiseen:
error-handling-expression:
try
protected-expression error-handleropt
protected-expression:
lauseke
error-handler:
otherwise-clause
catch-clause
otherwise-clause:
otherwise
default-expression
default-expression:
lauseke
catch-clause:
catch
catch-function
catch-function:
(
parameter-nameopt)
=>
function-body
Seuraava pätee arvioitaessa error-handling-expression-lauseketta ilman error-handler-käsittelijää:
- Jos Protected-lausekkeen arviointi ei aiheuta virhettä ja tuottaa arvon x, error-handling-lausekkeen tuottama arvo on seuraavan lomakkeen tietue:
[ HasErrors = false, Value = x ]
- Jos Protected-lausekkeen arviointi aiheuttaa virheen, arvo on e, error-handling-lausekkeen tulos on seuraavan lomakkeen tietue:
[ HasErrors = true, Error = e ]
Seuraava pätee arvioitaessa error-handling-expression-lauseketta , jossa on error-handler:
Protected-lauseke on arvioitava ennen virhekäsittelijää.
Virhekäsittelijä on arvioitava, jos ja vain jos Protected-expression-arviointi aiheuttaa virheen.
Jos Protected-lausekkeen arviointi aiheuttaa virheen, error-handling-lausekkeen tuottama arvo on virhekäsittelijän arvioinnin tulos.
Virhekäsittelijän arvioinnin aikana esiin tuodut virheet välitetään.
Kun arvioitava virhekäsittelijä on catch-clause, catch-function käynnistetään. Jos tämä funktio hyväksyy parametrin, virhearvo välitetään sen arvona.
Seuraavassa esimerkissä havainnollistetaan error-handling-expression tapauksessa, jossa virhettä ei ole esitetty:
let
x = try "A"
in
if x[HasError] then x[Error] else x[Value]
// "A"
Seuraavassa esimerkissä näytetään virheen esittäminen ja sen käsittely:
let
x = try error "A"
in
if x[HasError] then x[Error] else x[Value]
// [ Reason = "Expression.Error", Message = "A", Detail = null ]
Edellä oleva esimerkki voidaan kirjoittaa uudelleen pienemmällä syntaksilla käyttämällä catch-clause-lausetta , jossa on catch-function , joka hyväksyy parametrin:
let
x = try error "A" catch (e) => e
in
x
// [ Reason = "Expression.Error", Message = "A", Detail = null ]
Otherwise-lausekkeen avulla voidaan korvata try-lausekkeen käsittelemät virheet vaihtoehtoisella arvolla:
try error "A" otherwise 1
// 1
Zero-parameter catch-functionin catch-functionin catch-clause on käytännössä pidempi vaihtoehtoinen syntaksi otherwise-lausekkeelle:
try error "A" catch () => 1
// 1
Jos myös virhekäsittelijä aiheuttaa virheen, niin tekee koko try-lauseke:
try error "A" otherwise error "B"
// error with message "B"
try error "A" catch () => error "B"
// error with message "B"
try error "A" catch (e) => error "B"
// error with message "B"
Virheet tietueessa ja let-alustajissa
Seuraavassa esimerkissä näkyy tietueen alustaja, jossa on kenttä A
, joka aiheuttaa virheen ja jota käyttää kaksi muuta kenttää B
ja C
. Field B
ei käsittele :n aiheuttamaa A
virhettä, mutta C
tekee sen. Lopullinen kenttä D
ei käytä : A
a, joten virhe ei vaikuta :aan A
.
[
A = error "A",
B = A + 1,
C = let x =
try A in
if not x[HasError] then x[Value]
else x[Error],
D = 1 + 1
]
Edellä olevan lausekkeen arvioinnin tulos on seuraava:
[
A = // error with message "A"
B = // error with message "A"
C = "A",
D = 2
]
Virheiden käsittely M-versiossa tulee suorittaa lähellä virheiden aiheuttajia, jotta voidaan käsitellä laiska kentän alustus ja lykättyjen sulkemisten arviointien vaikutukset. Seuraavassa esimerkissä näytetään epäonnistunut yritys käsitellä virhettä lausekkeen try
avulla:
let
f = (x) => [ a = error "bad", b = x ],
g = try f(42) otherwise 123
in
g[a] // error "bad"
Tässä esimerkissä määritelmän g
oli tarkoitus käsitellä virhettä, joka ilmeni kutsuttaessa f
. Virhe ilmenee kuitenkin kentän alustajassa, joka suoritetaan vain tarvittaessa ja siten sen jälkeen, kun tietue palautettiin kohteesta f ja välitettiin lausekkeen try
kautta.
Ei toteutettu virhe
Kun lauseketta kehitetään, tekijä saattaa haluta jättää pois lausekkeen joidenkin osien toteutuksen, mutta saattaa silti haluta pystyä suorittamaan lausekkeen. Yksi tapa käsitellä tätä tapausta on aiheuttaa virhe osille, jotka eivät ole vielä valmis. Esimerkkejä:
(x, y) =>
if x > y then
x - y
else
error Error.Record("Expression.Error",
"Not Implemented")
Kolmea pistettä (...
) voidaan käyttää -pikakuvakkeena error
.
not-implemented-expression:
...
Esimerkiksi seuraava vastaa edellistä esimerkkiä:
(x, y) => if x > y then x - y else ...