Zoeken…


Definitie van optie

Een Option is een gediscrimineerde unie met twee gevallen, None of Some .

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

Gebruik optie <'T> boven nulwaarden

In functionele programmeertalen zoals F# null als potentieel schadelijk en slechte stijl (niet-idiomatisch) beschouwd.

Beschouw deze C# code:

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

x.Length werpt als x null laten we bescherming toevoegen:

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

Of:

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

Of:

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

In idiomatische F# null waarden niet gebruikt, dus onze code ziet er zo uit:

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

Soms is het echter nodig om lege of ongeldige waarden weer te geven. Dan kunnen we Option<'T> :

let SomeFunction () : string option = ...

SomeFunction ofwel rendement Some string waarde of None . We extraheren de string met behulp van patroonovereenkomst

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

De reden dat deze code minder kwetsbaar is dan:

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

Dat komt omdat we Length niet kunnen aanroepen op een string option . We moeten de string extraheren met behulp van patroonvergelijking en hierdoor zijn we ervan verzekerd dat de string veilig is om te gebruiken.

Optiemodule maakt Railway Oriented Programming mogelijk

Foutafhandeling is belangrijk, maar kan van een elegant algoritme een puinhoop maken. Railway Oriented Programming ( ROP ) wordt gebruikt om foutafhandeling elegant en configureerbaar te maken.

Overweeg de eenvoudige functie 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

Het doel van f is de ingang ontleden string waarde (als er Some ) in een int . Als de int groter is dan 0 , werpen we het in een float . In alle andere gevallen redden we met None .

Hoewel, een uiterst eenvoudige functie de geneste match de leesbaarheid aanzienlijk vermindert.

ROP merkt op dat we twee soorten uitvoeringspaden in ons programma hebben

  1. Gelukkig pad - zal uiteindelijk Some waarde berekenen
  2. Foutpad - Alle andere paden produceren None

Omdat de foutpaden vaker voorkomen, nemen ze de code over. We willen graag dat de happy path-code het meest zichtbare codepad is.

Een equivalente functie g met ROP kan er zo uitzien:

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

Het lijkt veel op hoe we de neiging hebben om lijsten en sequenties in F# te verwerken.

Men ziet een Option<'T> zoals een List<'T> die alleen 0 of 1 element kan bevatten waar Option.bind zich gedraagt als List.pick (conceptueel Option.bind kaarten beter naar List.collect maar List.pick kan zijn gemakkelijker te begrijpen).

bind , filter en map behandelt de foutpaden en g bevat alleen de happy path-code.

Alle functies die direct accepteert Option<_> en keert terug Option<_> direct composable met |> en >> .

ROP verhoogt daarom de leesbaarheid en de configureerbaarheid.

Optietypes van C # gebruiken

Het is geen goed idee om Optietypen bloot te stellen aan C # -code, omdat C # geen manier heeft om ze aan te pakken. De opties zijn om FSharp.Core te introduceren als een afhankelijkheid in uw C # -project (wat u zou moeten doen als u een F # -bibliotheek gebruikt die niet is ontworpen voor interop met C #), of om None waarden te wijzigen in null .

Pre-F # 4.0

De manier om dit te doen, is een eigen conversiefunctie maken:

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

Voor waardetypen moet u hun toevlucht nemen tot boksen of het gebruik van System.Nullable .

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

F # 4.0

In F # 4.0, de functies ofObj , toObj , ofNullable en toNullable waarbij kennis met de Option -module. In F # interactive kunnen ze als volgt worden gebruikt:

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

Merk op dat None compileert om null intern. Wat F # betreft, is het echter 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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow