Share via


Foutafhandeling

Het resultaat van het evalueren van een M-expressie produceert een van de volgende resultaten:

  • Er wordt één waarde geproduceerd.

  • Er is een fout opgetreden die aangeeft dat het proces voor het evalueren van de expressie geen waarde kan produceren. Een fout bevat één recordwaarde die kan worden gebruikt om aanvullende informatie te geven over wat de onvolledige evaluatie heeft veroorzaakt.

Fouten kunnen worden gegenereerd vanuit een expressie en kunnen worden verwerkt vanuit een expressie.

Fouten genereren

De syntaxis voor het genereren van een fout is als volgt:

foutverheffen-expressie:
      errorExpressie

Tekstwaarden kunnen worden gebruikt als afkorting voor foutwaarden. Bijvoorbeeld:

error "Hello, world" // error with message "Hello, world"

Volledige foutwaarden zijn records en kunnen worden samengesteld met behulp van de Error.Record functie:

error Error.Record("FileNotFound", "File my.txt not found",
     "my.txt")

De bovenstaande expressie is gelijk aan:

error [ 
    Reason = "FileNotFound", 
    Message = "File my.txt not found", 
    Detail = "my.txt" 
]

Als u een fout opgeeft, wordt de huidige expressie-evaluatie gestopt en wordt de expressie-evaluatiestack totdat een van de volgende bewerkingen plaatsvindt:

  • Een recordveld, sectielid of variabele (gezamenlijk: een vermelding) wordt bereikt. De vermelding wordt gemarkeerd als een fout, de foutwaarde wordt opgeslagen bij die vermelding en vervolgens doorgegeven. Als u later toegang tot deze vermelding krijgt, wordt er een identieke fout gegenereerd. Andere vermeldingen van de record, sectie of let-expressie worden niet noodzakelijkerwijs beïnvloed (tenzij ze toegang hebben tot een vermelding die eerder is gemarkeerd als een fout).

  • De expressie op het hoogste niveau is bereikt. In dit geval is het resultaat van het evalueren van de expressie op het hoogste niveau een fout in plaats van een waarde.

  • Er wordt een try expressie bereikt. In dit geval wordt de fout vastgelegd en geretourneerd als een waarde.

Afhandeling van fouten

Een foutafhandelingsexpressie (informeel bekend als een 'try-expressie') wordt gebruikt voor het afhandelen van een fout:

error-handling-expression:
      tryprotected-expression error-handleropt
beveiligde expressie:
      Expressie
error-handler:
      anders-component
      catch-component
anders-component:

      otherwisestandaardexpressie
standaardexpressie:
      Expressie
catch-component:
      catchcatch-function
catch-function:
      (parameter-nameopt)=>function-body

Het volgende geldt voor het evalueren van een foutafhandelingsexpressie zonder fout-handler:

  • Als de evaluatie van de beveiligde expressie geen fout oplevert en een waarde x produceert, is de waarde die wordt geproduceerd door de expressie voor foutafhandeling een record van het volgende formulier:
    [ HasErrors = false, Value = x ]
  • Als de evaluatie van de beveiligde expressie een foutwaarde e genereert, is het resultaat van de foutafhandelingsexpressie een record van het volgende formulier:
    [ HasErrors = true, Error = e ]

Het volgende geldt voor het evalueren van een foutafhandelingsexpressie met een fout-handler:

  • De beveiligde expressie moet worden geëvalueerd vóór de fout-handler.

  • De fout-handler moet worden geëvalueerd als en alleen als de evaluatie van de beveiligde expressie een fout veroorzaakt.

  • Als de evaluatie van de beveiligde expressie een fout genereert, is de waarde die wordt geproduceerd door de foutafhandelingsexpressie het resultaat van het evalueren van de fout-handler.

  • Fouten die zijn opgetreden tijdens de evaluatie van de fout-handler , worden doorgegeven.

  • Wanneer de fout-handler die wordt geëvalueerd een catch-component is, wordt de catch-functie aangeroepen. Als deze functie een parameter accepteert, wordt de foutwaarde doorgegeven als de bijbehorende waarde.

In het volgende voorbeeld ziet u een foutafhandelingsexpressie in een geval waarin er geen fout optreedt:

let
    x = try "A"
in
    if x[HasError] then x[Error] else x[Value] 
// "A"

In het volgende voorbeeld ziet u hoe u een fout opgeeft en deze vervolgens verwerkt:

let
    x = try error "A" 
in
    if x[HasError] then x[Error] else x[Value] 
// [ Reason = "Expression.Error", Message = "A", Detail = null ]

Het voorgaande voorbeeld kan met minder syntaxis worden herschreven met behulp van een catch-component met een catch-functie die een parameter accepteert:

let
    x = try error "A" catch (e) => e
in
    x
// [ Reason = "Expression.Error", Message = "A", Detail = null ]

Een andere component kan worden gebruikt om fouten te vervangen die worden verwerkt door een try-expressie met een alternatieve waarde:

try error "A" otherwise 1 
// 1

Een catch-component met een catch-function met nulparameters is in feite een langere, alternatieve syntaxis voor een anders-component:

try error "A" catch () => 1 
// 1

Als de fout-handler ook een fout genereert, wordt de volledige try-expressie dan uitgevoerd:

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"

Fouten in record en initializers toestaan

In het volgende voorbeeld ziet u een record initialisatiefunctie met een veld A dat een fout genereert en wordt geopend door twee andere velden B en C. Veld B verwerkt niet de fout die wordt gegenereerd door A, maar C wel. Het laatste veld D heeft geen toegang A en wordt dus niet beïnvloed door de fout in 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 
]

Het resultaat van het evalueren van de bovenstaande expressie is:

[ 
    A = // error with message "A" 
    B = // error with message "A" 
    C = "A", 
    D = 2 
]

Foutafhandeling in M moet dicht bij de oorzaak van fouten worden uitgevoerd om de gevolgen van lazy field initialisatie en uitgestelde sluitingsevaluaties af te handelen. In het volgende voorbeeld ziet u een mislukte poging om een fout te verwerken met behulp van een try expressie:

let
    f = (x) => [ a = error "bad", b = x ],
    g = try f(42) otherwise 123
in 
    g[a]  // error "bad"

In dit voorbeeld is de definitie g bedoeld voor het afhandelen van de fout die is opgetreden bij het aanroepen f. De fout wordt echter gegenereerd door een veld-initialisatiefunctie die alleen wordt uitgevoerd wanneer dat nodig is en dus nadat de record is geretourneerd van f en doorgegeven via de try expressie.

Fout niet geïmplementeerd

Hoewel een expressie wordt ontwikkeld, wil een auteur mogelijk de implementatie voor sommige delen van de expressie weglaten, maar de expressie mogelijk nog steeds kunnen uitvoeren. Een manier om deze case te verwerken, is door een fout te genereren voor de niet-geïmplementeerde onderdelen. Bijvoorbeeld:

(x, y) =>
     if x > y then
         x - y
     else
         error Error.Record("Expression.Error", 
            "Not Implemented")

Het beletselteken (...) kan worden gebruikt als een snelkoppeling voor error.

niet-geïmplementeerde expressie:
      ...

Het volgende is bijvoorbeeld gelijk aan het vorige voorbeeld:

(x, y) => if x > y then x - y else ...