Skip to content

Instantly share code, notes, and snippets.

@adolfont
Created March 21, 2022 19:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adolfont/72b6ece62c644c890976a137c62be714 to your computer and use it in GitHub Desktop.
Save adolfont/72b6ece62c644c890976a137c62be714 to your computer and use it in GitHub Desktop.
Structs em Elixir (um Livebook)

Estruturas (Structs) em Elixir

Pré-requisitos

  • Mapas
  • Listas de palavras-chave
  • Tipos de Dados

Mapas (Maps)

  • Você pode definir um mapa com %{ e terminando com }.

  • Os pares chave => valor são separados por vírgulas.

  • Se todas as chaves forem átomos, você pode escrever como abaixo (observe a posição do :).

# map = %{:a => 1, :b => 2}
map = %{a: 1, b: 2}
map[:a]
map2 = %{map | a: 3}
map
map2
map2[:a]

Structs

"Structs são extensões construídas em cima de mapas que fornecem verificações em tempo de compilação e valores padrão."

Exemplo de Struct Pessoa.

defmodule Pessoa do
  defstruct nome: "Emília", idade: 55
end

nome: "Emília", idade: 55 é uma lista de palavras-chave (keyword list).

%Pessoa{}
%Pessoa{nome: "João"}
%Pessoa{peso: 100}

Atribundo uma Struct a uma variável

joao = %Pessoa{nome: "João"}

Acessando um campo de uma struct

joao.nome

"Modificando" uma struct com |

maria = %{joao | nome: "Maria"}
maria = %{joao | peso: 55}

Uso de Structs no Casamento de Padrões

%Pessoa{nome: nome_de_joao} = joao
nome_de_joao

Structs são bare maps (mapas simples)

is_map(joao)

O campo especial struct:

joao.__struct__

Por que são mapas simples?

"nenhum dos protocolos implementados para mapas está disponível para structs. Por exemplo, você não pode enumerar nem acessar uma estrutura"

joao = %Pessoa{}
joao[:nome]
Enum.each(joao, fn {_field, value} -> IO.puts(value) end)

No entanto, como as structs são apenas mapas, elas funcionam com as funções do módulo Map.

jane = Map.put(%Pessoa{}, :nome, "Jane")
Map.merge(jane, %Pessoa{nome: "John"})
Map.keys(jane)

Valores Padrão (default)

Se você não especificar um valor para uma chave, o valor nil será atribuído.

defmodule Produto do
  defstruct [:nome]
end
%Produto{}

Você pode combinar valores padrão explícitos com o valor nil implícito

defmodule Usuario do
  defstruct [:email, nome: "João", idade: 27]
end
%Usuario{}

Mas na ordem inversa dá erro!

defmodule Usuario do
  defstruct [nome: "João", idade: 27, :email]
end

Definindo chaves obrigatórias

defmodule Car do
  @enforce_keys [:make]
  defstruct [:model, :make]
end
%Car{}
%Car{make: "Gurgel"}
%Car{make: "Gurgel", model: "BR-800"}

Construtores, Redutores e Conversores

Bruce Tate diz que basicamente existem 3 tipos de função:

  • construtoras
  • redutoras
  • conversoras
defmodule JogoDaVelha do
  defstruct [:tabuleiro, :jogadores, :jogador_da_vez, :vencedor]

  def new(jogador1, jogador2) do
    %__MODULE__{
      tabuleiro: ["", "", "", "", "", "", "", "", ""],
      jogadores: [jogador1, jogador2],
      jogador_da_vez: jogador1
    }
  end

  def joga(jogo, simbolo, x, y) do
    novo_tabuleiro = List.insert_at(jogo.tabuleiro, x - 1 + (y - 1) * 3, simbolo)
    [novo_jogador_da_vez] = jogo.jogadores -- [jogo.jogador_da_vez]
    %__MODULE__{jogo | tabuleiro: novo_tabuleiro, jogador_da_vez: novo_jogador_da_vez}
  end

  def jogador_da_vez(jogo) do
    jogo.jogador_da_vez
  end
end
um_jogo = JogoDaVelha.new("Maria", "João")
JogoDaVelha.joga(um_jogo, "X", 1, 1)
JogoDaVelha.jogador_da_vez(um_jogo)
JogoDaVelha.joga(um_jogo, "O", 2, 2)
um_jogo = JogoDaVelha.joga(um_jogo, "X", 1, 1)
um_jogo = JogoDaVelha.joga(um_jogo, "O", 2, 2)
JogoDaVelha.new("Pedro", "Paula")
|> JogoDaVelha.joga("X", 1, 1)
|> JogoDaVelha.joga("o", 2, 1)
|> JogoDaVelha.joga("X", 1, 2)
|> JogoDaVelha.joga("o", 2, 3)
JogoDaVelha.new("Pedro", "Paula")
|> JogoDaVelha.joga("X", 1, 1)
|> JogoDaVelha.joga("o", 2, 1)
|> JogoDaVelha.joga("X", 1, 2)
|> JogoDaVelha.joga("o", 2, 3)
|> JogoDaVelha.jogador_da_vez()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment