Coincidencia de modelosPattern Matching

Los patrones son reglas para transformar los datos de entrada.Patterns are rules for transforming input data. Se usan en todo el F# lenguaje para comparar los datos con una estructura lógica o estructuras, descomponer los datos en partes constituyentes o extraer información de los datos de varias maneras.They are used throughout the F# language to compare data with a logical structure or structures, decompose data into constituent parts, or extract information from data in various ways.

ComentariosRemarks

Los patrones se usan en muchas construcciones de lenguaje, como la expresión match.Patterns are used in many language constructs, such as the match expression. Se utilizan cuando se procesan argumentos para funciones en enlaces de let, expresiones lambda y en los controladores de excepción asociados a la expresión try...with.They are used when you are processing arguments for functions in let bindings, lambda expressions, and in the exception handlers associated with the try...with expression. Para obtener más información, Vea expresiones de coincidencia, enlaces Let, expresiones Lambda: la palabra clave funy excepciones: la expresión try...with.For more information, see Match Expressions, let Bindings, Lambda Expressions: The fun Keyword, and Exceptions: The try...with Expression.

Por ejemplo, en la expresión match, el patrón es lo que sigue al símbolo de canalización.For example, in the match expression, the pattern is what follows the pipe symbol.

match expression with
| pattern [ when condition ] -> result-expression
...

Cada patrón actúa como una regla para transformar la entrada de alguna manera.Each pattern acts as a rule for transforming input in some way. En la expresión match, cada patrón se examina a su vez para ver si los datos de entrada son compatibles con el patrón.In the match expression, each pattern is examined in turn to see if the input data is compatible with the pattern. Si se encuentra una coincidencia, se ejecuta la expresión de resultado.If a match is found, the result expression is executed. Si no se encuentra ninguna coincidencia, se prueba la siguiente regla de patrón.If a match is not found, the next pattern rule is tested. La parte de condición opcional when se explica en expresiones de coincidencia.The optional when condition part is explained in Match Expressions.

Los patrones admitidos se muestran en la tabla siguiente.Supported patterns are shown in the following table. En tiempo de ejecución, la entrada se prueba con cada uno de los patrones siguientes en el orden indicado en la tabla y los patrones se aplican de forma recursiva, de la primera a la última como aparecen en el código y de izquierda a derecha para los patrones de cada línea.At run time, the input is tested against each of the following patterns in the order listed in the table, and patterns are applied recursively, from first to last as they appear in your code, and from left to right for the patterns on each line.

NameName DescripciónDescription EjemploExample
Patrón de constanteConstant pattern Cualquier literal numérico, de carácter o de cadena, una constante de enumeración o un identificador literal definidoAny numeric, character, or string literal, an enumeration constant, or a defined literal identifier 1.0, "test", 30, Color.Red1.0, "test", 30, Color.Red
Patrón de identificadorIdentifier pattern Un valor de caso de una Unión discriminada, una etiqueta de excepción o un caso de modelo activoA case value of a discriminated union, an exception label, or an active pattern case Some(x)

Failure(msg)
Patrón de variableVariable pattern identifieridentifier a
patrón de asas pattern patrón como identificadorpattern as identifier (a, b) as tuple1
Patrón OROR pattern pattern1 | pattern2pattern1 | pattern2 ([h] | [h; _])
Y patrónAND pattern pattern1 & pattern2pattern1 & pattern2 (a, b) & (_, "test")
Patrón de consCons pattern Identifier :: List-Identifieridentifier :: list-identifier h :: t
Patrón de listaList pattern [ pattern_1;...; pattern_n ][ pattern_1; ... ; pattern_n ] [ a; b; c ]
Patrón de matrizArray pattern [| pattern_1;... pattern_n |][| pattern_1; ..; pattern_n |] [| a; b; c |]
Patrón entre paréntesisParenthesized pattern ( patrón )( pattern ) ( a )
Patrón de tuplaTuple pattern ( pattern_1,..., pattern_n )( pattern_1, ... , pattern_n ) ( a, b )
Patrón de registroRecord pattern { identificador1 = pattern_1;...; identifier_n = pattern_n }{ identifier1 = pattern_1; ... ; identifier_n = pattern_n } { Name = name; }
Patrón de carácter comodínWildcard pattern _
Patrón junto con anotación de tipoPattern together with type annotation patrón : tipopattern : type a : int
Modelo de prueba de tipoType test pattern :?:? tipo [como identificador ]type [ as identifier ] :? System.DateTime as dt
Patrón nullNull pattern nulonull null

