F # - Correspondência de padrões

A correspondência de padrões permite “comparar dados com uma estrutura ou estruturas lógicas, decompor dados em partes constituintes ou extrair informações de dados de várias maneiras”.

Em outros termos, ele fornece uma maneira mais flexível e poderosa de testar dados em uma série de condições e realizar alguns cálculos com base na condição encontrada.

Conceitualmente, é como uma série de declarações if ... then.

Sintaxe

Em termos de alto nível, a correspondência de padrões segue esta sintaxe em F # -

match expr with
| pat1 - result1
| pat2 -> result2
| pat3 when expr2 -> result3
| _ -> defaultResult

Onde,

  • Cada | símbolo define uma condição.
  • O símbolo -> significa "se a condição for verdadeira, retorne este valor ...".
  • O símbolo _ fornece o padrão padrão, o que significa que ele corresponde a todas as outras coisas, como um curinga.

Exemplo 1

O exemplo a seguir calcula os números de Fibonacci usando a sintaxe de correspondência de padrões -

let rec fib n =
   match n with
   | 0 -> 0
   | 1 -> 1
   | _ -> fib (n - 1) + fib (n - 2)
for i = 1 to 10 do
   printfn "Fibonacci %d: %d" i (fib i)

Quando você compila e executa o programa, ele produz a seguinte saída -

Fibonacci 1: 1
Fibonacci 2: 1
Fibonacci 3: 2
Fibonacci 4: 3
Fibonacci 5: 5
Fibonacci 6: 8
Fibonacci 7: 13
Fibonacci 8: 21
Fibonacci 9: 34
Fibonacci 10: 55

Você também pode encadear várias condições, que retornam o mesmo valor. Por exemplo -

Exemplo 2

let printSeason month =
   match month with
   | "December" | "January" | "February" -> printfn "Winter"
   | "March" | "April" -> printfn "Spring"
   | "May" | "June" -> printfn "Summer"
   | "July" | "August" -> printfn "Rainy"
   | "September" | "October" | "November" -> printfn "Autumn"
   | _ -> printfn "Season depends on month!"

printSeason "February"
printSeason "April"
printSeason "November"
printSeason "July"

Quando você compila e executa o programa, ele produz a seguinte saída -

Winter
Spring
Autumn
Rainy

Funções de correspondência de padrões

F # permite que você escreva funções de correspondência de padrões usando o function palavra-chave -

let getRate = function
   | "potato" -> 10.00
   | "brinjal" -> 20.50
   | "cauliflower" -> 21.00
   | "cabbage" -> 8.75
   | "carrot" -> 15.00
   | _ -> nan (* nan is a special value meaning "not a number" *)

printfn "%g"(getRate "potato")
printfn "%g"(getRate "brinjal")
printfn "%g"(getRate "cauliflower")
printfn "%g"(getRate "cabbage")
printfn "%g"(getRate "carrot")

Quando você compila e executa o programa, ele produz a seguinte saída -

10
20.5
21
8.75
15

Adicionando Filtros ou Protetores aos Padrões

Você pode adicionar filtros ou proteções aos padrões usando o when palavra-chave.

Exemplo 1

let sign = function
   | 0 -> 0
   | x when x < 0 -> -1
   | x when x > 0 -> 1

printfn "%d" (sign -20)
printfn "%d" (sign 20)
printfn "%d" (sign 0)

Quando você compila e executa o programa, ele produz a seguinte saída -

-1
1
0

Exemplo 2

let compareInt x =
   match x with
   | (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
   | (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
   | (var1, var2) -> printfn "%d equals %d" var1 var2

compareInt (11,25)
compareInt (72, 10)
compareInt (0, 0)

Quando você compila e executa o programa, ele produz a seguinte saída -

11 is less than 25
72 is greater than 10
0 equals 0

Correspondência de padrões com tuplas

O exemplo a seguir demonstra o padrão de correspondência com tuplas -

let greeting (name, subject) =
   match (name, subject) with
   | ("Zara", _) -> "Hello, Zara"
   | (name, "English") -> "Hello, " + name + " from the department of English"
   | (name, _) when subject.StartsWith("Comp") -> "Hello, " + name + " from the department of Computer Sc."
   | (_, "Accounts and Finance") -> "Welcome to the department of Accounts and Finance!"
   | _ -> "You are not registered into the system"

printfn "%s" (greeting ("Zara", "English"))
printfn "%s" (greeting ("Raman", "Computer Science"))
printfn "%s" (greeting ("Ravi", "Mathematics"))

Quando você compila e executa o programa, ele produz a seguinte saída -

Hello, Zara
Hello, Raman from the department of Computer Sc.
You are not registered into the system

Correspondência de padrões com registros

O exemplo a seguir demonstra a correspondência de padrões com registros -

type Point = { x: float; y: float }
let evaluatePoint (point: Point) =
   match point with
   | { x = 0.0; y = 0.0 } -> printfn "Point is at the origin."
   | { x = xVal; y = 0.0 } -> printfn "Point is on the x-axis. Value is %f." xVal
   | { x = 0.0; y = yVal } -> printfn "Point is on the y-axis. Value is %f." yVal
   | { x = xVal; y = yVal } -> printfn "Point is at (%f, %f)." xVal yVal

evaluatePoint { x = 0.0; y = 0.0 }
evaluatePoint { x = 10.0; y = 0.0 }
evaluatePoint { x = 0.0; y = 10.0 }
evaluatePoint { x = 10.0; y = 10.0 }

Quando você compila e executa o programa, ele produz a seguinte saída -

Point is at the origin.
Point is on the x-axis. Value is 10.000000.
Point is on the y-axis. Value is 10.000000.
Point is at (10.000000, 10.000000).