O pattern matching permite escrever código com ramificações expressivas, e a desestruturação traz uma forma elegante de vincular valores a variáveis.
O pattern matching pode vincular valores a variáveis ou descartá-los com o curinga _, usando a instrução case.
type Entity = Alien | Stranger (Maybe String) | Friend { name: String }
hello : Entity -> String
hello entity =
case entity of
-- Custom type variant
Alien -> "Hello, you are not from around here are you?"
-- Binding to a litteral value nested in Stranger
Stranger (Just nametag) -> "Hello, erm... " ++ nametag ++ "."
-- Discarding Friend's data
Friend _ -> "Hi!"
-- All other cases
_ -> "Hello stranger!"
A desestruturação pode vincular valores em ligações let, em argumentos de função e, claro, em expressões case, sempre que houver apenas um formato possível para os dados.
pairSum : ( Int, Int ) -> Int
pairSum pair =
-- Destructuring of a pair in a 'let' binding
let ( x, y ) = pair
in x + y
-- Destructuring in the function argument
pairSum : ( Int, Int ) -> Int
pairSum ( x, y ) = x + y
-- Custom type containing a single variant
type Container = Box String
-- Destructuring in the function argument
unbox : Container -> String
unbox (Box str) = str
-- Destructuring combined with pattern matching
unboxMaybe : Maybe Container -> Maybe String
unboxMaybe maybeContainer =
case maybeContainer of
Nothing -> Nothing
Just (Box "42") -> Just "The answer to the universe!"
Just (Box str) -> Just str
A desestruturação também pode ser usada com registros ou com a palavra-chave as.
type alias Circle =
{ radius : Float
, center : ( Float, Float )
}
perimeter : Circle -> Float
perimeter { radius } =
2 * pi * radius
left : Circle -> Float
left { radius, center } =
-- the pair center cannot be pattern matched directly in the function argument
-- so we do it in a 'let' statement
let ( x, _ ) = center
in x - radius
-- using the 'as' keyword to bind both the fields and the whole record
smaller : Float -> Circle -> Circle
smaller reduction ({ radius } as circle) =
if reduction < radius then
{ circle | radius = radius - reduction }
else
circle
Você faz parte do helpdesk de TI e quer melhorar o sistema de tickets para que ele seja mais eficiente e para fornecer estatísticas à sua gerente.
Um ticket tem um status (new, in progress...), uma pessoa criadora (identificada por um nome de usuário e um ID de funcionário), pode ser atribuído a um funcionário de TI e contém um histórico de comentários.
Aqui estão quatro tarefas que vão melhorar seu sistema de tickets atual.
Comentários vazios poluem a interface e não trazem nenhuma informação, então você quer filtrá-los.
Defina uma função auxiliar emptyComment que recebe um par usuário/comentário e retorna True para comentários vazios.
Use desestruturação para extrair o usuário e o comentário diretamente no argumento da função. Ignore o usuário, já que você não precisa dessa informação.
emptyComment ( User "Alice", "" )
-- => True
Sua gerente quer ter estatísticas sobre o envolvimento das pessoas no processo de tickets. Ela pede que você verifique quantos comentários foram adicionados por quem criou o ticket.
Defina numberOfCreatorComments, que recebe um ticket e retorna o número de comentários adicionados por quem criou o ticket.
Use desestruturação no argumento da função para extrair o record do tipo Ticket, ao mesmo tempo que os campos de que você precisa do record.
Depois, desestruture o createdBy em uma ligação let para poder contar os comentários relevantes.
Use funções do módulo List para fazer a contagem e use desestruturação no argumento de uma função anônima para separar o par usuário/comentário.
numberOfCreatorComments
numberOfCreatorComments
(Ticket
{ status = Closed
, createdBy = ( User "Chiaki", 1 )
, assignedTo = Nothing
, comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
}
)
-- => 1
Alguns tickets precisam ser escalados para Alice, Bob ou Charlie, do Time de Desenvolvimento. É importante ficar de olho neles para garantir que estejam avançando.
Defina uma função auxiliar assignedToDevTeam que verifica se um ticket está atribuído a um dos membros do Time de Desenvolvimento.
Use desestruturação no argumento da função para extrair o record do tipo Ticket, bem como o campo de que você precisa.
Depois, use um único case para verificar se o ticket está atribuído a Alice, Bob ou Charlie, usando pattern matching recursivo para extrair os nomes de usuário e pattern matching literal para compará-los.
assignedToDevTeam
(Ticket
{ status = InProgress
, createdBy = ( User "Bill", 2 )
, assignedTo = Just (User "Alice")
, comments = [ ( User "Bill", "What's an 'undefined'?" ) ]
}
)
-- => True
Às vezes, vários tickets precisam ser reatribuídos a outros funcionários de TI.
Defina uma função assignTicketTo para ajudar você a fazer isso. A função recebe dois argumentos: um usuário para quem atribuir o ticket e um ticket.
Se o status do ticket for New, atribua-o ao novo usuário e mude o status para InProgress.
Para os outros status, apenas reatribua o ticket ao novo usuário, exceto os tickets com o status Archived, que não devem ser modificados de forma alguma.
Use desestruturação no argumento da função para extrair o record do tipo Ticket, bem como o campo de que você precisa, e use também a palavra-chave as para capturar o record inteiro como ele está.
Use um único case para fazer pattern matching do status e retornar o ticket apropriado, criado a partir da modificação do record original que você capturou com a palavra-chave as.
assignTicketTo (User "Danny")
(Ticket
{ status = New
, createdBy = ( User "Jesse", 3 )
, assignedTo = Just (User "Alice")
, comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
}
)
-- => Ticket
-- { status = InProgress
-- , createdBy = ( User "Jesse", 3 )
-- , assignedTo = Just (User "Danny")
-- , comments = [ ( User "Jesse", "I've been waiting for 6 months!!" ) ]
-- }
Crie sua conta no Exercism para aprender e dominar Elm com 28 conceitos110 exercícios e mentoria humana de verdade, tudo de graça.