Patrones constantesConstant Patterns

Los patrones constantes son los literales numéricos, de carácter y de cadena, las constantes de enumeración (con el nombre de tipo de enumeración incluido).Constant patterns are numeric, character, and string literals, enumeration constants (with the enumeration type name included). Una expresión match que solo tiene patrones constantes puede compararse con una instrucción Case en otros lenguajes.A match expression that has only constant patterns can be compared to a case statement in other languages. La entrada se compara con el valor literal y el patrón coincide si los valores son iguales.The input is compared with the literal value and the pattern matches if the values are equal. El tipo del literal debe ser compatible con el tipo de la entrada.The type of the literal must be compatible with the type of the input.

En el ejemplo siguiente se muestra el uso de patrones literales y también se usa un patrón de variable y un patrón o.The following example demonstrates the use of literal patterns, and also uses a variable pattern and an OR pattern.

[<Literal>]
let Three = 3

let filter123 x =
    match x with
    // The following line contains literal patterns combined with an OR pattern.
    | 1 | 2 | Three -> printfn "Found 1, 2, or 3!"
    // The following line contains a variable pattern.
    | var1 -> printfn "%d" var1

for x in 1..10 do filter123 x

Otro ejemplo de un patrón literal es un modelo basado en constantes de enumeración.Another example of a literal pattern is a pattern based on enumeration constants. Debe especificar el nombre del tipo de enumeración al usar constantes de enumeración.You must specify the enumeration type name when you use enumeration constants.

type Color =
    | Red = 0
    | Green = 1
    | Blue = 2

let printColorName (color:Color) =
    match color with
    | Color.Red -> printfn "Red"
    | Color.Green -> printfn "Green"
    | Color.Blue -> printfn "Blue"
    | _ -> ()

printColorName Color.Red
printColorName Color.Green
printColorName Color.Blue

Patrones de identificadorIdentifier Patterns

Si el patrón es una cadena de caracteres que forma un identificador válido, el formato del identificador determina cómo coincide el patrón.If the pattern is a string of characters that forms a valid identifier, the form of the identifier determines how the pattern is matched. Si el identificador es más largo que un carácter único y comienza con un carácter en mayúsculas, el compilador intenta establecer una coincidencia con el patrón de identificador.If the identifier is longer than a single character and starts with an uppercase character, the compiler tries to make a match to the identifier pattern. El identificador de este patrón puede ser un valor marcado con el atributo literal, un caso de Unión discriminada, un identificador de excepción o un caso de modelo activo.The identifier for this pattern could be a value marked with the Literal attribute, a discriminated union case, an exception identifier, or an active pattern case. Si no se encuentra ningún identificador coincidente, se produce un error en la coincidencia y la siguiente regla de patrón, el patrón de variable, se compara con la entrada.If no matching identifier is found, the match fails and the next pattern rule, the variable pattern, is compared to the input.

Los patrones de Unión discriminada pueden ser casos con nombre sencillos o pueden tener un valor o una tupla que contiene varios valores.Discriminated union patterns can be simple named cases or they can have a value, or a tuple containing multiple values. Si hay un valor, debe especificar un identificador para el valor.If there is a value, you must specify an identifier for the value. En el caso de una tupla, debe proporcionar un patrón de tupla con un identificador para cada elemento de la tupla o un identificador con un nombre de campo para uno o más campos de unión con nombre.In the case of a tuple, you must supply a tuple pattern with an identifier for each element of the tuple or an identifier with a field name for one or more named union fields. Vea los ejemplos de código de esta sección para obtener ejemplos.See the code examples in this section for examples.

El option tipo es una Unión discriminada que tiene dos casos, Some y None.The option type is a discriminated union that has two cases, Some and None. Un caso (Some) tiene un valor, pero el otro (None) es simplemente un caso con nombre.One case (Some) has a value, but the other (None) is just a named case. Por lo tanto, Some necesita tener una variable para el valor asociado al Some caso, pero None debe aparecer por sí sola.Therefore, Some needs to have a variable for the value associated with the Some case, but None must appear by itself. En el código siguiente, a la variable var1 se le proporciona el valor que se obtiene al buscar coincidencias con el Some caso.In the following code, the variable var1 is given the value that is obtained by matching to the Some case.

let printOption (data : int option) =
    match data with
    | Some var1  -> printfn "%d" var1
    | None -> ()

En el ejemplo siguiente, la Unión discriminada PersonName contiene una mezcla de cadenas y caracteres que representan las posibles formas de los nombres.In the following example, the PersonName discriminated union contains a mixture of strings and characters that represent possible forms of names. Los casos de la Unión discriminada son FirstOnly, LastOnlyy FirstLast.The cases of the discriminated union are FirstOnly, LastOnly, and FirstLast.

type PersonName =
    | FirstOnly of string
    | LastOnly of string
    | FirstLast of string * string

let constructQuery personName =
    match personName with
    | FirstOnly(firstName) -> printf "May I call you %s?" firstName
    | LastOnly(lastName) -> printf "Are you Mr. or Ms. %s?" lastName
    | FirstLast(firstName, lastName) -> printf "Are you %s %s?" firstName lastName

En el caso de las uniones discriminadas que tienen campos con nombre, use el signo igual (=) para extraer el valor de un campo con nombre.For discriminated unions that have named fields, you use the equals sign (=) to extract the value of a named field. Por ejemplo, considere una Unión discriminada con una declaración como la siguiente.For example, consider a discriminated union with a declaration like the following.

type Shape =
    | Rectangle of height : float * width : float
    | Circle of radius : float

Puede usar los campos con nombre en una expresión de coincidencia de patrones como se indica a continuación.You can use the named fields in a pattern matching expression as follows.

let matchShape shape =
    match shape with
    | Rectangle(height = h) -> printfn "Rectangle with length %f" h
    | Circle(r) -> printfn "Circle with radius %f" r

El uso del campo con nombre es opcional, por lo que en el ejemplo anterior, tanto Circle(r) como Circle(radius = r) tienen el mismo efecto.The use of the named field is optional, so in the previous example, both Circle(r) and Circle(radius = r) have the same effect.

Cuando especifique varios campos, use el punto y coma (;) como separador.When you specify multiple fields, use the semicolon (;) as a separator.

match shape with
| Rectangle(height = h; width = w) -> printfn "Rectangle with height %f and width %f" h w
| _ -> ()

Los modelos activos permiten definir una coincidencia de patrones personalizada más compleja.Active patterns enable you to define more complex custom pattern matching. Para obtener más información sobre los patrones activos, vea patrones activos.For more information about active patterns, see Active Patterns.

El caso en el que el identificador es una excepción se usa en la coincidencia de patrones en el contexto de los controladores de excepciones.The case in which the identifier is an exception is used in pattern matching in the context of exception handlers. Para obtener información sobre la coincidencia de patrones en el control de excepciones, vea excepciones: la expresión try...with.For information about pattern matching in exception handling, see Exceptions: The try...with Expression.

Patrones de variablesVariable Patterns

El patrón variable asigna el valor que coincide con un nombre de variable, que está disponible para su uso en la expresión de ejecución a la derecha del símbolo ->.The variable pattern assigns the value being matched to a variable name, which is then available for use in the execution expression to the right of the -> symbol. Un patrón variable solo coincide con cualquier entrada, pero los modelos variables suelen aparecer dentro de otros patrones, lo que permite que las estructuras más complejas, como las tuplas y las matrices, se descompongan en variables.A variable pattern alone matches any input, but variable patterns often appear within other patterns, therefore enabling more complex structures such as tuples and arrays to be decomposed into variables.

