Dela via


Felhantering

Resultatet av utvärderingen av ett M-uttryck ger något av följande resultat:

  • Ett enda värde skapas.

  • Ett fel utlöses, vilket indikerar att processen för att utvärdera uttrycket inte kunde generera ett värde. Ett fel innehåller ett enda postvärde som kan användas för att ge ytterligare information om vad som orsakade den ofullständiga utvärderingen.

Fel kan uppstå inifrån ett uttryck och kan hanteras inifrån ett uttryck.

Skapa fel

Syntaxen för att skapa ett fel är följande:

error-raising-expression:
      error uttryck

Textvärden kan användas som förkortning för felvärden. Till exempel:

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

Fullständiga felvärden är poster och kan konstrueras med hjälp av Error.Record funktionen:

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

Uttrycket ovan motsvarar:

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

Om du skapar ett fel stoppas utvärderingen av det aktuella uttrycket, och uttrycksutvärderingsstacken varvar ned tills något av följande inträffar:

  • Ett postfält, en avsnittsmedlem eller en låtvariabel – kollektivt: en post – nås. Posten har markerats som ett fel, felvärdet sparas med posten och sprids sedan. All efterföljande åtkomst till posten orsakar ett identiskt fel. Andra poster i posten, avsnittet eller let-uttrycket påverkas inte nödvändigtvis (såvida de inte har åtkomst till en post som tidigare markerats som ett fel).

  • Det översta uttrycket har nåtts. I det här fallet är resultatet av utvärderingen av uttrycket på den översta nivån ett fel i stället för ett värde.

  • Ett try uttryck har nåtts. I det här fallet registreras felet och returneras som ett värde.

Hantera fel

Ett felhanteringsuttryck (som informellt kallas "try expression") används för att hantera ett fel:

error-handling-expression:
      tryfelhanterarval förskyddat uttryck
protected-expression:
      uttryck
error-handler:
      otherwise-clause
      catch-clause
otherwise-clause:

      otherwisestandarduttryck
default-expression:
      uttryck
catch-clause:
      catchcatch-function
catch-function:
      (parameter-nameopt) => function-body

Följande gäller vid utvärdering av ett felhanteringsuttryck utan felhanterare:

  • Om utvärderingen av det skyddade uttrycket inte resulterar i ett fel och genererar ett värde x, är värdet som genereras av felhanteringsuttrycket en post i följande formulär:
    [ HasErrors = false, Value = x ]
  • Om utvärderingen av det skyddade uttrycket genererar ett felvärde e, är resultatet av uttrycket för felhantering en post i följande formulär:
    [ HasErrors = true, Error = e ]

Följande gäller när du utvärderar ett felhanteringsuttryck med en felhanterare:

  • Det skyddade uttrycket måste utvärderas innan felhanteraren.

  • Felhanteraren måste utvärderas om och endast om utvärderingen av det skyddade uttrycket ger upphov till ett fel.

  • Om utvärderingen av det skyddade uttrycket ger upphov till ett fel är värdet som genereras av uttrycket error-handling-resultatet av utvärderingen av felhanteraren.

  • Fel som uppstår under utvärderingen av felhanteraren sprids.

  • När felhanteraren som utvärderas är en catch-clause anropas catch-function. Om den funktionen accepterar en parameter skickas felvärdet som dess värde.

I följande exempel visas ett felhanteringsuttryck i ett fall där inget fel utlöses:

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

I följande exempel visas hur du skapar ett fel och sedan hanterar det:

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

Föregående exempel kan skrivas om med mindre syntax med hjälp av en catch-clause med en catch-function som accepterar en parameter:

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

En annars-sats kan användas för att ersätta fel som hanteras av ett try-uttryck med ett alternativt värde:

try error "A" otherwise 1 
// 1

En catch-clause med en catch-function med nollparameter är i själva verket en längre alternativ syntax för en annars-sats:

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

Om felhanteraren också genererar ett fel gör även hela try-uttrycket det:

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"

Fel i posten och låt initierare

I följande exempel visas en postinitierare med ett fält A som genererar ett fel och som nås av två andra fält B och C. Fältet B hanterar inte det fel som utlöses av A, men C gör det. Det sista fältet D har inte åtkomst och A påverkas därför inte av felet i 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 
]

Resultatet av utvärderingen av uttrycket ovan är:

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

Felhantering i M bör utföras nära orsaken till fel för att hantera effekterna av lat fältinitiering och uppskjutna stängningsutvärderingar. I följande exempel visas ett misslyckat försök att hantera ett fel med ett try uttryck:

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

I det här exemplet var definitionen g avsedd att hantera felet som uppstod när du anropade f. Felet utlöses dock av en fältinitierare som bara körs när det behövs och därmed efter att posten returnerades från f och skickades genom try uttrycket.

Inte implementerat fel

Medan ett uttryck utvecklas kanske en författare vill utelämna implementeringen för vissa delar av uttrycket, men kanske fortfarande vill kunna köra uttrycket. Ett sätt att hantera det här fallet är att skapa ett fel för de ogenomförda delarna. Till exempel:

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

Ellipssymbolen (...) kan användas som en genväg för error.

not-implemented-expression:
      ...

Följande motsvarar till exempel föregående exempel:

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