Il pattern matching permette di scrivere codice con diramazioni espressive e la destrutturazione consente un'elegante associazione di valori alle variabili.
Il pattern matching può associare valori a variabili, oppure scartarli con il carattere jolly _, con l'uso dell'istruzione 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!"
La destrutturazione può associare valori nei binding let, negli argomenti di una funzione e, naturalmente, nelle espressioni case, ogni volta che per i dati è possibile una sola forma.
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
La destrutturazione può essere usata anche con i record, oppure con la parola chiave 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
Fai parte dell'helpdesk IT e vuoi rendere il sistema di ticketing più efficiente e fornire statistiche al tuo manager.
Un ticket ha uno stato (new, in progress...), un creatore (identificato da un nome utente e da un ID dipendente), può essere assegnato a un dipendente IT e contiene una cronologia di commenti.
Ecco quattro attività che miglioreranno l'attuale sistema di ticketing.
I commenti vuoti ingombrano l'interfaccia e non portano alcuna informazione: vuoi eliminarli.
Definisci una funzione ausiliaria emptyComment che prende una coppia utente/commento e restituisce True per i commenti vuoti.
Usa la destrutturazione per estrarre l'utente e il commento direttamente nell'argomento della funzione. Ignora l'utente, dato che quell'informazione non ti serve.
emptyComment ( User "Alice", "" )
-- => True
Il tuo manager vuole avere statistiche sul coinvolgimento degli utenti nel processo di gestione dei ticket. Ti chiede di verificare quanti commenti sono stati aggiunti dal creatore del ticket.
Definisci numberOfCreatorComments, che prende un ticket e restituisce il numero di commenti aggiunti dal creatore del ticket.
Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket, insieme ai campi del record che ti servono.
Poi destruttura createdBy in un binding let, così da poter contare i commenti rilevanti.
Usa le funzioni di List per fare il conteggio e usa la destrutturazione nell'argomento di una funzione anonima per separare la coppia utente/commento.
numberOfCreatorComments
numberOfCreatorComments
(Ticket
{ status = Closed
, createdBy = ( User "Chiaki", 1 )
, assignedTo = Nothing
, comments = [ ( User "Chiaki", "Never mind, fixed it." ) ]
}
)
-- => 1
Alcuni ticket devono essere escalati ad Alice, Bob o Charlie del Dev Team. È importante tenerli d'occhio per assicurarsi che facciano progressi.
Definisci una funzione ausiliaria assignedToDevTeam che verifica se un ticket è assegnato a uno dei membri del Dev Team.
Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket e anche il campo che ti serve.
Poi usa un'unica istruzione case per verificare se il ticket è assegnato ad Alice, Bob o Charlie, usando il pattern matching ricorsivo per estrarre i loro nomi utente e il pattern matching letterale per riconoscerli.
assignedToDevTeam
(Ticket
{ status = InProgress
, createdBy = ( User "Bill", 2 )
, assignedTo = Just (User "Alice")
, comments = [ ( User "Bill", "What's an 'undefined'?" ) ]
}
)
-- => True
A volte diversi ticket devono essere riassegnati ad altri dipendenti IT.
Definisci una funzione assignTicketTo che ti aiuti a farlo. La funzione riceve due argomenti: un utente a cui assegnare il ticket e un ticket.
Se lo stato del ticket è New, assegnalo al nuovo utente e cambia lo stato in InProgress.
Per gli altri stati, riassegna semplicemente il ticket ai nuovi utenti, tranne per i ticket con stato Archived, che non vanno modificati affatto.
Usa la destrutturazione nell'argomento della funzione per estrarre il record dal tipo Ticket e anche il campo che ti serve, e usa anche la parola chiave as per catturare l'intero record così com'è.
Usa un'unica istruzione case per fare pattern matching sullo stato e restituire il ticket appropriato, creato modificando il record originale che hai catturato con la parola chiave 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!!" ) ]
-- }
Iscriviti a Exercism per imparare e padroneggiare Elm con 28 concetti110 esercizi e il mentoring di persone reali, tutto gratis.