En el ejemplo siguiente se muestra un patrón de variable dentro de un patrón de tupla.The following example demonstrates a variable pattern within a tuple pattern.

let function1 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

function1 (1,2)
function1 (2, 1)
function1 (0, 0)

como patrónas Pattern

El patrón as es un patrón que tiene una cláusula as anexada a él.The as pattern is a pattern that has an as clause appended to it. La cláusula as enlaza el valor coincidente con un nombre que se puede usar en la expresión de ejecución de una expresión match, o bien, en el caso en el que este patrón se usa en un enlace de let, el nombre se agrega como un enlace al ámbito local.The as clause binds the matched value to a name that can be used in the execution expression of a match expression, or, in the case where this pattern is used in a let binding, the name is added as a binding to the local scope.

En el ejemplo siguiente se usa un patrón de as.The following example uses an as pattern.

let (var1, var2) as tuple1 = (1, 2)
printfn "%d %d %A" var1 var2 tuple1

Patrón OROR Pattern

El patrón o se utiliza cuando los datos de entrada pueden coincidir con varios patrones y desea ejecutar el mismo código como resultado.The OR pattern is used when input data can match multiple patterns, and you want to execute the same code as a result. Los tipos de ambos lados del patrón o deben ser compatibles.The types of both sides of the OR pattern must be compatible.

En el siguiente ejemplo se muestra el patrón o.The following example demonstrates the OR pattern.

let detectZeroOR point =
    match point with
    | (0, 0) | (0, _) | (_, 0) -> printfn "Zero found."
    | _ -> printfn "Both nonzero."
detectZeroOR (0, 0)
detectZeroOR (1, 0)
detectZeroOR (0, 10)
detectZeroOR (10, 15)

Y patrónAND Pattern

El patrón y requiere que la entrada coincida con dos patrones.The AND pattern requires that the input match two patterns. Los tipos de ambos lados del patrón y deben ser compatibles.The types of both sides of the AND pattern must be compatible.

El ejemplo siguiente es como detectZeroTuple se muestra en la sección modelo de tupla más adelante en este tema, pero aquí tanto var1 como var2 se obtienen como valores mediante el patrón y.The following example is like detectZeroTuple shown in the Tuple Pattern section later in this topic, but here both var1 and var2 are obtained as values by using the AND pattern.

let detectZeroAND point =
    match point with
    | (0, 0) -> printfn "Both values zero."
    | (var1, var2) & (0, _) -> printfn "First value is 0 in (%d, %d)" var1 var2
    | (var1, var2)  & (_, 0) -> printfn "Second value is 0 in (%d, %d)" var1 var2
    | _ -> printfn "Both nonzero."
detectZeroAND (0, 0)
detectZeroAND (1, 0)
detectZeroAND (0, 10)
detectZeroAND (10, 15)

Patrón de consCons Pattern

El patrón cons se usa para descomponer una lista en el primer elemento, el encabezadoy una lista que contiene los elementos restantes, la cola.The cons pattern is used to decompose a list into the first element, the head, and a list that contains the remaining elements, the tail.

let list1 = [ 1; 2; 3; 4 ]

// This example uses a cons pattern and a list pattern.
let rec printList l =
    match l with
    | head :: tail -> printf "%d " head; printList tail
    | [] -> printfn ""

printList list1

Patrón de listaList Pattern

El patrón de lista permite descomponer listas en varios elementos.The list pattern enables lists to be decomposed into a number of elements. El propio patrón de lista solo puede coincidir con las listas de un número específico de elementos.The list pattern itself can match only lists of a specific number of elements.

// This example uses a list pattern.
let listLength list =
    match list with
    | [] -> 0
    | [ _ ] -> 1
    | [ _; _ ] -> 2
    | [ _; _; _ ] -> 3
    | _ -> List.length list

