Elm Language
Raccolta di dati: tuple, registri e dizionari
Ricerca…
Le tuple
Le tuple sono elenchi ordinati di valori di qualsiasi tipo.
(True, "Hello!", 42)
È impossibile modificare la struttura di una Tupla o aggiornare il valore.
Le tuple in Elm sono considerate un tipo di dati primitivi, il che significa che non è necessario importare alcun modulo per utilizzare Tuples.
Accesso ai valori
Il modulo di base ha due funzioni di supporto per l'accesso ai valori di una tupla con una lunghezza di due ( a, b ) senza utilizzare la corrispondenza del modello:
fst (True, "Hello!") -- True
snd (True, "Hello!") -- "Hello!"
I valori di accesso delle tuple con una lunghezza maggiore vengono eseguiti attraverso la corrispondenza dei modelli.
Pattern matching
Le tuple sono estremamente utili in combinazione con la corrispondenza del modello:
toggleFlag: (Sting, Bool) -> (Sting, Bool)
toggleFlag (name, flag) =
(name, not flag)
Note su Tuples
Le tuple contengono meno di 7 valori di tipo di dati comparable
dizionari
I dizionari sono implementati in una libreria principale di Dict .
Un dizionario che associa chiavi univoche ai valori. Le chiavi possono essere di qualsiasi tipo comparabile. Ciò include Int, Float, Time, Char, String e tuple o liste di tipi comparabili.
Le operazioni di inserimento, rimozione e interrogazione richiedono tutto il tempo O (log n).
A differenza di Tuples e Records, i dizionari possono cambiare la loro struttura, in altre parole è possibile aggiungere e rimuovere le chiavi.
È possibile aggiornare un valore con una chiave.
È anche possibile accedere o aggiornare un valore utilizzando i tasti dinamici.
Accesso ai valori
È possibile recuperare un valore da un dizionario utilizzando una funzione Dict.get .
Digitare la definizione di Dict.get :
get : comparable -> Dict comparable v -> Maybe v
Verrà sempre restituito Maybe v , perché è possibile provare a ottenere un valore tramite una chiave inesistente.
import Dict
initialUsers =
Dict.fromList [ (1, "John"), (2, "Brad") ]
getUserName id =
initialUsers
|> Dict.get id
|> Maybe.withDefault "Anonymous"
getUserName 2 -- "Brad"
getUserName 0 -- "Anonymous"
Aggiornamento dei valori
L'operazione di aggiornamento su un dizionario viene eseguita utilizzando Maybe.map , poiché la chiave richiesta potrebbe essere assente.
import Dict
initialUsers =
Dict.fromList [ (1, "John"), (2, "Brad") ]
updatedUsers =
Dict.update 1 (Maybe.map (\name -> name ++ " Johnson")) initialUsers
Maybe.withDefault "No user" (Dict.get 1 updatedUsers) -- "John Johnson"
Records
Record è un insieme di coppie chiave-valore.
greeter =
{ isMorning: True
, greeting: "Good morning!"
}
È impossibile accedere a un valore con una chiave inesistente.
È impossibile modificare dinamicamente la struttura di Record.
I record ti consentono solo di aggiornare i valori con chiavi costanti.
Accesso ai valori
Non è possibile accedere ai valori utilizzando una chiave dinamica per evitare possibili errori di runtime:
isMorningKeyName =
"isMorning "
greeter[isMorningKeyName] -- Compiler error
greeter.isMorning -- True
La sintassi alternativa per l'accesso al valore consente di estrarre il valore, mentre si esegue il piping attraverso il record:
greeter
|> .greeting
|> (++) " Have a nice day!" -- "Good morning! Have a nice day!"
Estendere i tipi
A volte vorresti la firma di un parametro per vincolare i tipi di record che passi alle funzioni. L'estensione dei tipi di record rende superfluo l'idea di supertipi. L'esempio seguente mostra come questo concetto può essere implementato:
type alias Person =
{ name : String
}
type alias Animal =
{ name : String
}
peter : Person
peter =
{ name = "Peter" }
dog : Animal
dog =
{ name = "Dog" }
getName : { a | name : String } -> String
getName livingThing =
livingThing.name
bothNames : String
bothNames =
getName peter ++ " " ++ getName dog
Potremmo addirittura estendere ulteriormente i record e fare qualcosa come:
type alias Named a = { a | name : String }
type alias Totalled a = { a | total : Int }
totallyNamed : Named ( Totalled { age : Int })
totallyNamed =
{ name = "Peter Pan"
, total = 1337
, age = 14
}
Ora abbiamo modi per passare questi tipi parziali in giro nelle funzioni:
changeName : Named a -> String -> Named a
changeName a newName =
{ a | name = newName }
cptHook = changeName totallyNamed "Cpt. Hook" |> Debug.log "who?"
Aggiornamento dei valori
Elm ha una sintassi speciale per gli aggiornamenti del record:
model =
{ id: 1
, score: 0
, name: "John Doe"
}
update model =
{ model
| score = model.score + 100
| name = "John Johnson"
}