Listas

Vamos diretamente a um exemplo prƔtico.

Foi decidido que precisamos de uma listagem de candidatos que foram aprovados no vestibular. Com ela, podemos realizar a operação de aprovar estudantes (adicionando o estudando a lista) e também desaprovar estudantes (removendo o estudando da lista.) Com esse levantamento temos três pontos a lidar:

  1. Ter uma lista de estudando aprovados

  2. Conseguir adicionar estudantes nessa lista

  3. Remover estudantes da lista.

Vamos ao primeiro teste:

test/students_test.exs
defmodule StudentsTest do
  use ExUnit.Case

  test "adding a new user on approved list" do
    current_list = ["Paulo", "João"]
    students = ["Iago"]
  
    assert Students.add_to_approved_list(current_list, students) == ["Paulo", "João", "Iago"]
  end
end

Criamos uma variÔvel chamada current_list que vai conter nossa lista inicião de aprovados. Depois criamos uma variÔvel chamada students, que é uma lista de usuÔrio. Temo então na linha 8 a chamada Students.add_to_approved_list/2. Ele é nossa função que irÔ adicionar uma lista de usuÔrio a uma lista ja existente. O retorno dessa função serÔ uma nova lista com os estudantes adicionados. Com isso conseguimos criar nossa assertion dizendo que deve ser igual a nova lista.

Vamos rodar esse teste:

mix test test/students_test.exs
warning: Students.add_to_approved_list/2 is undefined (module Students is not available or is yet to be defined)
  test/students_test.exs:9: StudentsTest."test List of students approved adding a new user on approved list"/1



  1) test List of students approved adding a new user on approved list (StudentsTest)
     test/students_test.exs:5
     ** (UndefinedFunctionError) function Students.add_to_approved_list/2 is undefined (module Students is not available)
     code: assert Students.add_to_approved_list(current_list, students) == ["Paulo", "João", "Iago"]
     stacktrace:
       Students.add_to_approved_list(["Paulo", "João"], ["Iago"])
       test/students_test.exs:9: (test)


Finished in 0.02 seconds (0.00s async, 0.02s sync)
1 test, 1 failure

Com somente o teste criado, recebemos a mensagem de que a função Students.add_to_approved_list/2 não existe. Próximo passo é cria-la.

Criamos o módulo Students e dentro a função add_to_approved/2. Como jÔ tinhamos falado, retornaremos uma lista.

No teste falhou novamente. Agora acusando que a nossa chamada esta retornando um [] e esperavamos ["Paulo", "João", "Iago"]. Claro, não retornamos a lista enviada. Vamos fazer isso para seguir com a implementação. Vamos alterar students.ex. Ao chamar a função, o primeiro argumento que passamos é a lista atual e o segundo argumento é a lista de estudantes a serem adicionados. Vamos primeiro retornar apenas a primeira lista.

Vamos executar novamente o teste:

Estamos chegando perto! Agora acusou apenas que não temos o estudante Iago em nossa lista. Isso porque o primeiro parâmetro de nossa função esta passando apenas uma lista sem Iago. JÔ o segundo parâmetro estÔ passando uma lista e nessa lista possuímos o nome Iago. Essa segunda lista são os estudantes que queremos adicionar na lista de estudantes que passaram. Precisamos unir essas duas listas. Para isso, podemos usar o operador ++/2 do elixir.

Alteramos o nome do segundo parâmetro de underline (_) para new_students para podermos usar em nossa função. Tendo os novos estudantes em mãos, adicionamos o operador ++/2 ao lado de current_list e colocamos ao final a lista que queremos fazer a união, no nosso casso new_students. Vamos rodar novamente nosso teste:

Agora temos uma nova lista retornada pela função add_to_approved_list/2 contendo a união de duas listas. Com isso temos dois dos problemas resolvidos.

  1. Ter uma lista de estudando aprovados

  2. Conseguir adicionar estudantes nessa lista

  3. Remover estudantes da lista.

Precisamos agora remover os estudantes que foram desaprovados. Vamos ao teste:

Agora vamos fazer o oposto do que fizemos anteriormente. Queremos remove elementos de uma lista. Choque com a informação, mas o oposot de ++/2 é --/2. Acredito que nem precisaria fazer essa implementação. Mas vou fazer para deixar aqui completo. Vamos a implementação:

Fizemos a mesma implementação, porem, utilizamos o operador --/2. Pode rodar os testes e ser feliz.

E nosso escopo esta fechado:

  1. Ter uma lista de estudando aprovados

  2. Conseguir adicionar estudantes nessa lista

  3. Remover estudantes da lista.

Vamos adicionar mais uma tarefa. Queremos saber a quantidade de estudantes que passaram no vestibular. Vamos ao teste:

Não possuímos a função. Logo, temos um erro. Vamos resolver isso criando ela:

Quando lidamos com totais, sempre esperamos um integer, para manter consistente retornamos dessa função apenas 2 para nosso teste passar. Vamos ver o que o teste nos diz.

Vamos adicionar uma outra assertion para nosso teste, com uma quantidade diferente de itens na lista. Isso garante que ela funciona bem.

Vamos rodar o teste com a nova assertion:

Algo deu errado. A quantidade esperada na segunda assertion é diferente de dois, que colocamos diretamente na implementação. Precisamos de algo mais dinâmico. Por sorte (uma brincadeira), temos a função nativa length/1, onde espera uma lista e nos retorna o total de elementos dessa lista. Vamos lÔ:

Simples não? Vamos rodar novamente os testes:

Muito bem! VocĆŖ estĆ” indo bem. Mas vamos pensar em alguma outra coisa. VocĆŖ Ć© um desses estudantes e quer saber se vocĆŖ passou. Como podemos fazer isso? Vamos ao teste:

Criamos um teste que chama uma função was_approved?/2, onde o primeiro argumento é a lista de aprovados e o segundo argumento é uma string com o nome do estudante que queremos saber se foi aprovado.

O nome da função possui uma interrogação, dando a entender que queremos uma resposta de verdadeiro ou falso, isso é uma convenção que também adotamos no Elixir, você pode ver mais sobre isso no capítulo de conveções.

Vamos resolver esse teste:

Criamos a função no módulo Students e retornamos uma valor estÔtico true. Assim nosso teste passarÔ.

Vamos adicionar agora um caso de que o estudante que procuramos não passou.

Para isso, apenas adicionamos a linha 9 a nosso teste, procuranod por um estudante chamado Rui que não existe em nossa lista. Vamos rodar o teste:

A resposta para se Rui passou nos exames é true, mas na verdade esperavamos por false. Isso devido ao retorno de nossa função ser estÔtico. Precisamos de algo mais dinâmico para nos salvar agora.

Temos um operador em elixir chamado in/2. Ele verificar se existe um elemento em nossa lista. A leitura desse operador fica muito interessante: 1 in [1,2,3]. Vamos aplica-lo em nosso código:

Adicionamos o operador in na linha 4. Também removemos o underline (_) dos dois parâmetros da função, para podermos utiliza-las. vamos rodar o teste:

Perfeito! As funções de lista para estudantes estão tomando forma e ficando claras em seus objetivos. Precisamos so de mais duas funcionalidades. Me ligaram ainda pouco pedindo que adicionacemos a possibilidade de saber o primeiro e ultimo estudante de nossa lista. Falei que não seria um problema, que você jÔ estava dominando a listagem. Vamos escopar isso

Desafio final

  1. Obter primeiro estudante da lista

  2. Obter Ćŗltimo estudante da lista

Vamos comeƧar do primeiro. Criaremos seu teste:

Vamos implementar a função first/1, onde recebe a lista que queremos obter o primeiro. Elixir tem um módulo de List que nos ajuda a listar com algumas coisas relacionadas a lista. Para resolver nosso problema aqui, temos a função List.first/1, onde o argumento passado é a lista e a resposta é o elemento da lista, exatamente o que precisamos.

Simples não? Agora precisamos lidar com o útilmo da lista. Te desafio a pensar qual função usaremos para resolver isso. Enquanto pensa, vamos para o teste:

Vamos implementar a função que nĆ£o existe. Pensou na função que usariamos para ser oposto a List.first/1? Ɖ isso mesmo, List.last/1. Vamos implementar nosso código.

Conclusão

Ɠtimo! Agora temos muitas ferramentas para lidar com listas. Listas sĆ£o simples, mas podemos tirar grandes vantagens dela ao dia-a-dia de trabalho. Ela sempre estarĆ” presente e muitas vezes podem se tornar bem complexa. O domĆ­nio de operaƧƵes e funƧƵes de auxĆ­lio ira te ajudar na jornada.

Você deve ter ficado com a impressão de faltar algo. Sim, temos um buraco aqui. Que tipo de aprendizado de lista não ensina como a percorremos. Por isso o próximo capítulo falarÔ sobre estruturas de repetição.

Last updated

Was this helpful?