Este artigo não cita fontes confiáveis. (Fevereiro de 2019) |
Em ciência da computação, casamento de padrões é o ato de verificação da presença de um padrão em um conjunto de dados. Em contraste ao reconhecimento de padrões, o padrão é rigidamente especificado, seja por uma cadeia de caracteres ou uma árvore. O casamento de padrões é usado para testar se o objeto de estudo possui a estrutura desejada, para então encontrar a estrutura relevante, encontrar os pontos de alinhamento e substituir a parte do casamento por outra estrutura. Padrões de sequência (como cadeias de texto) são geralmente escritos usando expressões regulares.
Padrões de árvores podem ser usados em linguagens de programação como uma ferramenta geral para processar dados baseado em sua estrutura. Algumas linguagens de programação funcionais como Haskell, ML e Mathematica possuem uma sintaxe especial para expressar padrões de árvore e uma construção na linguagem para execução condicional. Por questões de simplicidade e eficiência, tais padrões de árvore carecem algumas das funcionalidades disponíveis em expressões regulares.
Padrões primitivos
O padrão mais simples em um casamento de padrões é um valor explícito (literal) ou uma variável. Por exemplo, considerando uma simples definição de função em Haskell:
f 0 = 1
Aqui, o parâmetro 0
da função f
é um padrão literal. Sempre que a função for invocada com o valor 0
como argumento, o retorno será 1
. com qualquer outro valor, o casamento (e a função) irá falhar. Pode-se continuar a definição estendendo para argumentos mais genéricos:
f n = n * f (n-1)
Aqui, o argumento n
é um padrão de variável, que irá casar com qualquer argumento na invocação da função, assumindo uma referência do valor. O padrão especial _
também é usado para casar padrões, mas ele não assume a referência do valor, simplesmente ignora.
Padrões de árvore
Padrões mais complexos podem ser construídos a partir de primitivos, geralmente da mesma forma que os valores são construídos ao combinar outros valores. A diferença é que o padrão não é construído em um único valor, mas sim um grupo de valores. Um padrão de árvore descreve uma parte de uma árvore ao começar com um nó e especificando alguns galhos. Em Haskell, a seguinte linha define um tipo de dado algébrico Color
que possui um construtor ColorConstructor
que associa um inteiro e uma cadeia de caracteres.
data Color = ColorConstructor Integer String
O construtor é um nó em uma árvore, o inteiro e a cadeia de caracteres são folhas em galhos. Quando quer-se escrever funções para fazer de Color
um tipo de dado abstrato, quer-se escrever funções para criar uma interface com o tipo de dado, para extrair alguma informação do tipo de dado; no caso, ou o valor inteiro ou a cadeia de caracteres. Logo, para uma função retornar o valor inteiro de Color
, o seguinte padrão de árvore é aplicado:
integerPart (ColorConstructor theInteger _) = theInteger
Ou para a cadeia de caracteres:
stringPart (ColorConstructor _ theString) = theString
Relacionamento com cadeias de caracteres
O uso mais comum de casamento de padrões envolve cadeias de caracteres. Em várias linguagens de programação, uma sintaxe particular de cadeias de caracteres é usada pra representar expressões regulares, que são padrões para descrever cadeias de caracteres.
Em linguagens funcionais de modo geral, cadeias de caracteres são representadas como listas de caracteres. De forma funcional, elas são definidas como uma lista vazia, ou um elemento anexado a uma lista existente. Em Haskell:
[] -- uma lista vazia x:xs -- um elemento x anexado em uma lista xs
A estrutura de uma lista é então elemento:resto_da_lista
. No casamento de padrões é assegurado que certo pedaço de dado é igual a certo padrão. Por exemplo, na seguinte função:
primeiro_elemento (elemento:lista) = elemento
é assegurado que o primeiro elemento do argumento de primeiro_elemento
é chamado elemento, e que é isso que a função retorna. Sabe-se que é o primeiro elemento pois é assim que as listas são definidas (um elemento anexado a uma lista). Uma lista vazia não irá casar com o padrão, pois não possui primeiro elemento. Como não existe uso para o resto da lista, então pode-se omití-lo do código, como em:
primeiro_elemento (elemento:_) = elemento