Suche…


Definition der Option

Eine Option ist eine diskriminierte Gewerkschaft mit zwei Fällen: None oder Some .

type Option<'T> = Some of 'T | None

Verwenden Sie die Option <'T> über Nullwerte

In funktionalen Programmiersprachen wie F# null als potenziell schädlich und als schlecht (nicht idiomatisch) angesehen.

Betrachten Sie diesen C# -Code:

string x = SomeFunction ();
int    l = x.Length;

x.Length wird geworfen, wenn x null , fügen Sie den Schutz hinzu:

string x = SomeFunction ();
int    l = x != null ? x.Length : 0;

Oder:

string x = SomeFunction () ?? "";
int    l = x.Length;

Oder:

string x = SomeFunction ();
int    l = x?.Length;

In idiomatic werden keine F# null verwendet, daher sieht unser Code folgendermaßen aus:

let x = SomeFunction ()
let l = x.Length

Manchmal müssen jedoch leere oder ungültige Werte dargestellt werden. Dann können wir Option<'T> :

let SomeFunction () : string option = ...

SomeFunction entweder Some string oder None . Wir extrahieren den string Wert mithilfe von Pattern-Matching

let v =
  match SomeFunction () with
  | Some x  -> x.Length
  | None    -> 0

Der Grund, warum dieser Code weniger anfällig ist als:

string x = SomeFunction ();
int    l = x.Length;

Ist, weil wir Length mit einer string option aufrufen können. Wir müssen den string Wert mithilfe von Pattern-Matching extrahieren. Dadurch wird sichergestellt, dass der string Wert sicher verwendet werden kann.

Das Optionsmodul ermöglicht die eisenbahnorientierte Programmierung

Fehlerbehandlung ist wichtig, kann jedoch einen eleganten Algorithmus zum Durcheinander bringen. Eisenbahnorientierte Programmierung ( ROP ) wird verwendet, um die Fehlerbehandlung elegant und komponierbar zu gestalten.

Betrachten Sie die einfache Funktion f :

let tryParse s =
  let b, v = System.Int32.TryParse s
  if b then Some v else None

let f (g : string option) : float option =
  match g with
  | None    -> None
  | Some s  ->
    match tryParse s with           // Parses string to int
    | None              -> None
    | Some v when v < 0 -> None     // Checks that int is greater than 0
    | Some v -> v |> float |> Some  // Maps int to float

Der Zweck von f ist die Eingabe zu analysieren string - Wert (wenn es Some ) in einen int . Wenn das int größer als 0 , werfen wir es in einen float . In allen anderen Fällen retten wir mit None .

Eine extrem einfache Funktion, die verschachtelte match verringert jedoch die Lesbarkeit erheblich.

ROP stellt fest, dass wir zwei Arten von Ausführungspfaden in unserem Programm haben

  1. Glücklicher Weg - Will irgendwann Some Wert berechnen
  2. Fehlerpfad - Alle anderen Pfade erzeugen None

Da die Fehlerpfade häufiger sind, neigen sie dazu, den Code zu übernehmen. Wir möchten, dass der Happy-Path-Code der sichtbarste Codepfad ist.

Eine äquivalente Funktion g die ROP könnte folgendermaßen aussehen:

let g (v : string option) : float option =
  v
  |> Option.bind    tryParse  // Parses string to int
  |> Option.filter  ((<) 0)   // Checks that int is greater than 0
  |> Option.map     float     // Maps int to float

Es sieht sehr danach aus, wie wir Listen und Sequenzen in F# .

Man kann eine Option<'T> wie eine List<'T> , die nur 0 oder 1 Elemente enthalten kann, wobei Option.bind sich wie List.pick verhält (konzeptionell ist Option.bind besser auf List.collect List.pick möglicherweise jedoch List.pick leichter zu verstehen).

bind , filter und map behandelt die Fehlerpfade und g enthält nur den Code für den glücklichen Pfad.

Alle Funktionen, die Option<_> direkt akzeptieren und Option<_> direkt mit |> und >> .

ROP erhöht daher die Lesbarkeit und Komposierbarkeit.

Verwendung von Optionstypen aus C #

Es ist keine gute Idee, Optionstypen mit C # -Code zu versehen, da C # keine Möglichkeit hat, sie zu behandeln. Sie haben die Möglichkeit, entweder FSharp.Core als Abhängigkeit in Ihrem C # -Projekt einzuführen (was Sie tun müssten, wenn Sie eine F # -Bibliothek verwenden, die nicht für die Interop mit C # vorgesehen ist) oder die Werte von None in null ändern.

Pre-F # 4.0

Dazu erstellen Sie eine eigene Konvertierungsfunktion:

let OptionToObject opt =
    match opt with
    | Some x -> x 
    | None -> null

Für System.Nullable Sie auf Boxen oder System.Nullable .

let OptionToNullable x = 
    match x with 
    | Some i -> System.Nullable i
    | None -> System.Nullable ()

F # 4.0

In F # 4.0 wurden die Funktionen ofObj , toObj , ofNullable und toNullable in das Option . In F # interactive können sie wie folgt verwendet werden:

let l1 = [ Some 1 ; None ; Some 2]
let l2 = l1 |> List.map Option.toNullable;;

// val l1 : int option list = [Some 1; null; Some 2]
// val l2 : System.Nullable<int> list = [1; null; 2]

let l3 = l2 |> List.map Option.ofNullable;;
// val l3 : int option list = [Some 1; null; Some 2]

// Equality
l1 = l2 // fails to compile: different types
l1 = l3 // true

Beachten Sie, dass None intern zu null kompiliert wird. Für F # ist dies jedoch None .

let lA = [Some "a"; None; Some "b"]
let lB = lA |> List.map Option.toObj

// val lA : string option list = [Some "a"; null; Some "b"]
// val lB : string list = ["a"; null; "b"]

let lC = lB |> List.map Option.ofObj
// val lC : string option list = [Some "a"; null; Some "b"]

// Equality
lA = lB // fails to compile: different types
lA = lC // true


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow