<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mateus Martins</title>
    <description>The latest articles on DEV Community by Mateus Martins (@mateusbmo).</description>
    <link>https://dev.to/mateusbmo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F809080%2Fecd0abb5-cd59-452b-9187-bb6dc1b9f616.webp</url>
      <title>DEV Community: Mateus Martins</title>
      <link>https://dev.to/mateusbmo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mateusbmo"/>
    <language>en</language>
    <item>
      <title>Aprendizado Elixir - módulo 2</title>
      <dc:creator>Mateus Martins</dc:creator>
      <pubDate>Mon, 27 Jun 2022 13:00:57 +0000</pubDate>
      <link>https://dev.to/mateusbmo/aprendizado-elixir-modulo-2-1601</link>
      <guid>https://dev.to/mateusbmo/aprendizado-elixir-modulo-2-1601</guid>
      <description>&lt;p&gt;Nesse módulo, criaremos um projeto chamado reports_generator, então já vamos cria-lo no terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix new reports_generator


* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/reports_generator.ex
* creating test
* creating test/test_helper.exs
* creating test/reports_generator_test.exs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Desta vez, já iremos utilizar uma lib externa, então iremos aprender a instalar uma lib externa. &lt;/p&gt;

&lt;p&gt;A lib em questão será o &lt;code&gt;CREDO&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para instala-lo, basta pesquisar por “elixir credo” no google, ou acessar o &lt;a href="https://github.com/rrrene/credo" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mas afinal, o que é o credo?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O credo é um analisador sintático de código. Ele Irá nos ajudar a manter boas práticas de escrita do nosso código, além do mix format que irá nos ajudar a formatar o código. &lt;/p&gt;

&lt;p&gt;Para instalar o credo, basta acessar a pasta “mix .exs” dentro do projeto e ir até a função “defp deps do”.&lt;br&gt;
Lá iremos inserir: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;{:credo, "~&amp;gt; 1.6", only: [:dev, :test], runtime: false}&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No terminal, utilizamos o comando “mix deps.get” para instalar as libs.&lt;/p&gt;

&lt;p&gt;Agora, uma vez que o credo está instalado, rodaremos o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix credo gen.config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este comando irá gerar um arquivo de configuração  do credo que podemos configura-lo para decidirmos o que queremos que ele cheque ou não.&lt;/p&gt;

&lt;p&gt;Agora, se visualizarmos dentro do nosso código, veremos que foi criada uma pasta com o nome “.credo.exs":&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kiw04mh9jw2n71891g2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6kiw04mh9jw2n71891g2.png" alt=" " width="800" height="472"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para testarmos, vamos rodar o comando &lt;code&gt;mix credo&lt;/code&gt; no terminal&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2hmjucksx98re0se502.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2hmjucksx98re0se502.png" alt=" " width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como estamos em um projeto recém criado, ele não irá apresentar nenhuma issues. &lt;br&gt;
Porém, se entrarmos dentro da lib “reports_generator.ex” e apagarmos a doc e rodarmos novamente o comando mix credo, ele irá nos devolver a seguinte mensagem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3 mods/funs, found 1 code readability issue.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, ele nos diz que os módulos devem ter documentação. &lt;br&gt;
Como não iremos trabalhar com documentação, iremos a pasta credo.exs e adicionar “false” em um dos nossos checks:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{Credo.Check.Readability.ModuleDoc, false},&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Outra coisa que podemos fazer é observar que o credo vem como padrão um limite por linhas (nesse caso, 120)&lt;br&gt;
Para obtermos esse resultado no credo, precisamos rodar um comando mais severo do credo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; mix credo —strict  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o credo irá nos retornar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Line is too long (max is 120, was 164).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Existe uma extensão no vscode chamada Elixirlint que executa de forma dinâmica e executa os erros de forma ao vivo, sem precisarmos de rodar os checks o tempo todo. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pra darmos continuidade ao nosso projeto, utilizaremos um arquivo que irá conter todos os CSV`s que iremos precisar. &lt;/p&gt;

&lt;p&gt;Vamos alterar o nome da função para def build(filename) que irá receber o nome do arquivo que queremos abrir&lt;br&gt;
Para ler o arquivo, colocamos dentro da nossa função:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;File = File.read(“reports/#{filename})”)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agora, vamos rodar o &lt;code&gt;iex -S mix&lt;/code&gt; para  tentar abrir um arquivo do nosso projeto&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(1)&amp;gt; ReportsGenerator.build("report_test.csv")&lt;br&gt;
{:ok,&lt;br&gt;
 "1,pizza,48\r\n2,açaí,45\r\n3,hambúrguer,31\r\n4,esfirra,42\r\n5,hambúrguer,49\r\n6,esfirra,18\r\n7,pizza,27\r\n8,esfirra,25\r\n9,churrasco,24\r\n10,churrasco,36"}&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E obtemos um &lt;code&gt;:ok&lt;/code&gt;. &lt;br&gt;
Mas como podemos lidar melhor com o erro ao não encontrarmos um arquivo?&lt;br&gt;
Na prática, criamos o “corpo” do &lt;code&gt;case&lt;/code&gt; desta maneira:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nós tentamos dar match em alguma ocasião , ou seja,  se tivermos um “ok, result”, devolveremos result.&lt;br&gt;
Mas, se recebermos um “error, reason”, devolveremos um reason (o motivo de error)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsh3kg172eebahbpyuin.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsh3kg172eebahbpyuin.png" alt=" " width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agora, testamos no terminal as duas opções e ele irá nos retornar:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(4)&amp;gt; ReportsGenerator.build("report_test.csv")&lt;br&gt;
"1,pizza,48\r\n2,açaí,45\r\n3,hambúrguer,31\r\n4,esfirra,42\r\n5,hambúrguer,49\r\n6,esfirra,18\r\n7,pizza,27\r\n8,esfirra,25\r\n9,churrasco,24\r\n10,churrasco,36"&lt;br&gt;
iex(5)&amp;gt; ReportsGenerator.build("report_tawdest.csv")&lt;br&gt;
:enoent&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Uma outra forma, talvez mais elegante e mais aderente ao nosso exemplo quando entendermos o nosso módulo. &lt;/p&gt;

&lt;p&gt;Vamos iniciar o conhecimento em &lt;strong&gt;Pipe Operator&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vamos dar um exemplo na prática para entendermos o seu funcionamento. &lt;br&gt;
No terminal, vou criar uma String simples:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;iex(4)&amp;gt; string = " aaaaaaaaAaaaAa \n"&lt;br&gt;
" aaaaaaaaAaaaAa \n"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora, queremos gerar uma string sem o “/n” e sem esses “a” maiúsculos. &lt;br&gt;
Uma opção seria passar: String.trim(string) &lt;br&gt;
Assim, ele deletaria todos os espaços e o “/n”. &lt;br&gt;
Só que estamos em uma linguagem imutável, então teríamos que atribuir a nossa string novamente: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
String = String.trim(string)&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E só assim modificamos a nossa string de fato. &lt;br&gt;
Mas e se eu quiser deixa-la toda minúscula também?&lt;br&gt;
Então teríamos que de fato fazer outra atribuição: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(10)&amp;gt; string = " aaaaAaaaaaa \n" &lt;br&gt;
" aaaaAaaaaaa \n"&lt;br&gt;
iex(11)&amp;gt; String.trim(string)&lt;br&gt;
"aaaaAaaaaaa"&lt;br&gt;
iex(12)&amp;gt; string = String.trim(string)&lt;br&gt;
"aaaaAaaaaaa"&lt;br&gt;
iex(13)&amp;gt; string&lt;br&gt;
"aaaaAaaaaaa"&lt;br&gt;
iex(14)&amp;gt; string = String.downcase(string)&lt;br&gt;
"aaaaaaaaaaa"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pouco legível e muita concatenação. Atrapalharia inclusive a leitura do código por outros desenvolvedores. &lt;/p&gt;

&lt;p&gt;E onde o Pipe Operator entra? &lt;br&gt;
Vamos seguir o mesmo exemplo de cima:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(16)&amp;gt; " aaaaaaAAAAAAaaaa \n" |&amp;gt; String.trim() |&amp;gt; String.downcase()&lt;br&gt;
"aaaaaaaaaaaaaaaa"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Olha como fica legal, mais legível e extende bem menos o código. &lt;/p&gt;

&lt;p&gt;O Pipe Operator nada mais faz do que pegar o primeiro o resultado de qualquer operação antes dele e passar pra função seguinte como primeiro argumento, e o resultado da da primeira função ele passaria pra segunda, e assim adiante, e por isso não há nada dentro dos parênteses, pois está vindo como resultado do “|&amp;gt;(pipe).&lt;/p&gt;

&lt;p&gt;E como podemos aplicar isso dentro do nosso exemplo lá no projeto?&lt;/p&gt;

&lt;p&gt;Vamos lá no código pegar o nome do nosso arquivo “filename” e concatenar com a variável reports:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3t4urf91x2ti0mgnvwt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff3t4urf91x2ti0mgnvwt.png" alt=" " width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Estamos pegando essa string: "reports/#{filename}" e passando para a primeira função |&amp;gt;File.read() e o resultado da função file.read eu estou passando para a função |&amp;gt;handle_file&lt;/p&gt;

&lt;p&gt;Agora, vamos testar com um arquivo que existe: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(2)&amp;gt; ReportsGenerator.build("report_test.csv")&lt;br&gt;
"1,pizza,48\r\n2,açaí,45\r\n3,hambúrguer,31\r\n4,esfirra,42\r\n5,hambúrguer,49\r\n6,esfirra,18\r\n7,pizza,27\r\n8,esfirra,25\r\n9,churrasco,24\r\n10,churrasco,36"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E quando tentamos um arquivo não existente, obtemos: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(3)&amp;gt; ReportsGenerator.build("report_tesawdt.csv")&lt;br&gt;
"Error while opening file!"&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Assim, conseguimos trabalhar com Pipe Operator e pattern matching, controlando o fluxo da nossa execução, sem dependermos de if&amp;amp;else ou “complicando” o nosso código.&lt;/p&gt;

&lt;p&gt;Voltando ao nosso projeto, dentro temos um arquivo chamado “report_complete.csv” contendo 300 mil linhas.&lt;br&gt;
Será com esse arquivo que iremos inicialmente trabalhar.&lt;/p&gt;

&lt;p&gt;Em um cenário real, um arquivo contendo 1 milhão de linhas poderia ser muito pesado de ser carregado completamente na memória. &lt;br&gt;
Então,  a primeira coisa que iremos mudar é ao invés de utilizarmos “File.read()” nós iremos usar “File.stream!().&lt;/p&gt;

&lt;p&gt;Usaremos um IO.inspect() para debugar no terminal o resultado desta operação. O IO sempre irá imprimir no terminal aquilo que passamos para ele como parâmetro. &lt;/p&gt;

&lt;p&gt;Agora, faremos um recompile no terminal e iremos chamar novamente a função &lt;code&gt;ReportsGenerator.build("report_test.csv”)&lt;/code&gt;, e ele irá nos retornar: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;p&gt;%File.Stream{&lt;br&gt;
  line_or_bytes: :line,&lt;br&gt;
  modes: [:raw, :read_ahead, :binary],&lt;br&gt;
  path: "reports/report_test.csv",&lt;br&gt;
  raw: true&lt;br&gt;
}&lt;br&gt;
%File.Stream{&lt;br&gt;
  line_or_bytes: :line,&lt;br&gt;
  modes: [:raw, :read_ahead, :binary],&lt;br&gt;
  path: "reports/report_test.csv",&lt;br&gt;
  raw: true&lt;br&gt;
}&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Assim, ele nos traz uma Struct (nada mais é do que um map com um nome, resumidamente por hora)&lt;br&gt;
O file.stream não traz o conteúdo em si, mas sim metadados&lt;/p&gt;

&lt;p&gt;O file.stream possui um “!” no fim pois ele só abre arquivos existentes, não devolvendo tuplas com “error” ou “ok”.&lt;/p&gt;

&lt;p&gt;Vamos usar o Enum.each e para cada elemento que tiver nesse arquivo (cada linha), daremos um IO.inspect&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;|&amp;gt; Enum.each(fn elem -&amp;gt; IO.inspect(elem) end)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;E agora vamos chamar o mesmo comando &lt;code&gt;iex(14)&amp;gt; ReportsGenerator.build("report_test.csv”)&lt;/code&gt;&lt;br&gt;
E ele irá nos retornar: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
%File.Stream{&lt;br&gt;
  line_or_bytes: :line,&lt;br&gt;
  modes: [:raw, :read_ahead, :binary],&lt;br&gt;
  path: "reports/report_test.csv",&lt;br&gt;
  raw: true&lt;br&gt;
}&lt;br&gt;
"1,pizza,48\n"&lt;br&gt;
"2,açaí,45\n"&lt;br&gt;
"3,hambúrguer,31\n"&lt;br&gt;
"4,esfirra,42\n"&lt;br&gt;
"5,hambúrguer,49\n"&lt;br&gt;
"6,esfirra,18\n"&lt;br&gt;
"7,pizza,27\n"&lt;br&gt;
"8,esfirra,25\n"&lt;br&gt;
"9,churrasco,24\n"&lt;br&gt;
"10,churrasco,36"&lt;br&gt;
:ok&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora, pra cada linha do arquivo, ele leu e deu inspect.&lt;/p&gt;

&lt;p&gt;Agora, faremos um exemplo utilizando Enum.map e para cada linha nós iremos trabalhar essa linha. &lt;br&gt;
Por exemplo: nós iremos separar os elementos para visualizarmos de maneira melhor cada item. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr94abpvgk5afa3uhu1e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr94abpvgk5afa3uhu1e.png" alt=" " width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adicionamos algumas strings e mudamos o nosso enum e quando testamos novamente no terminal, ele nos retorna desta forma: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
iex(22)&amp;gt; ReportsGenerator.build("report_test.csv")&lt;br&gt;
[&lt;br&gt;
  ["1", "pizza", "48"],&lt;br&gt;
  ["2", "açaí", "45"],&lt;br&gt;
  ["3", "hambúrguer", "31"],&lt;br&gt;
  ["4", "esfirra", "42"],&lt;br&gt;
  ["5", "hambúrguer", "49"],&lt;br&gt;
  ["6", "esfirra", "18"],&lt;br&gt;
  ["7", "pizza", "27"],&lt;br&gt;
  ["8", "esfirra", "25"],&lt;br&gt;
  ["9", "churrasco", "24"],&lt;br&gt;
  ["10", "churrasco", "36"]&lt;br&gt;
]&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mas por que utilizamos o &amp;amp;?&lt;br&gt;
Quando criamos uma função anonima, podemos usar o fn com o E comercial  e criar uma função de forma implícita.&lt;/p&gt;

&lt;p&gt;Prosseguindo com o nosso parseamento do arquivo, podemos ver que ainda não está em um formato muito legal.&lt;br&gt;
Estamos consumindo uma lista de listas basicamente, o que não seria muito legal. &lt;br&gt;
Pra melhorarmos isso podemos utilizar a função &lt;code&gt;reduce&lt;/code&gt;, que funciona da seguinte forma: &lt;/p&gt;

&lt;p&gt;Enum.reduce([1,2,3,4], 0, fn elem, acc -&amp;gt; acc + elem end)&lt;/p&gt;

&lt;p&gt;Nessa função, passamos a coleção de dados que queremos passar, no nosso caso uma lista “1, 2,3.4”, um valor de acumulador inicial, no nosso caso “0”,  e uma função anonima “fn”, e essa função anonima sempre como primeiro elemento ela vai receber cada elemento da lista, e como segundo elemento o valor atual do acumulador, no nosso caso “acc"&lt;/p&gt;

&lt;p&gt;Quando aplicamos a função dentro do nosso projeto, obtemos como resultado: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2m5x0xzauyr946iwbpk3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2m5x0xzauyr946iwbpk3.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;iex(4)&amp;gt; ReportsGenerator.build("report_test.csv")&lt;br&gt;
%{&lt;br&gt;
  "1" =&amp;gt; 48,&lt;br&gt;
  "10" =&amp;gt; 36,&lt;br&gt;
  "2" =&amp;gt; 45,&lt;br&gt;
  "3" =&amp;gt; 31,&lt;br&gt;
  "4" =&amp;gt; 42,&lt;br&gt;
  "5" =&amp;gt; 49,&lt;br&gt;
  "6" =&amp;gt; 18,&lt;br&gt;
  "7" =&amp;gt; 27,&lt;br&gt;
  "8" =&amp;gt; 25,&lt;br&gt;
  "9" =&amp;gt; 24&lt;/p&gt;

&lt;p&gt;Agora, ao invés de uma lista de listas, temos um Map onde temos o ID do usuário e quanto ele consumiu, de acordo com o nosso arquivo de teste. &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Introdução ao Elixir</title>
      <dc:creator>Mateus Martins</dc:creator>
      <pubDate>Mon, 27 Jun 2022 01:37:40 +0000</pubDate>
      <link>https://dev.to/mateusbmo/introducao-ao-elixir-102a</link>
      <guid>https://dev.to/mateusbmo/introducao-ao-elixir-102a</guid>
      <description>&lt;p&gt;&lt;strong&gt;Strings&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Por padrão, uma string em Elixir sempre utilizará aspas duplas.&lt;br&gt;
Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; "mateus"
"mateus"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Criando interpolação de strings:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(7)&amp;gt; x = "martins"
"martins"
iex(8)&amp;gt; "mateus #{x}"
"mateus martins"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O que são esses /1, /2 que encontramos em algumas funções dentro das documentações?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;São chamadas de Aridade da função. &lt;br&gt;
E o que são?&lt;/p&gt;

&lt;p&gt;Aridade nada mais é do que quantas argumentos a função recebe.&lt;br&gt;
Por exemplo:&lt;/p&gt;

&lt;p&gt;A função length/1 (do modulo String) só recebe um argumento. &lt;br&gt;
E qual argumento é esse?&lt;/p&gt;

&lt;p&gt;A string que eu quero saber o cumprimento:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; String.length("mateus")
&amp;gt;6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste caso, a função &lt;code&gt;length&lt;/code&gt; está passando um único argumento, e me retornando o número de letras dentro dessa função. &lt;/p&gt;

&lt;p&gt;Como obter as funções do módulo String:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim, obtemos todas as funções do módulo String. &lt;/p&gt;

&lt;p&gt;E como sabemos o que cada função faz?&lt;/p&gt;

&lt;p&gt;Para isso, podemos usar o h(helper) antes de passar as funções:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;H String.slice

iex(2)&amp;gt; h String.slice


## Examples

    iex&amp;gt; String.slice("elixir", 1..3)
    "lix"

    iex&amp;gt; String.slice("elixir", 1..10)
    "lixir"

    iex&amp;gt; String.slice("elixir", -4..-1)
    "ixir"

    iex&amp;gt; String.slice("elixir", -4..6)
    "ixir"

For ranges where start &amp;gt; stop, you need to explicit mark them as increasing:

    iex&amp;gt; String.slice("elixir", 2..-1//1)
    "ixir"

    iex&amp;gt; String.slice("elixir", 1..-2//1)
    "lixi"

If values are out of bounds, it returns an empty string:

    iex&amp;gt; String.slice("elixir", 10..3)
    ""

    iex&amp;gt; String.slice("elixir", -10..-7)
    ""

    iex&amp;gt; String.slice("a", 0..1500)
    "a"

    iex&amp;gt; String.slice("a", 1..1500)
    ""


                        def slice(string, start, length)                        

  @spec slice(t(), integer(), non_neg_integer()) :: grapheme()



## Examples

    iex&amp;gt; String.slice("elixir", 1, 3)
    "lix"

    iex&amp;gt; String.slice("elixir", 1, 10)
    "lixir"

    iex&amp;gt; String.slice("elixir", 10, 3)
    ""

    iex&amp;gt; String.slice("elixir", -4, 4)
    "ixir"


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora na prática:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(4)&amp;gt; String.slice("MATEUSMARTINS", 2, 5)
"TEUSM"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outras formas de realiza-lar essa alteração:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(7)&amp;gt; x = "mateus"
"mateus"
iex(8)&amp;gt; String.downcase(x)
"mateus"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Atoms&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O que são atoms em Elixir?&lt;/p&gt;

&lt;p&gt;São constantes onde o valor da constante é o próprio nome. &lt;br&gt;
Exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(10)&amp;gt; :error
:error
iex(11)&amp;gt; :ok
:ok
iex(12)&amp;gt; :mateus
:mateus 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Listas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;É possível passar uma lista com vários “tipos” diferentes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[1, 2, 3, 4.5, “string”]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplos de listas somadas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(14)&amp;gt; [1, 2, 3] ++ [4, 5, 6]
[1, 2, 3, 4, 5, 6]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(15)&amp;gt; hd([1,2,3])
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(3)&amp;gt; tl([1,2,3])
[2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alguns outros exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(17)&amp;gt; x =  [1, 2, 3] ++ [4]  
[1, 2, 3, 4]

iex(18)&amp;gt; x
[1, 2, 3, 4]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Tuplas&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ao invés de se utilizar colchetes, utilizamos chaves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(4)&amp;gt; {1,2,3}
{1, 2, 3}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Qual a principal diferença entre Tuplas e Listas?&lt;/p&gt;

&lt;p&gt;A tupla é armazenada quantiguamente  na memória, ou seja, em endereços de memória  um após o outro, seguintes. &lt;br&gt;
Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(5)&amp;gt; x = {1, 2, 3, 4, 5, 6, 7}
{1, 2, 3, 4, 5, 6, 7}
iex(6)&amp;gt; elem(x, 4)
5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também podemos armazenar valores diferentes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(7)&amp;gt; put_elem(x, 4, "banana")
{1, 2, 3, 4, "banana", 6, 7}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Geralmente uma tupla tem 2 elementos apenas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(9)&amp;gt; {:ok, "meu arquivo"}
{:ok, "meu arquivo"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Maps&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;São utilizados para quando precisamos armazenar chave e valor em uma estrutura de dados por acesso direto por chave. &lt;/p&gt;

&lt;p&gt;Como criamos um mapa?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; %{a: 1, b: 2, c: 3}
%{a: 1, b: 2, c: 3}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usando strings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(3)&amp;gt; %{"a" =&amp;gt; 1, "b" =&amp;gt; 2, "c" =&amp;gt; 3}
%{"a" =&amp;gt; 1, "b" =&amp;gt; 2, "c" =&amp;gt; 3}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Qual a diferença na hora de criarmos um map?&lt;/p&gt;

&lt;p&gt;Atribuindo dentro de uma variável:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;meu_map = %{a: 1, b: 2, c: 3}  
%{a: 1, b: 2, c: 3}

iex(5)&amp;gt; meu_map.a
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, o mesmo não acontece com Strings.&lt;/p&gt;

&lt;p&gt;Maps também podem ter valores mesclados.&lt;br&gt;
Alguns meios de uso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(18)&amp;gt; meu_map                   
%{a: 1, b: 2, c: 3}
iex(19)&amp;gt; Map.put(meu_map, "d", 5.5)
%{:a =&amp;gt; 1, :b =&amp;gt; 2, :c =&amp;gt; 3, "d" =&amp;gt; 5.5}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como podemos alterar um valor dentro de um map?&lt;br&gt;
Neste exemplo criamos um map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(6)&amp;gt; x = %{c: 5, d: 6, e: "sal", f: 5.5}
%{c: 5, d: 6, e: "sal", f: 5.5}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, gostaria de mudar o valor de “D”. Como podemos fazer isso?&lt;/p&gt;

&lt;p&gt;Basta passar o map da seguinte maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ex(7)&amp;gt; %{x | d: 10}                       
%{c: 5, d: 10, e: "sal", f: 5.5}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não é possível adicionar um valor, apenas alterar um já existente. &lt;br&gt;
Um caso bem comum é na criação de usuários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(8)&amp;gt; users = [%{name: "Mateus", age: 22}, %{name: "Lucas", age: 25}]
[%{age: 22, name: "Mateus"}, %{age: 25, name: "Lucas"}]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern Matching&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Exemplos de Pattern Matching com mapas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ex(1)&amp;gt; %{a: 1, b: 2, c: 3, d: 4}
%{a: 1, b: 2, c: 3, d: 4}
iex(2)&amp;gt; %{c: valor} = %{a: 1, b: 2, c: 3, d: 4}
%{a: 1, b: 2, c: 3, d: 4}
iex(3)&amp;gt; valor
3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplos com tuplas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(4)&amp;gt; {:ok, result} =  {:ok, 14}
{:ok, 14}
iex(5)&amp;gt; result
14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Criando uma função anonima:  (sintaxe de uma função anonima: fn)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(1)&amp;gt; multiply = fn a, b -&amp;gt; a * b end
#Function&amp;lt;43.65746770/2 in :erl_eval.expr/5&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, com a função criada, executamos ela dessa maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(2)&amp;gt; multiply.(2,3)
6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outro exemplo de função anonima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(3)&amp;gt; read_file = fn
...(3)&amp;gt; {:ok, result} -&amp;gt; "Sucess #{result}" 
...(3)&amp;gt; {:error, reason} -&amp;gt; "Error #{reason}" 
...(3)&amp;gt; end
#Function&amp;lt;44.65746770/1 in :erl_eval.expr/5&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usando a função que foi criada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(4)&amp;gt; read_file.(File.read("test.txt"))
"Error enoent"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;*&lt;em&gt;Agora que aprendemos algumas funções básicas, vamos ao nosso primeiro projeto Elixir! *&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para criarmos um projeto em Elixir, basta realizar-mos o seguinte comando dentro do terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mateusmartins@Mateuss-MacBook-Pro ~ % mix new name_project
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/name_project.ex
* creating test
* creating test/test_helper.exs
* creating test/name_project_test.exs

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com o projeto criado, podemos abri-lo desta maneira no próprio terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd name_projct/
code .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(No meu caso, usei palace_list)&lt;br&gt;
Com isso, conseguiremos ver a estrutura básica de um projeto. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Algumas dicas do pacote mix: &lt;br&gt;
Mix test = roda os testes da aplicação &lt;br&gt;
Mix compile = compila a aplicação &lt;br&gt;
Mix  format = formata o código automaticamente&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pra rodar o &lt;code&gt;iex&lt;/code&gt; dentro do seu projeto basta rodar o comando  dentro do terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex -S mix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando fazemos isso ele automaticamente compila o nosso código e carrega todo o nosso código no iex.&lt;/p&gt;

&lt;p&gt;E como chamamos uma função específica de dentro de um módulo?&lt;/p&gt;

&lt;p&gt;Para isso, chamamos o nome do módulo (no meu caso, PalaceList) e o nome da função (por exemplo: hello) &lt;br&gt;
Ficando assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(2)&amp;gt; PalaceList.hello
:world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Criando nossa primeira função dentro do projeto&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Def (pra definir uma função), entre parênteses quais argumentos essa função recebe: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;def sum([], acc) do&lt;br&gt;
0&lt;br&gt;
end&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Depois criamos uma mesma função para definirmos o head, com o mesmo nome:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;def sum([head | tail], acc) do&lt;br&gt;
    head&lt;br&gt;
  end&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;E quando rodamos o recompile e chamamos a função dentro do terminal, obtemos este resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(7)&amp;gt; PalaceList.sum([1,2,3], 0)
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos atribuir o retorno do Match a uma variável:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;def sum([head | tail] =list, acc) do&lt;br&gt;
    list&lt;br&gt;
  end&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(10)&amp;gt; PalaceList.sum([1,2,3], 0)
[1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E agora estamos imprimindo a lista inteira.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(8)&amp;gt; PalaceList.sum([1,2,3], 0) 
6
iex(9)&amp;gt; PalaceList.sum([1,2,4], 0)
7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Porém, ainda temos um bug que se eu chamar a lista com o “5” no final, ele retorna 5. &lt;/p&gt;

&lt;p&gt;Para consertamos isso, ao invés de executarmos essa função  direto,  tornaremos essas funções PRIVADAS, ou seja, não permitiremos que o usuário execute elas, elas apenas são funções pra gente utilizar ela dentro do nosso módulo. &lt;/p&gt;

&lt;p&gt;Para deixar-mos uma função privada alteramos o def para defp &lt;/p&gt;

&lt;p&gt;E agora criaremos uma função chamada “call”, que irá chamar a função do módulo que é somar. &lt;/p&gt;

&lt;p&gt;Criamos ela dessa maneira: def call(lista) (aqui ela recebe uma lista qualquer) , do: sum(List, 0) (e ela sempre irá chamar a nossa função privada SUM com a lista que recebemos e o acumulador 0)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Def call(lista), do: sum(list, 0)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora, quando executamos no terminal, quando chamamos uma lista vazia obtemos o “0”&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(12)&amp;gt; PalaceList.call([])   
0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E quando chamamos uma lista obtemos a soma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(13)&amp;gt; PalaceList.call([1,2,3])
6

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testando nossa aplicação&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dentro do nosso projeto, abriremos a pasta “test” e acessaremos o arquivo “palace_list_test.exs” &lt;/p&gt;

&lt;p&gt;Dentro do nosso teste, podemos deletar o “doctest PalaceList”, pois ele executa todo o código que temos na documentação e ve se o código executa corretamente. &lt;br&gt;
Como deletemos a documentação, não iremos utilizar o doctest.&lt;/p&gt;

&lt;p&gt;Sempre teremos os testes com os nomes “exs”, enquanto os arquivos “comuns” serão “ex”. &lt;/p&gt;

&lt;p&gt;Temos dentro do nosso arquivo de test um “use ExUnit.Case”. Mas o que é e para que serve? &lt;/p&gt;

&lt;p&gt;Estamos trazendo todas as macros que temos pra usarmos no nosso test, trazendo todas as funcionalidades do ExUnit para dentro do módulo. &lt;/p&gt;

&lt;p&gt;Todo test começaremos com “describe” acompanhado do nome da função que queremos testar junto da sua aridade. &lt;br&gt;
Vale lembrar que sempre fazemos de funções PÚBLICAS.&lt;/p&gt;

&lt;p&gt;No nosso caso, ficaria assim: describe “call/1” do&lt;br&gt;
End&lt;/p&gt;

&lt;p&gt;Usamos a “/“ para dizer qual é a aridade. &lt;br&gt;
Poderíamos ter vários parâmetros, então dessa forma especificamos qual deles estamos testando. &lt;/p&gt;

&lt;p&gt;Agora,  iremos descrever o nosso test junto de uma descrição:&lt;br&gt;
Test “return the list sum""&lt;/p&gt;

&lt;p&gt;Agora, criaremos um setup para o nosso test: &lt;br&gt;
List = [1, 2, 3]&lt;/p&gt;

&lt;p&gt;E criaremos uma nova variável que irá armazenar a resposta&lt;br&gt;
Chamaremos o nosso módulo “PalaceList” com a função “Call”&lt;br&gt;
Não precisamos importar o módulo pois já temos acesso dentro do nosso test.&lt;/p&gt;

&lt;p&gt;response = PalaceList.call(list)&lt;/p&gt;

&lt;p&gt;Agora, criaremos uma resposta esperada: &lt;/p&gt;

&lt;p&gt;expect_response = “mateus”&lt;/p&gt;

&lt;p&gt;E, para executarmos o nosso test, utilizamos o assert. &lt;br&gt;
O assert irá verificar se um valor é igual ao outro. &lt;/p&gt;

&lt;p&gt;Faremos um primeiro test com valores diferentes para ele nos mostrar um erro. &lt;/p&gt;

&lt;p&gt;No terminal, fora do iex, rodaremos o comando “mix test”, e ele irá nos retornar a seguinte mensagem de erro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;== Compilation error in file test/palace_list_test.exs ==
** (ExUnit.AssertionError) 

Assertion with == failed
code:  assert response == expect_response
left:  6
right: "mateus"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tínhamos o valor 6 de um lado, e recebemos “mateus”.&lt;/p&gt;

&lt;p&gt;Agora, vamos voltar ao módulo de test e levar o resultado corretamente substituindo o nome pelo valor “6”.&lt;/p&gt;

&lt;p&gt;Rodamos o test novamente e obtemos o resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mix test

.

Finished in 0.01 seconds (0.00s async, 0.01s sync)
1 test, 0 failures
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos realizar o teste de outra maneira também:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;assert PalaceList.call([1, 2, 3]) == 6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Enum&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Uma breve introdução ao módulo Enum&lt;/p&gt;

&lt;p&gt;Normalmente, trabalhamos com o módulo Enum utilizando Listas, Maps ou Ranges. &lt;br&gt;
Mudamos a nossa função para “def call_enum(list), do: Enum.sum(list)”, e dentro do terminal chamamos ela desta maneira:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(3)&amp;gt; PalaceList.call_enum([1, 2, 3, 4])
10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Veja que o próprio Enum já possui uma função para somar todos os elementos. &lt;br&gt;
Também podemos realizar um teste com valores mínimos ou máximos de uma lista, utilizando o próprio enum. &lt;br&gt;
Desta forma, a função ficaria assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def call_enum(list), do: Enum.min(list)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E o retorno de uma lista iex(5)&amp;gt; PalaceList.call_enum([1, 2, 3, 4]) seria “1”&lt;/p&gt;

&lt;p&gt;Ou podemos transformar em valor máximo:&lt;/p&gt;

&lt;p&gt;def call_enum(list), do: Enum.max(list)&lt;/p&gt;

&lt;p&gt;E o maior valor da nossa lista seria o “4”. &lt;/p&gt;

&lt;p&gt;E outra função muito utilizada é o Map &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;def call_enum(list), do: Enum.map(list, fn elem -&amp;gt; elem + 1 end)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Assim, criamos uma função dentro do map que irá cada valor dentro dessa lista:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iex(12)&amp;gt; PalaceList.call_enum([1, 2, 3, 4])
[2, 3, 4, 5]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por hoje é isso pessoal! &lt;br&gt;
Nos vemos no próximo capítulo "Introdução ao Elixir - módulo 2""&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2bhv8kf65x8xbpcs2tq.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2bhv8kf65x8xbpcs2tq.gif" alt=" " width="220" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>liveview</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>O que são API's? (para iniciantes)</title>
      <dc:creator>Mateus Martins</dc:creator>
      <pubDate>Thu, 10 Feb 2022 15:27:57 +0000</pubDate>
      <link>https://dev.to/mateusbmo/o-que-sao-apis-para-iniciantes-1i24</link>
      <guid>https://dev.to/mateusbmo/o-que-sao-apis-para-iniciantes-1i24</guid>
      <description>&lt;h2&gt;
  
  
  Por que você precisa se preocupar com API's?
&lt;/h2&gt;

&lt;p&gt;Como desenvolvedor (ou até mesmo empresa), as APIs ajudam você a economizar tempo e facilitam muito o processo de desenvolvimento de software. Isso permite que você crie e libere produtos rapidamente. Se esses benefícios parecem interessantes para você, continue lendo!&lt;/p&gt;

&lt;h2&gt;
  
  
  O que são APIs?
&lt;/h2&gt;

&lt;p&gt;Antes de entrarmos em qualquer detalhe técnico, vamos dar uma olhada em um exemplo do mundo real para termos um contexto. &lt;br&gt;
No exemplo, veremos uma interação que todos nós já experimentamos um dia, pedindo comida diretamente para algum restaurante ou aplicativo.&lt;/p&gt;

&lt;p&gt;Pense sobre esta situação por um momento: como você normalmente pediria comida?&lt;/p&gt;

&lt;p&gt;Na sua forma mais simples, você faria um pedido e pegaria sua comida logo depois (espero). Em outras palavras, você faz um pedido e recebe uma resposta (na forma de comida). Esse tipo básico de interação (ou seja, fazer algum tipo de solicitação e obter algum tipo de resposta de volta) se aplica a muitos outros contextos. Mas, por enquanto, vamos nos concentrar no exemplo de pedido de comida.&lt;/p&gt;

&lt;p&gt;Vamos visualizar essa interação abaixo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4mn365d7e62b4h9ke6s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp4mn365d7e62b4h9ke6s.gif" alt=" " width="760" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Então, o que pedir comida tem a ver com API's?&lt;/p&gt;

&lt;p&gt;Em sua essência, as API's se comportam da mesma maneira. Pense em uma API como uma maneira de um software solicitar informações de outro software e receber uma resposta de volta. Bem, de que tipo de informação estamos falando? Na maioria das vezes, estamos falando de dados. Quaisquer dados que algum software deseja. Por exemplo: um site pode querer saber o clima em um local específico, ou um aplicativo de mídia social pode querer saber o que as pessoas estão fazendo. Basicamente, quaisquer dados que atendam às suas necessidades de negócios.&lt;/p&gt;

&lt;p&gt;Vamos visualizar como uma API se comporta:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzp6tv7kbvxscfq6rd4r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwzp6tv7kbvxscfq6rd4r.gif" alt=" " width="760" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como você pode ver, uma API ajuda você a solicitar e receber dados.&lt;/p&gt;

&lt;p&gt;No caso do nosso exemplo do pedido de comida, um cliente faz um pedido, que é então enviado para a cozinha. A cozinha então processa o pedido e envia a comida de volta ao cliente. O cliente não precisa saber como a cozinha faz sua comida, apenas que  recebe o pedido solicitado.&lt;/p&gt;

&lt;p&gt;As API's funcionam da mesma maneira. Um sistema faz uma solicitação, que é processada pelo receptor. O receptor então envia a resposta de volta ao solicitante. O solicitante não precisa saber como o destinatário processa a solicitação, apenas que recebe a resposta contendo a solicitação que requerida.&lt;/p&gt;

&lt;p&gt;Agora que temos uma ideia do que é uma API, o que significa?&lt;/p&gt;

&lt;p&gt;API significa Application Programming Interface, ou na sua tradução literária, Interface de Programação de Aplicações. &lt;/p&gt;




&lt;p&gt;Se você olhar para essas três palavras, uma delas pode ser menos clara do que as outras. Aposto que "interface" é essa palavra. Então o que isso significa?&lt;/p&gt;

&lt;p&gt;Vejamos outro exemplo: se quiser ouvir sons do seu computador, você precisará conectar algum dispositivo de áudio no computador. Mas como você faz isso? Você conectaria os fones de ouvido, por exemplo, a uma entrada USB. A entrada USB, neste exemplo, é uma interface entre seus fones de ouvido e o computador. Essa entrada USB expõe a funcionalidade ao usuário, para que o usuário obtenha o que deseja (som). O usuário não precisa entender como isso funciona, apenas receber o retorno que está buscando (neste caso, o som).&lt;/p&gt;

&lt;p&gt;Interfaces em software atuam no mesmo princípio. No contexto de software, uma Interface de Programação de Aplicativo ajuda o software a obter informações de outro software sem precisar saber como ele funciona, apenas que eles obtenham o que desejam.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxapo59neyxffdd4fzrtp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxapo59neyxffdd4fzrtp.jpg" alt=" " width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você percebe como esse princípio pode ser benéfico? Como seu software apenas solicita e recebe o que está procurando, você economiza tempo reutilizando a funcionalidade que já existe. Não há necessidade de reinventar os dados. &lt;br&gt;
Aqui está um exemplo: por que fazer pão caseiro quando você pode comprá-lo em uma loja? Isso economizaria muito tempo, o que ajuda a enviar seu produto mais rapidamente.&lt;/p&gt;

&lt;p&gt;Excelente! Agora que entendemos melhor as APIs, vamos entrar em mais detalhes. Vou voltar ao nosso primeiro exemplo: pedir comida. Como você sabe, existem alguns passos extras que você precisa tomar antes de pedir comida. Não é tão simples como pedir e depois receber comida. Essas etapas podem ser divididas em:&lt;/p&gt;

&lt;p&gt;Passo 1: Reconheça que você está com fome e que gostaria de comer alguma coisa.&lt;br&gt;
Passo 2: Vá a um restaurante que sirva o que você procura.&lt;br&gt;
Passo 3: Navegue pelo cardápio.&lt;br&gt;
Passo 4: Decida o que você gostaria de pedir.&lt;br&gt;
Passo 5: Fale com um garçom e faça seu pedido.&lt;br&gt;
Passo 6: Espere um pouco e, eventualmente, seu garçom trará o seu pedido.&lt;/p&gt;

&lt;p&gt;Vamos traduzir cada uma dessas etapas no contexto das API's:&lt;/p&gt;

&lt;p&gt;Etapa 1: Reconheça que você precisa de dados e gostaria de obtê-los sem precisar construí-los do zero.&lt;br&gt;
Etapa 2: Faça uma pesquisa na Internet para encontrar a API que deseja.&lt;br&gt;
Etapa 3: Navegue pela documentação da API.&lt;br&gt;
Etapa 4: Decida quais dados você precisa e como os solicitaria.&lt;br&gt;
Etapa 5: Interaja com a API e envie sua solicitação.&lt;br&gt;
Etapa 6: Espere um pouco e, eventualmente, sua API trará os seus dados.&lt;br&gt;
Fornecerei mais detalhes sobre cada uma dessas etapas em um artigo futuro, mas por enquanto, o propósito desse artigo é entender o que é uma API. Espero ter ajudado de uma forma mais interessante, com uma leitura simples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Onde você pode encontrar uma API?
&lt;/h2&gt;

&lt;p&gt;Às vezes, encontrar o prato que você quer pedir pode ser difícil. Por exemplo, se você quiser comer macarrão, pode visitar o restaurante que visitou anteriormente ou procurar online um novo restaurante com boas críticas. Outras vezes, você pode nem saber o que quer comer.&lt;/p&gt;

&lt;p&gt;Essa ideia também se aplica às API's. Se você quiser usar uma API, você pode usar uma com a qual esteja familiarizado ou fazer uma pesquisa no Google para encontrar o que está procurando. Mas isso pode ser difícil porque existem muitas API's por aí. E muitas vezes, pode ser difícil encontrar a API certa de que você precisa. Às vezes, você pode querer navegar pelas API's por categorias e ver o que há por aí.&lt;/p&gt;

&lt;p&gt;Bem, e se você quisesse tornar as coisas mais fáceis? Você pode ir a um buffet, pois sabe que eles têm todos os tipos de comida. E se você pudesse visitar um mercado agregado para todos os tipos de API's? Não seria muito mais fácil?&lt;/p&gt;

&lt;p&gt;Felizmente, existe um produto que faz exatamente isso! &lt;a href="https://rapidapi.com/" rel="noopener noreferrer"&gt;RapidAP&lt;/a&gt; é um mercado/agregado de API's, para ajudar a encontrar a API certa para suas necessidades. Você pode pensar nisso como um buffet de API's porque tem tudo o que você pode precisar.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quer aprender mais?
&lt;/h2&gt;

&lt;p&gt;Esta foi apenas uma introdução para ajudar os iniciantes a entender as API's e por que elas são importantes. Em um artigo futuro, entrarei em mais detalhes. Vou explicar como você pode encontrar a API certa para suas necessidades e como usá-las (com trechos de código). Espero que isso tenha ajudado você! &lt;/p&gt;

&lt;p&gt;Até mais! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqgn3gmtkzboudd317lk.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqgn3gmtkzboudd317lk.gif" alt=" " width="760" height="570"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>webdev</category>
      <category>programming</category>
      <category>braziliandevs</category>
    </item>
    <item>
      <title>Quer aprender sobre git e GitHub de uma forma mais divertida?</title>
      <dc:creator>Mateus Martins</dc:creator>
      <pubDate>Fri, 04 Feb 2022 17:34:48 +0000</pubDate>
      <link>https://dev.to/mateusbmo/quer-aprender-sobre-git-e-github-de-uma-forma-mais-divertida-n47</link>
      <guid>https://dev.to/mateusbmo/quer-aprender-sobre-git-e-github-de-uma-forma-mais-divertida-n47</guid>
      <description>&lt;p&gt;Nós sempre assistimos a muitos vídeos e tutoriais e passamos por muita documentação para aprender algum conceito ou qualquer linguagem de programação.&lt;/p&gt;

&lt;p&gt;Mas você sabia que é possível aprender git e GitHub de uma maneira mais divertida, como jogar ou visualizar?&lt;br&gt;
SIM! você ouviu direito, jogando!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aqui estão alguns dos recursos para aprender git e GitHub de uma maneira mais divertida.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;1) TwilioQuest - "Floresta de código aberto":&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Este é um jogo feito por &lt;a href="https://www.twilio.com/pt-br/" rel="noopener noreferrer"&gt;Twilio &lt;/a&gt;, você aprenderá sobre git e GitHub enquanto joga e faz tarefas. Além disso, você ganhará XP após cada tarefa que concluir.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.twilio.com/quest/learn/open-source" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1tadbsi34t6jrhz0rts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft1tadbsi34t6jrhz0rts.png" alt=" " width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) E não para por ai!:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ele permite que você visualize as estruturas internas dos repositórios Git em tempo real.&lt;br&gt;
&lt;a href="https://ohmygit.org" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbv38krxaakw83b4vj9aj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbv38krxaakw83b4vj9aj.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Aprenda a ramificação do Git:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Você pode dominar seu conceito de ramificação do git visualizando, jogando e fazendo certas tarefas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learngitbranching.js.org/?locale=pt_BR" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkx32gpkojvwo8pchiwuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkx32gpkojvwo8pchiwuj.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4) Laboratório de aprendizagem do GitHub:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/" rel="noopener noreferrer"&gt;O próprio GitHub &lt;/a&gt;fornece uma trilha de aprendizado, que aumenta suas habilidades ao concluir projetos divertidos e realistas.&lt;br&gt;
&lt;a href="https://lab.github.com/" rel="noopener noreferrer"&gt;Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsi601i45zxqdasg119s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvsi601i45zxqdasg119s.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Obrigado! &lt;/p&gt;

&lt;p&gt;Qualquer dúvida ou sugestão você pode entrar em contato comigo através do &lt;a href="https://www.instagram.com/mateusbmo/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bye! &lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
    </item>
  </channel>
</rss>