printfn "%d" (listLength [ 1 ])
printfn "%d" (listLength [ 1; 1 ])
printfn "%d" (listLength [ 1; 1; 1; ])
printfn "%d" (listLength [ ] )

Patrón de matrizArray Pattern

El patrón de matriz se asemeja al patrón de lista y se puede usar para descomponer las matrices de una longitud específica.The array pattern resembles the list pattern and can be used to decompose arrays of a specific length.

// This example uses array patterns.
let vectorLength vec =
    match vec with
    | [| var1 |] -> var1
    | [| var1; var2 |] -> sqrt (var1*var1 + var2*var2)
    | [| var1; var2; var3 |] -> sqrt (var1*var1 + var2*var2 + var3*var3)
    | _ -> failwith "vectorLength called with an unsupported array size of %d." (vec.Length)

printfn "%f" (vectorLength [| 1. |])
printfn "%f" (vectorLength [| 1.; 1. |])
printfn "%f" (vectorLength [| 1.; 1.; 1.; |])
printfn "%f" (vectorLength [| |] )

Patrón entre paréntesisParenthesized Pattern

Los paréntesis se pueden agrupar en torno a patrones para lograr la asociatividad deseada.Parentheses can be grouped around patterns to achieve the desired associativity. En el ejemplo siguiente, los paréntesis se usan para controlar la asociatividad entre un patrón AND y un patrón cons.In the following example, parentheses are used to control associativity between an AND pattern and a cons pattern.

let countValues list value =
    let rec checkList list acc =
       match list with
       | (elem1 & head) :: tail when elem1 = value -> checkList tail (acc + 1)
       | head :: tail -> checkList tail acc
       | [] -> acc
    checkList list 0

let result = countValues [ for x in -10..10 -> x*x - 4 ] 0
printfn "%d" result

Patrón de tuplaTuple Pattern

El patrón de tupla asocia la entrada en forma de tupla y permite descomponer la tupla en sus elementos constituyentes mediante el uso de variables de coincidencia de patrones para cada posición de la tupla.The tuple pattern matches input in tuple form and enables the tuple to be decomposed into its constituent elements by using pattern matching variables for each position in the tuple.

En el ejemplo siguiente se muestra el patrón de tupla y también se usan patrones literales, patrones de variables y el patrón de caracteres comodín.The following example demonstrates the tuple pattern and also uses literal patterns, variable patterns, and the wildcard pattern.

let detectZeroTuple point =
    match point with
    | (0, 0) -> printfn "Both values zero."
    | (0, var2) -> printfn "First value is 0 in (0, %d)" var2
    | (var1, 0) -> printfn "Second value is 0 in (%d, 0)" var1
    | _ -> printfn "Both nonzero."
detectZeroTuple (0, 0)
detectZeroTuple (1, 0)
detectZeroTuple (0, 10)
detectZeroTuple (10, 15)

Patrón de registroRecord Pattern

El patrón de registro se usa para descomponer registros para extraer los valores de los campos.The record pattern is used to decompose records to extract the values of fields. El patrón no tiene que hacer referencia a todos los campos del registro; los campos omitidos simplemente no participan en la coincidencia y no se extraen.The pattern does not have to reference all fields of the record; any omitted fields just do not participate in matching and are not extracted.

// This example uses a record pattern.

type MyRecord = { Name: string; ID: int }

let IsMatchByName record1 (name: string) =
    match record1 with
    | { MyRecord.Name = nameFound; MyRecord.ID = _; } when nameFound = name -> true
    | _ -> false

let recordX = { Name = "Parker"; ID = 10 }
let isMatched1 = IsMatchByName recordX "Parker"
let isMatched2 = IsMatchByName recordX "Hartono"

Patrón de carácter comodínWildcard Pattern

