Os mapas em Elixir são a estrutura de dados para guardar informação em pares chave-valor. Noutras linguagens, também podem ser conhecidos como arrays associativos (PHP), hashes (Perl 5, Raku) ou dicionários (Python).
As chaves e os valores podem ser de qualquer tipo de dados, mas se a chave for um átomo podemos usar uma sintaxe abreviada. Os mapas não garantem a ordem das suas entradas quando são acedidos ou devolvidos.
Um mapa vazio declara-se simplesmente com %{}. Se quisermos adicionar itens a um mapa literal, podemos usar duas formas:
# If the key is an atom:
%{atom_key: 1}
# If the key is a different type:
%{1 => :atom_value}
# You can even mix these if the atom form comes second:
%{"first_form" => :a, atom_form: :b}
Embora não exista um formato canónico, escolhe uma forma consistente de representar os pares chave-valor literais.
O Elixir disponibiliza muitas funções para trabalhar com mapas no módulo Map. Algumas funções do módulo Map exigem que lhes seja passada uma função anónima para ajudar na transformação do mapa.
Em Elixir, podemos definir atributos de módulo que podem ser usados como constantes nas nossas funções.
defmodule Example do
# Defines the attribute as the value 1
@constant_number 1
def example_value() do
# Returns the value 1
@constant_number
end
end
Quando são usados para definir constantes de módulo, os atributos podem ser qualquer expressão que possa ser avaliada em tempo de compilação. Depois da compilação, os atributos de módulo já não estão acessíveis, uma vez que são expandidos durante a compilação, à semelhança das macros definidas em linguagens como C.
Neste exercício, vais implementar uma forma de acompanhar as pontuações máximas do jogo mais popular do salão de jogos da tua zona.
Para criar um novo mapa de pontuações máximas, define a função HighScore.new/0, que não recebe argumentos e devolve um mapa de pontuações máximas novo e vazio.
HighScore.new()
# => %{}
Para adicionar um jogador ao mapa de pontuações máximas, define HighScore.add_player/3, uma função que recebe 3 argumentos:
Guarda a pontuação inicial predefinida num atributo de módulo. Vais precisar dela outra vez.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 0, "José Valim"=> 486_373}
Para remover um jogador do mapa de pontuações máximas, define HighScore.remove_player/2, que recebe 2 argumentos:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas")
# => %{"Dave Thomas" => 0}
score_map = HighScore.remove_player(score_map, "Dave Thomas")
# => %{}
Para reiniciar a pontuação de um jogador, define HighScore.reset_score/2, que recebe 2 argumentos:
A função também deve funcionar se o jogador não tiver pontuação.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.reset_score(score_map, "José Valim")
# => %{"José Valim"=> 0}
Para atualizar a pontuação de um jogador somando à pontuação anterior, define HighScore.update_score/3, que recebe 3 argumentos:
A função também deve funcionar se o jogador não tiver uma pontuação anterior; assume que a pontuação anterior é 0.
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"José Valim"=> 486_373}
score_map = HighScore.update_score(score_map, "José Valim", 5)
# => %{"José Valim"=> 486_378}
Para obteres uma lista de jogadores, define HighScore.get_players/1, que recebe 1 argumento:
score_map = HighScore.new()
# => %{}
score_map = HighScore.add_player(score_map, "Dave Thomas", 2_374)
# => %{"Dave Thomas" => 2_374}
score_map = HighScore.add_player(score_map, "José Valim", 486_373)
# => %{"Dave Thomas" => 2_374, "José Valim"=> 486_373}
HighScore.get_players(score_map)
# => ["Dave Thomas", "José Valim"]
Inscreve-te no Exercism para aprenderes e dominares Elixir com 58 conceitos168 exercícios, e mentoria humana real, tudo grátis.