Udostępnij za pośrednictwem


Wzorce aktywne (F#)

Desenie Active pozwalają zdefiniować nazwany partycje, które należy podzielić dane wejściowe, można użyć tych nazw w wzorzec dopasowania wyrażenia tak samo, jak dla dyskryminowanych Unii.Aktywne wzorców można użyć do danych w sposób dostosowany dla każdej partycja.

// Complete active pattern definition.
let (|identifer1|identifier2|...|) [ arguments ] = expression
// Partial active pattern definition.
let (|identifier|_|) [ arguments ] = expression

Uwagi

W poprzednich składni identyfikatory są nazwy partycji danych wejściowych, która jest reprezentowana przez arguments, lub innymi słowy, nazwy dla podzbiorów zestaw wszystkich wartości argumentów.W definicji active wzorzec może być maksymalnie siedem partycji.expression Opisuje formularz , do którego rozkładać dane.Definicja wzorca aktywnego umożliwia definiowanie zasady określające, które partycje nazwane wartości podane jako argumenty należą do.(| I |) symbole są określane jako klipy bananów i nosi nazwę funkcja , utworzony przez ten typ powiązania let rozpoznawania active.

Na przykład należy rozważyć następujący wzór aktywny z argument.

let (|Even|Odd|) input = if input % 2 = 0 then Even else Odd

We wzorcu dopasowania wyrażenia, jak w poniższym przykładzie, można używać active wzorca.

let TestNumber input =
   match input with
   | Even -> printfn "%d is even" input
   | Odd -> printfn "%d is odd" input

TestNumber 7
TestNumber 11
TestNumber 32

Dane wyjściowe tego programu jest w następujący sposób:

7 is odd
11 is odd
32 is even

Innym używanie wzorców, aktywny jest rozkładać typów danych na wiele sposobów, na przykład gdy ma różne reprezentacje możliwe w tych samych danych źródłowych.Na przykład Color obiekt może być rozłożony na reprezentację RGB lub HSB reprezentacji.

open System.Drawing

let (|RGB|) (col : System.Drawing.Color) =
     ( col.R, col.G, col.B )

let (|HSB|) (col : System.Drawing.Color) =
   ( col.GetHue(), col.GetSaturation(), col.GetBrightness() )

let printRGB (col: System.Drawing.Color) =
   match col with
   | RGB(r, g, b) -> printfn " Red: %d Green: %d Blue: %d" r g b

let printHSB (col: System.Drawing.Color) =
   match col with
   | HSB(h, s, b) -> printfn " Hue: %f Saturation: %f Brightness: %f" h s b

let printAll col colorString =
  printfn "%s" colorString
  printRGB col
  printHSB col

printAll Color.Red "Red"
printAll Color.Black "Black"
printAll Color.White "White"
printAll Color.Gray "Gray"
printAll Color.BlanchedAlmond "BlanchedAlmond"

Dane wyjściowe programu powyżej jest w następujący sposób:

Red
 R: 255 G: 0 B: 0
 H: 0.000000 S: 1.000000 B: 0.500000
Black
 R: 0 G: 0 B: 0
 H: 0.000000 S: 0.000000 B: 0.000000
White
 R: 255 G: 255 B: 255
 H: 0.000000 S: 0.000000 B: 1.000000
Gray
 R: 128 G: 128 B: 128
 H: 0.000000 S: 0.000000 B: 0.501961
BlanchedAlmond
 R: 255 G: 235 B: 205
 H: 36.000000 S: 1.000000 B: 0.901961

W połączeniu te dwa sposoby za pomocą wzorców, aktywny umożliwiają partycja i rozkładać dane do tylko odpowiedniej formularz i wykonywać odpowiednie obliczenia na odpowiednie dane w formularz najbardziej wygodne do obliczeń.

Wynikowy wzorzec wyrażenia pasujące włączyć dane są zapisywane w wygodny sposób, że jest bardzo czytelny, co znacznie upraszcza rozgałęzianie złożonych i kod analiza danych.

Częściowe desenie Active

Czasami trzeba partycja tylko część obszaru wejściowego.W takim przypadku piszesz zestaw częściowo desenie które odpowiadać niektóre dane wejściowe, ale nie odpowiadać innych nakładów.Nazywane są aktywne desenie, które zawsze nie dają wartość częściowo desenie active; mają wartości zwracanej, który jest typem opcji.Do definiowania częściowo deseń aktywny, użyć symbol wieloznaczny (_) na końcu listy wzorców wewnątrz klipów bananów.Poniższy kod ilustruje wykorzystanie częściowo deseń aktywne.

let (|Integer|_|) (str: string) =
   let mutable intvalue = 0
   if System.Int32.TryParse(str, &intvalue) then Some(intvalue)
   else None

let (|Float|_|) (str: string) =
   let mutable floatvalue = 0.0
   if System.Double.TryParse(str, &floatvalue) then Some(floatvalue)
   else None

let parseNumeric str =
   match str with
     | Integer i -> printfn "%d : Integer" i
     | Float f -> printfn "%f : Floating point" f
     | _ -> printfn "%s : Not matched." str

parseNumeric "1.1"
parseNumeric "0"
parseNumeric "0.0"
parseNumeric "10"
parseNumeric "Something else"

Dane wyjściowe z poprzedniego przykładu jest w następujący sposób:

1.100000 : Floating point
0 : Integer
0.000000 : Floating point
10 : Integer
Something else : Not matched.

Podczas korzystania z częściowo active desenie, czasami poszczególnych opcji może być odłączony lub wzajemnie się wykluczają, ale nie muszą być.W poniższym przykładzie kwadrat deseń i deseń modułu nie są rozłączne, ponieważ niektóre numery są zarówno kwadratów i modułów, takich jak 64.Poniższy program drukuje wszystkie liczby całkowite do 1000000, które są zarówno kwadratów i moduły.

let err = 1.e-10

let isNearlyIntegral (x:float) = abs (x - round(x)) < err

let (|Square|_|) (x : int) =
  if isNearlyIntegral (sqrt (float x)) then Some(x)
  else None

let (|Cube|_|) (x : int) =
  if isNearlyIntegral ((float x) ** ( 1.0 / 3.0)) then Some(x)
  else None

let examineNumber x =
   match x with
      | Cube x -> printfn "%d is a cube" x
      | _ -> ()
   match x with
      | Square x -> printfn "%d is a square" x
      | _ -> ()

let findSquareCubes x =
   if (match x with
       | Cube x -> true
       | _ -> false
       &&
       match x with
       | Square x -> true
       | _ -> false
      )
   then printf "%d \n" x

[ 1 .. 1000000 ] |> List.iter (fun elem -> findSquareCubes elem)

Produkcja jest w następujący sposób:

1
64
729
4096
15625
46656
117649
262144
531441
1000000

Sparametryzowana desenie Active

Aktywne wzorców zawsze trwać co najmniej jeden argument dla elementu filtrowanego, ale mogą przybierać dodatkowe argumenty, jak również, w którym to przypadku nazwa sparametryzowana deseń active stosuje się.Dodatkowe argumenty umożliwiają ogólne deseń być wyspecjalizowany.Na przykład, zawierać wyrażenie regularne active desenie, które używają wyrażeń regularnych do analizowania ciągów często jako dodatkowy parametr, w następujący kod, który używa również częściowo deseń active Integer określonych w poprzednim przykładzie kodu.W tym przykładzie ciągów, które używają wyrażeń regularnych w różnych formatach daty są podane do dostosowywać ogólnym modelem active ParseRegex.Wzorzec active całkowitą jest używany do konwertować ciągów dopasowanych do liczb całkowitych, które mogą być przekazywane do konstruktorelementu DateTime.

open System.Text.RegularExpressions

// ParseRegex parses a regular expression and returns a list of the strings that match each group in 
// the regular expression. 
// List.tail is called to eliminate the first element in the list, which is the full matched expression, 
// since only the matches for each group are wanted. 
let (|ParseRegex|_|) regex str =
   let m = Regex(regex).Match(str)
   if m.Success
   then Some (List.tail [ for x in m.Groups -> x.Value ])
   else None

// Three different date formats are demonstrated here. The first matches two- 
// digit dates and the second matches full dates. This code assumes that if a two-digit 
// date is provided, it is an abbreviation, not a year in the first century. 
let parseDate str =
   match str with
     | ParseRegex "(\d{1,2})/(\d{1,2})/(\d{1,2})$" [Integer m; Integer d; Integer y]
          -> new System.DateTime(y + 2000, m, d)
     | ParseRegex "(\d{1,2})/(\d{1,2})/(\d{3,4})" [Integer m; Integer d; Integer y]
          -> new System.DateTime(y, m, d)
     | ParseRegex "(\d{1,4})-(\d{1,2})-(\d{1,2})" [Integer y; Integer m; Integer d]
          -> new System.DateTime(y, m, d)
     | _ -> new System.DateTime()

let dt1 = parseDate "12/22/08" 
let dt2 = parseDate "1/1/2009" 
let dt3 = parseDate "2008-1-15" 
let dt4 = parseDate "1995-12-28"

printfn "%s %s %s %s" (dt1.ToString()) (dt2.ToString()) (dt3.ToString()) (dt4.ToString())

Dane wyjściowe poprzedniego kodu jest w następujący sposób:

12/22/2008 12:00:00 AM 1/1/2009 12:00:00 AM 1/15/2008 12:00:00 AM 12/28/1995 12:00:00 AM

Zobacz też

Informacje

Wyrażenia dopasowania (F#)

Inne zasoby

Materiały referencyjne dotyczące języka F#