El patrón de caracteres comodín se representa mediante el carácter de subrayado (_) y coincide con cualquier entrada, al igual que el patrón de variable, con la excepción de que la entrada se descarta en lugar de asignarla a una variable.The wildcard pattern is represented by the underscore (_) character and matches any input, just like the variable pattern, except that the input is discarded instead of assigned to a variable. El patrón de caracteres comodín se usa a menudo en otros patrones como un marcador de posición para los valores que no son necesarios en la expresión a la derecha del símbolo ->.The wildcard pattern is often used within other patterns as a placeholder for values that are not needed in the expression to the right of the -> symbol. El patrón de caracteres comodín también se usa con frecuencia al final de una lista de patrones para buscar coincidencias con cualquier entrada no coincidente.The wildcard pattern is also frequently used at the end of a list of patterns to match any unmatched input. El patrón de caracteres comodín se muestra en muchos ejemplos de código de este tema.The wildcard pattern is demonstrated in many code examples in this topic. Vea el código anterior para ver un ejemplo.See the preceding code for one example.

Patrones que tienen anotaciones de tipoPatterns That Have Type Annotations

Los patrones pueden tener anotaciones de tipo.Patterns can have type annotations. Estos se comportan como otras anotaciones de tipo e inferencia de la guía como otras anotaciones de tipo.These behave like other type annotations and guide inference like other type annotations. Se requieren paréntesis en torno a las anotaciones de tipo en los patrones.Parentheses are required around type annotations in patterns. En el código siguiente se muestra un patrón que tiene una anotación de tipo.The following code shows a pattern that has a type annotation.

let detect1 x =
    match x with
    | 1 -> printfn "Found a 1!"
    | (var1 : int) -> printfn "%d" var1
detect1 0
detect1 1

Modelo de prueba de tipoType Test Pattern

El modelo de prueba de tipo se usa para hacer coincidir la entrada con un tipo.The type test pattern is used to match the input against a type. Si el tipo de entrada es una coincidencia con (o un tipo derivado de) el tipo especificado en el patrón, la coincidencia se realiza correctamente.If the input type is a match to (or a derived type of) the type specified in the pattern, the match succeeds.

En el siguiente ejemplo se muestra el modelo de prueba de tipo.The following example demonstrates the type test pattern.

open System.Windows.Forms

let RegisterControl(control:Control) =
    match control with
    | :? Button as button -> button.Text <- "Registered."
    | :? CheckBox as checkbox -> checkbox.Text <- "Registered."
    | _ -> ()

Si solo está comprobando si un identificador es de un tipo derivado determinado, no necesita la parte as identifier del patrón, tal como se muestra en el ejemplo siguiente:If you're only checking if an identifier is of a particular derived type, you don't need the as identifier part of the pattern, as shown in the following example:

type A() = class end
type B() = inherit A()
type C() = inherit A()

let m (a: A) =
    match a with
    | :? B -> printfn "It's a B"
    | :? C -> printfn "It's a C"
    | _ -> ()

Patrón nullNull Pattern

El patrón null coincide con el valor null que puede aparecer cuando se trabaja con tipos que permiten un valor null.The null pattern matches the null value that can appear when you are working with types that allow a null value. Los patrones NULL se utilizan con frecuencia al interoperar con código de .NET Framework.Null patterns are frequently used when interoperating with .NET Framework code. Por ejemplo, el valor devuelto de una API de .NET podría ser la entrada a una expresión match.For example, the return value of a .NET API might be the input to a match expression. Puede controlar el flujo del programa en función de si el valor devuelto es NULL y también de otras características del valor devuelto.You can control program flow based on whether the return value is null, and also on other characteristics of the returned value. Puede usar el patrón null para evitar que los valores NULL se propaguen al resto del programa.You can use the null pattern to prevent null values from propagating to the rest of your program.

En el ejemplo siguiente se usa el patrón NULL y el patrón variable.The following example uses the null pattern and the variable pattern.

let ReadFromFile (reader : System.IO.StreamReader) =
    match reader.ReadLine() with
    | null -> printfn "\n"; false
    | line -> printfn "%s" line; true

let fs = System.IO.File.Open("..\..\Program.fs", System.IO.FileMode.Open)
let sr = new System.IO.StreamReader(fs)
while ReadFromFile(sr) = true do ()
sr.Close()

Vea tambiénSee also