<?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: Ingresse</title>
    <description>The latest articles on DEV Community by Ingresse (@ingresse).</description>
    <link>https://dev.to/ingresse</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%2Forganization%2Fprofile_image%2F1966%2F3b444e7a-0310-4d9e-9bda-66253ee904df.png</url>
      <title>DEV Community: Ingresse</title>
      <link>https://dev.to/ingresse</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ingresse"/>
    <language>en</language>
    <item>
      <title>Docker e Docker Compose um guia para iniciantes.</title>
      <dc:creator>Leoni Mella</dc:creator>
      <pubDate>Mon, 11 May 2020 14:24:17 +0000</pubDate>
      <link>https://dev.to/ingresse/docker-e-docker-compose-um-guia-para-iniciantes-48k8</link>
      <guid>https://dev.to/ingresse/docker-e-docker-compose-um-guia-para-iniciantes-48k8</guid>
      <description>&lt;h1&gt;
  
  
  Docker e Docker Compose um guia para iniciantes.
&lt;/h1&gt;

&lt;p&gt;Quando comecei a usar &lt;em&gt;Docker&lt;/em&gt; e o &lt;em&gt;Docker Compose&lt;/em&gt; foi fácil entender quais eram suas funções, mas encontrei dificuldade em descobrir como eu poderia aplicá-los em meus projetos. Depois de muita leitura, tentativa e erro e algumas implementações eu consegui "decifrar" os &lt;strong&gt;pedaços que estavam faltando&lt;/strong&gt; e aprendi o básico para utilizá-lo.&lt;/p&gt;

&lt;p&gt;Nesse artigo tento explicar alguns desses pedaços que, os inciantes em &lt;em&gt;Docker&lt;/em&gt;, geralmente se confundem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Antes de começarmos
&lt;/h2&gt;

&lt;p&gt;Caso você não conheça nada sobre &lt;em&gt;Docker&lt;/em&gt;, sugiro que você leia a &lt;a href="https://docs.docker.com/"&gt;documentação oficial&lt;/a&gt; antes e se você ainda não tem &lt;em&gt;Docker&lt;/em&gt; e &lt;em&gt;Docker Compose&lt;/em&gt; instalado, aqui estão alguns links para ajuda-lo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/install/"&gt;Instalação&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/como-instalar-e-utilizar-o-docker-primeiros-passos-pt"&gt;Instalação em pt-br&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/docker-overview/"&gt;Docker overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Docker Compose

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/install/"&gt;Instalação&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-docker-compose-on-ubuntu-18-04-pt"&gt;Instalação em pt-br&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/"&gt;Docker Compose overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dividi este artigo por partes que considero importante, sinta-se livre para pular as que você já esteja familiarizado.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 01 - Dockerfile, Imagens e Containers&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Geralmente o arquivo &lt;code&gt;Dockerfile&lt;/code&gt; é o ponto de entrada para quem começa a utilizar o &lt;em&gt;Docker&lt;/em&gt;. Embora o &lt;a href="https://docs.docker.com/get-started/part2/"&gt;guia&lt;/a&gt; explique bem as instruções definidas no arquivo eu não conseguia entender muito bem o que eram as &lt;strong&gt;imagens&lt;/strong&gt; e o que eram os &lt;strong&gt;containers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;Dockerfile&lt;/code&gt; define uma &lt;strong&gt;imagem&lt;/strong&gt;. E o que é uma imagem? A &lt;strong&gt;imagem&lt;/strong&gt; é um conjunto de recursos responsável pela execução de um código ou uma aplicação. Geralmente a imagem que você define sempre tem outra imagem como base. Você pode pensar nela como se fosse um pacote semelhante a um módulo do &lt;code&gt;node_modules&lt;/code&gt;, ou um &lt;code&gt;package&lt;/code&gt; dentro do &lt;code&gt;vendor&lt;/code&gt; da sua aplicação, não é a forma mais correta de definir, mas pode ajudar a enxergar como ela funciona. Esses pacotes de recursos servem para executar alguma função dentro da sua aplicação, já as imagens servem para construir o &lt;strong&gt;container&lt;/strong&gt; que você vai rodar sua aplicação.&lt;/p&gt;

&lt;p&gt;Todo &lt;strong&gt;container&lt;/strong&gt; roda em cima de uma &lt;strong&gt;imagem&lt;/strong&gt;, é uma dependência direta, se tem um &lt;strong&gt;container&lt;/strong&gt; sendo executado tem uma &lt;strong&gt;imagem&lt;/strong&gt; por trás dele. Por exemplo, vamos supor que nós queremos executar o comando &lt;code&gt;elixir -v&lt;/code&gt;. Nós precisamos definir uma &lt;strong&gt;imagem&lt;/strong&gt; capaz de interpretar a linguagem Elixir e depois colocar um &lt;strong&gt;container&lt;/strong&gt; para executar essa imagem. Vamos criar o &lt;code&gt;Dockerfile&lt;/code&gt; e inserir nele o mínimo do mínimo para nosso exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; elixir:1.10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos construir a imagem que estamos definindo com o comando &lt;code&gt;build&lt;/code&gt; (mais sobre a &lt;code&gt;--tag&lt;/code&gt; depois):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--tag&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;elixir:example &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="c"&gt;# o ponto final é importante!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto! Temos a imagem criada, você pode conferir ela listando as imagens no seu sistema, executando &lt;code&gt;docker image ls&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Agora que temos uma imagem definida, vamos criar nosso container e executar o comando que queremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; elixir:example elixir &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E pronto! A imagem que criamos foi utilizada nesse container que executou o comando &lt;code&gt;elixir -v&lt;/code&gt; e foi destruído após essa execução graças a flag &lt;code&gt;--rm&lt;/code&gt; que passamos.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Pegadinhas"
&lt;/h3&gt;

&lt;p&gt;Nosso &lt;code&gt;Dockerfile&lt;/code&gt; é muito muito simples e nesse caso não precisaríamos ter definido um. O mesmo resultado pode ser obtido ao executar o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; elixir:1.10 elixir &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora ao invés rodar um container em cima da imagem que criamos com o &lt;code&gt;docker build ...&lt;/code&gt;, rodamos o container tendo como base a imagem padrão do Elixir 1.10: &lt;code&gt;elixir:1.10&lt;/code&gt;. Já que nossa imagem só tem como dependência a &lt;code&gt;elixir:1.10&lt;/code&gt; cortamos caminho e executamos o container direto com ela.&lt;/p&gt;

&lt;p&gt;Mas vamos supor que além da linguagem Elixir instalada, precisássemos também do Git. Ai sim declaramos um &lt;code&gt;Dockerfile&lt;/code&gt; que reuna as duas dependências:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; elixir:1.10&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install &lt;/span&gt;git &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma a imagem gerada contém esses dois recursos que seriam necessários pela nossa aplicação.&lt;/p&gt;

&lt;p&gt;E pra fechar essa primeira parte, e quanto a essa flag que utilizamos &lt;code&gt;--tag&lt;/code&gt;? Quando "tageamos" uma imagem estamos versionando ela, você pode fazer um paralelo com o sistema de &lt;strong&gt;branches&lt;/strong&gt; do Git. Ao tagear uma imagem nós salvamos tudo o que foi instalado nessa imagem naquela versão. Por exemplo, a imagem &lt;code&gt;elixir:1.10&lt;/code&gt; significa que estamos utilizando uma imagem com nome Elixir e que a versão dessa &lt;strong&gt;imagem&lt;/strong&gt; é a 1.10, &lt;strong&gt;por convenção a versão de Elixir sendo executada dentro dessa imagem também é a 1.10.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Isso se repete para todas as outras linguagens e recursos: &lt;code&gt;php:7.3&lt;/code&gt;, &lt;code&gt;python:3.8&lt;/code&gt;, &lt;code&gt;ubuntu:18.04&lt;/code&gt; e etc...&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 02 - Operando o Container&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;container&lt;/strong&gt; é a parte responsável por executar o que foi definido na sua imagem, sendo assim é recomendado evitar qualquer mudança ou edição diretamente. Caso você instale ou modifique alguma coisa no container a alteração feita fica disponível somente no próprio &lt;strong&gt;container&lt;/strong&gt; e não na &lt;strong&gt;imagem&lt;/strong&gt; base. Dito isso, de vez em quando precisamos debugar, modificar ou experimentar alguma coisa em nossas aplicações.&lt;/p&gt;

&lt;p&gt;Vamos cobrir algumas operações e configurações básicas que podem ajudar você a dar aquele ajuste fino na sua aplicação e ver o que está acontecendo dentro dela.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1 Criando
&lt;/h3&gt;

&lt;p&gt;O comando &lt;code&gt;docker run&lt;/code&gt; cria um container dada determinada imagem e ele ficará la até que você o remova. Se você usa a forma mais simples do comando, &lt;code&gt;docker run elixir:1.10&lt;/code&gt; o &lt;em&gt;Docker&lt;/em&gt; cria um container com um nome default gerado automaticamente, executa o que está definido na imagem, ou o comando que você passou com o output do comando no terminal.&lt;/p&gt;

&lt;p&gt;Podemos melhorar isso passando alguns parâmetros para o comando &lt;code&gt;docker run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dê um nome ao seu container usando a flag &lt;code&gt;--name&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;application elixir:1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso facilita muito no manuseio, se você precisar executar um comando nesse container ou pausar, iniciar e remover ele, basta passar o nome selecionado ao invés do id. Por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker start application

docker stop application

docker &lt;span class="nb"&gt;exec &lt;/span&gt;application &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando o container em &lt;em&gt;detached&lt;/em&gt; mode usando a flag &lt;code&gt;-d&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;application &lt;span class="nt"&gt;-d&lt;/span&gt; elixir:1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após a inicialização do container ele continua rodando em segundo plano, liberando o seu terminal. Provavelmente você vai usar muito essa flag. Você pode conferir o status atual do seu container com o comando &lt;code&gt;docker ps&lt;/code&gt; e ver que ele continua lá, rodando.&lt;/p&gt;

&lt;p&gt;Exponha uma porta de rede de seu container para que ele possa receber tráfego com a flag &lt;code&gt;--expose&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;application &lt;span class="nt"&gt;--expose&lt;/span&gt; 4000 &lt;span class="nt"&gt;-d&lt;/span&gt; elixir:1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma o container deixa a porta &lt;code&gt;4000&lt;/code&gt; exposta para receber tráfego através dela. Provavelmente você vai expor a porta que sua aplicação está ouvindo. Ou você pode vincular com uma porta no seu &lt;code&gt;localhost&lt;/code&gt; para que toda vez que você faça um request para essa porta, por exemplo: &lt;code&gt;http://localhost:4000&lt;/code&gt; esse request seja encaminhado para o seu container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;application &lt;span class="nt"&gt;-p&lt;/span&gt; 4000:4000 &lt;span class="nt"&gt;-d&lt;/span&gt; elixir:1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A flag &lt;code&gt;-p 4000:4000&lt;/code&gt; indica que a porta &lt;code&gt;4000&lt;/code&gt; da sua máquina será encaminhada para a &lt;code&gt;4000&lt;/code&gt; do container. Resumindo &lt;code&gt;-p host_port:container_port&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;É importante entender a diferença entre o vinculo &lt;code&gt;-p&lt;/code&gt; e a exposição &lt;code&gt;--expose&lt;/code&gt; de portas do container&lt;/strong&gt;. Quando expomos uma porta do container, ela não está vinculada à nossa máquina, ela apenas está disponível para o request, dessa forma ao invés de fazer o request assim: &lt;code&gt;http://localhost:4000&lt;/code&gt; fazemos o request assim: &lt;code&gt;http://{container_ip}:4000&lt;/code&gt;. Demorei um tempo para entender isso!&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2 Gerenciando
&lt;/h3&gt;

&lt;p&gt;Quando um container está rodando é corriqueiro executarmos algumas operações nele durante o desenvolvimento. As vezes precisamos ver os logs da aplicação, modificar algum comportamento, checar alguma outra coisa, enfim... Problemas que aparecem durante o desenvolvimento.&lt;/p&gt;

&lt;p&gt;Vamos supor que criamos o container seguindo o exemplo do tópico anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--expose&lt;/span&gt; 4000 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; application elixir:1.10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se quisermos ver os logs da aplicação que está sendo executada dentro do container, geralmente basta executar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando esse comando todo o log que existe no seu container será exibido no seu terminal. Você pode aplicar a flag &lt;em&gt;follow&lt;/em&gt; &lt;code&gt;-f&lt;/code&gt;, isso fará com que o terminal fique "escutando" os logs e qualquer logs novos serão exibidos na sua tela.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs application &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Melhorando um pouco mais, podemos filtrar o output inicial desse comando com a quantidade de linhas que quiser ver. Fazemos isso com a flag &lt;code&gt;--tail=number&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs application &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="nt"&gt;--tail&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma seguimos os logs do container e será exibido somente as últimas 10 linhas.&lt;/p&gt;

&lt;p&gt;Outra operação muito comum é o "ssh login" nos containers. Para tal operação utilizamos o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; application bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse comando não faz um "ssh login". Na verdade ele vai modificar o input do seu terminal para que todos os comandos a seguir passem a rodar dentro do programa iniciado dentro do container, o &lt;code&gt;bash&lt;/code&gt; nesse caso. E também vincula o output do container ao seu terminal. Tudo isso é feito pelas flags &lt;code&gt;-it&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Você pode rodar comandos para o seu container sem essas flags. Algumas aplicações escrevem arquivos de logs ao invés de só exibi-los no terminal, para ler esses arquivos você poderia uilizar o &lt;code&gt;docker exec&lt;/code&gt; da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;application &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /path/to/log_file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que temos um entendimento claro da diferença entre &lt;strong&gt;imagens&lt;/strong&gt; e &lt;strong&gt;containers&lt;/strong&gt; e de alguns comandos básicos, vamos falar sobre o &lt;em&gt;Docker Compose&lt;/em&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 03 - Docker Compose não é Docker&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Pode parecer besteira, mas é importante ressaltar aqui que &lt;em&gt;Docker Compose&lt;/em&gt; e &lt;em&gt;Docker&lt;/em&gt; são coisas diferentes!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resumindo, o &lt;em&gt;Docker Compose&lt;/em&gt; é uma ferramenta de administração de containers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Geralmente, no mundo de aplicações descentralizadas, os famosos &lt;em&gt;Micro Services&lt;/em&gt;, é comum que seu negócio esteja dividido em aplicações diferentes, as vezes em linguagens de programação diferentes. Por causa dessa separação, teoricamente, você precisaria de mais de uma imagem e mais de um container para que tudo funcione.&lt;/p&gt;

&lt;p&gt;Mesmo se sua aplicação for um monolito, a chance de você utilizar um banco de dados, web server, redis e outras tecnologias fora da sua aplicação é grande o que "força" você a dividir cada vez mais em containers e imagem menores que sejam responsáveis somente por uma tarefa.&lt;/p&gt;

&lt;p&gt;Então, se você tem uma aplicação monolítica, que se conecta a um banco de dados, o ideal seria ter um container com sua aplicação e outra com seu banco de dados, certo? Com o que vimos até agora você poderia criar esses dois containers rodando o &lt;code&gt;docker run&lt;/code&gt; com especificações um pouco diferentes.&lt;/p&gt;

&lt;p&gt;Mas vamos supor que além da aplicação e do banco de dados você também precise do Nginx. Ai você teria que criar mais um container. Percebe que começa a ficar complicado gerenciar esses containers "soltos" que estamos criando para nossa aplicação funcionar? Por causa dessa crescente complexidade você pode optar pelos seguintes cenários:&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Rodar todos os containers de forma independente
&lt;/h3&gt;

&lt;p&gt;Nesse cenário você sairia escrevendo &lt;code&gt;docker run&lt;/code&gt; no seu terminal como se não houvesse amanhã. Destruindo e modificando containers até que eles funcionem da maneira que você espera.&lt;/p&gt;

&lt;p&gt;Funciona, mas essa abordagem não é muito prática, imagina que para subir sua aplicação você tenha que iniciar cinco containers diferentes. Lá vai você &lt;code&gt;docker run ...&lt;/code&gt;, &lt;code&gt;docker run ...&lt;/code&gt;, &lt;code&gt;docker run ...&lt;/code&gt;, &lt;code&gt;docker run ...&lt;/code&gt; e por último &lt;code&gt;docker run ...&lt;/code&gt; com flags e imagens diferentes em cada comando... Acho que já deu preguiça em você só de pensar no trabalho desse método.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 Agregar todas as tecnologias em uma única imagem
&lt;/h3&gt;

&lt;p&gt;Você poderia criar uma imagem que contenha todas as dependências do seu negócio. Parece interessante, certo?&lt;/p&gt;

&lt;p&gt;Mas imagine o tanto de configuração necessária no seu &lt;code&gt;Dockerfile&lt;/code&gt; para que você rode sua aplicação, seu banco de dados, seu web server e etc. Você acabaria tendo um &lt;code&gt;Dockerfile&lt;/code&gt; mega extenso e difícil de manter. Seria praticamente fazer o setup disso tudo no seu próprio computador. Bem cansativo também.&lt;/p&gt;

&lt;p&gt;Essa abordagem não é de todo o mal para ambientes de desenvolvimento ou homologação, mas imagine em um servidor de produção. Na AWS, por exemplo, você utilizar o seu banco de dados dentro de uma EC2 não parece uma boa ideia. Mas pode ser que você esteja usando &lt;em&gt;Docker&lt;/em&gt; só em desenvolvimento, nesse caso pode ser uma abordagem válida.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Criar um docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;Essa provavelmente é a melhor abordagem para gerenciar vários containers dependentes. O arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt; é onde declaramos nossas instruções e o estado que cada container deve ser criado e operado bem como a comunicação entre eles.&lt;/p&gt;

&lt;p&gt;Esse tópico é um pouco extenso, vamos elaborar melhor ele na próxima parte deste artigo.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 04 - Docker Compose&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Vimos que o &lt;em&gt;Docker Compose&lt;/em&gt; é uma ferramenta para gerenciar containers que tenham algum tipo de dependência entre si. Nós declaramos esses containers e seus parâmetros em um arquivo chamado &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vamos supor que em uma empresa o negócio dela esteja dividido em três partes: Uma aplicação que utiliza o Phoenix (um &lt;em&gt;web framework&lt;/em&gt; feito com Elixir), um servidor web Nginx e um banco de dados Postgres.&lt;/p&gt;

&lt;p&gt;Dado esse cenário, vamos criar um &lt;code&gt;docker-compose.yml&lt;/code&gt; capaz de definir 3 containers diferentes para que cada tecnologia tenha seu próprio ambiente e sejam capazes de conversar entre si.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Criando o docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;A primeira coisa que fazemos no arquivo é declarar os 3 containers que precisamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mix&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;phx.server"&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.17&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O bloco &lt;code&gt;version&lt;/code&gt; mostra pra gente qual versão do &lt;code&gt;docker-compose&lt;/code&gt; está sendo utilizada e o bloco &lt;code&gt;services&lt;/code&gt; declara os 3 containers necessários: app, nginx e postgres. Cada &lt;code&gt;service&lt;/code&gt; é um bloco indenpendente com as próprias declarações.&lt;/p&gt;

&lt;p&gt;No service &lt;code&gt;app&lt;/code&gt; temos duas declarações. A primeira é a &lt;code&gt;build: .&lt;/code&gt; essa declaração define que para construir esse container deve ser utilizado um &lt;code&gt;Dockerfile&lt;/code&gt; que deve estar no mesmo diretório que o arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt;. Por esse service representar o container da nossa aplicação, é comum que tenhamos um &lt;code&gt;Dockerfile&lt;/code&gt; que declara os recursos que precisamos em nossa imagem para que a aplicação rode corretamente.&lt;/p&gt;

&lt;p&gt;Nos demais services, nginx e postgres, nós substituímos a declaração &lt;code&gt;build&lt;/code&gt; pela declaração &lt;code&gt;image&lt;/code&gt;. Dessa forma ao invés de procurar outro &lt;code&gt;Dockerfile&lt;/code&gt; para construir uma imagem do Nginx e outro para construir a imagem do Postgres, nós utilizamos uma imagem pronta, fornecida pelo &lt;em&gt;Docker Hub&lt;/em&gt; que já possui essas duas tecnologias prontas para uso.&lt;/p&gt;

&lt;p&gt;Você poderia declarar &lt;code&gt;Dockerfiles&lt;/code&gt; diferentes para cada service, mas em nosso caso não é necessário, já que as imagens &lt;code&gt;nginx:1-17&lt;/code&gt; e a &lt;code&gt;postgres:9.5&lt;/code&gt; já tem tudo o que precisamos para as respectivas tecnologias.&lt;/p&gt;

&lt;p&gt;E a ultima declaração do &lt;code&gt;app&lt;/code&gt; é  a &lt;code&gt;command&lt;/code&gt;. Nela nós colocamos o valor &lt;code&gt;mix phx.server&lt;/code&gt;, que é um comando do Phoenix responsável por inicializá-lo. Assim, quando o container ficar pronto, esse comando será executado e nossa aplicação é iniciada dentro dele.&lt;/p&gt;

&lt;p&gt;Não utilizamos &lt;code&gt;command&lt;/code&gt; nos outros services pois as imagens que escolhemos já lidam com essa parte da inicialização do serviço dentro delas.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.2 Melhorando os serviços
&lt;/h3&gt;

&lt;h4&gt;
  
  
  4.2.1 App
&lt;/h4&gt;

&lt;p&gt;Além dos pedaços que já definimos no tópico anterior temos que nos preocupar com alguns outros aspectos da nossa aplicação e do nosso container. Precisamos expor a porta que nossa aplicação ouve, montar um "volume" que vai ligar os arquivos locais com os arquivos do container e também, por comodidade, definir um &lt;em&gt;working directory&lt;/em&gt; para facilitar a execução de alguns comandos da nossa aplicação.&lt;/p&gt;

&lt;p&gt;Para que todos os requisitos sejam atendidos, modificamos o bloco &lt;code&gt;app&lt;/code&gt; da seguinte forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/var/www/application/&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/application/"&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mix&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;phx.server"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como vimos anteriormente &lt;code&gt;expose&lt;/code&gt; expõe a porta &lt;code&gt;4000&lt;/code&gt; do container para que ela receba tráfego. &lt;code&gt;working_dir&lt;/code&gt; define que o path que passamos à ela, &lt;code&gt;/var/www/application/&lt;/code&gt; daqui pra frente seja o diretório padrão onde os comandos serão executados. Então quando o container for executar o &lt;code&gt;mix phx.server&lt;/code&gt; ou qualquer outro comando passado à ele, ele vai executar no diretório &lt;code&gt;/var/www/application/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;container_name&lt;/code&gt; é basicamente isso, estamos definindo um nome para nosso container.&lt;/p&gt;

&lt;p&gt;E por últimos temos o &lt;code&gt;volume&lt;/code&gt;, essa declaração faz uma "ligação" com o diretório da sua máquina (host) com o diretório do container. Então, nós estamos "ligando" o diretório em que o &lt;code&gt;docker-compose.yml&lt;/code&gt; está &lt;code&gt;./&lt;/code&gt; com o diretório &lt;code&gt;/var/www/application/&lt;/code&gt; dentro do container. Dessa forma todos os arquivos que tem em um diretório aparecerá no outro.&lt;/p&gt;

&lt;h4&gt;
  
  
  4.2.2 Nginx e Postgres
&lt;/h4&gt;

&lt;p&gt;Para concluir a definição do nosso &lt;code&gt;docker-compose.yml&lt;/code&gt; vamos complementar os serviços restantes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.17&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nginx"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx:/etc/nginx/conf.d&lt;/span&gt;
    &lt;span class="s"&gt;ports:t&lt;/span&gt;
      &lt;span class="s"&gt;- "80:80"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicionamos o &lt;code&gt;volume&lt;/code&gt;, que colocará os arquivos de configuração do Nginx dentro do caminho correto do container. E por último adicionamos o &lt;code&gt;port&lt;/code&gt; que vai vincular o nosso &lt;code&gt;localhost&lt;/code&gt; ao container do &lt;code&gt;nginx&lt;/code&gt;. Dessa forma, sempre que fazemos um request &lt;code&gt;http://localhost&lt;/code&gt;, ele será encaminhado para o container do &lt;code&gt;nginx&lt;/code&gt; que, por sua vez, encaminhará o request para o container &lt;code&gt;app&lt;/code&gt;, conforme dita as configurações nos arquivos dentro da pasta&lt;code&gt;./nginx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E por último, completamos a definição do Postgres&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.5&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./postgres:/var/lib/postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=your_db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=your_user&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=your_secret&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A única descrição nova aqui é a &lt;code&gt;environment&lt;/code&gt;. Com ela você adiciona &lt;em&gt;env variables&lt;/em&gt; ao seu container. As três variáveis que adicionamos servem para o Postgres configurar um banco de dados, usuário e senha.&lt;/p&gt;

&lt;p&gt;Vinculamos as &lt;code&gt;ports&lt;/code&gt; do Postgres com o host para facilitar a conexão ao container do banco de dados. Dessa forma, se você possui algum programa para gerenciar banco de dados, por exemplo, facilita a conexão com esse container.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.3 Completando o docker-compose.yml
&lt;/h3&gt;

&lt;p&gt;Se você seguiu esse guia até agora, a versão final do seu &lt;code&gt;docker-compose.yml&lt;/code&gt; será assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/var/www/application/&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/application/"&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mix&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;phx.server"&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.17&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nginx"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx:/etc/nginx&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.5&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./postgres:/var/lib/postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=your_db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=your_user&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=your_secret&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Agora que temos o nosso arquivo do &lt;code&gt;docker-compose&lt;/code&gt; configurado, vamos ver como utilizá-lo!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 05 - Usando o Docker Compose&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;No tópico anterior definimos um &lt;code&gt;docker-compose.yml&lt;/code&gt; com três containers para nossa aplicação ser executada, porém para que tudo funcione nesse momento, vamos fazer pequenas alterações na declaração do nosso serviço &lt;code&gt;app&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/var/www/application/&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/application/"&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000"&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como não temos uma aplicação Phoenix pronta para rodar o comando &lt;code&gt;mix phx.server&lt;/code&gt; não vai funcionar e nosso container não conseguirá subir.&lt;/p&gt;

&lt;p&gt;Substituímos por um container criado a partir de uma image padrão de Elixir &lt;code&gt;elixir:1.10&lt;/code&gt; e trocamos a declaração &lt;code&gt;command&lt;/code&gt; por &lt;code&gt;tty&lt;/code&gt;. A declaração &lt;code&gt;tty&lt;/code&gt; faz com que o container fique em execução em segundo plano mesmo se nenhum comando for executado, o que é justamente o que queremos.&lt;/p&gt;

&lt;p&gt;Outra modificação que precisamos fazer é remover o &lt;code&gt;volume&lt;/code&gt; do serviço &lt;code&gt;nginx&lt;/code&gt;. Como não temos aplicação rodando, não precisamos configurar o Nginx para rotear o tráfego para o container desejado.&lt;/p&gt;

&lt;p&gt;Resumindo, o novo &lt;code&gt;docker-compose.yml&lt;/code&gt; fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.7"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;app"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./:/var/www/application/&lt;/span&gt;
    &lt;span class="na"&gt;working_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/www/application/"&lt;/span&gt;
    &lt;span class="na"&gt;expose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000"&lt;/span&gt;
    &lt;span class="na"&gt;tty&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.17&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nginx"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:9.5&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./postgres:/var/lib/postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=your_db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=your_user&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=your_secret&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Feito isso podemos colocar todos esses containers para rodar com o comando&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;em&gt;Docker&lt;/em&gt; vai validar nosso arquivo &lt;code&gt;yml&lt;/code&gt; e se tudo estiver ok vai começar a procurar as imagens que nossos containers precisam para serem executados. Aqui nós também adicionamos a flag &lt;code&gt;-d&lt;/code&gt; para que nosso terminal seja liberado após a conclusão desse comando.&lt;/p&gt;

&lt;p&gt;A primeira vez que você executa esse comando em um projeto pode demorar um pouco. O &lt;em&gt;Docker&lt;/em&gt; precisa preparar todas as imagens que esses containers utilizarão e dependendo da sua internet ou do seu computador essa etapa pode levar alguns minutos.&lt;/p&gt;

&lt;p&gt;Feito isso o &lt;em&gt;Docker&lt;/em&gt; começa a criar os containers na ordem e inicializá-los. E se tudo correu bem você pode listar os containers criados com &lt;code&gt;docker ps&lt;/code&gt;. O output desse comando mostra todos os containers que estão em execução, adiciona a flag &lt;code&gt;-a&lt;/code&gt; para ver todos os containers que existe na sua máquina.&lt;/p&gt;

&lt;p&gt;Deixo abaixo uma lista com os comandos mais corriqueiros do &lt;em&gt;Docker Compose&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;Parando todos os containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose stop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Removendo todos os containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vendo o log de todos os containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose logs &lt;span class="nt"&gt;-f&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Construir os containers sem inicializá-los:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale ressaltar que os containers criados pelo comando &lt;code&gt;docker-compose&lt;/code&gt; são "comuns", sendo assim os outros comandos de &lt;em&gt;Docker&lt;/em&gt; também são válidos. Você pode até parar e retomar a execução de um container em específico.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Parte 06 - Interação entre Containers&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Teoricamente, todos os containers que criamos no tópico anterior fazem parte da mesma aplicação e por isso precisam se comunicar. Quando criamos containers utilizando o &lt;code&gt;docker-compose&lt;/code&gt;, além dos containers, outras entidades são criadas. Uma das mais importantes é a &lt;strong&gt;&lt;em&gt;Network&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na versão &lt;code&gt;2.x&lt;/code&gt; todos os containers de todos os arquivos &lt;code&gt;docker-compose.yml&lt;/code&gt; que eram criados se juntavam em uma mesma &lt;code&gt;network&lt;/code&gt; com nome &lt;code&gt;default&lt;/code&gt;. Na versão &lt;code&gt;3.x&lt;/code&gt; esse comportamento mudou, de modo que cada arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt; tem sua própria &lt;code&gt;network&lt;/code&gt;. O &lt;code&gt;docker-compose&lt;/code&gt; nomeia a &lt;code&gt;network&lt;/code&gt; do arquivo &lt;code&gt;docker-compose.yml&lt;/code&gt; utilizando o nome do diretório concatenado com a string &lt;code&gt;_default&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O tópico de &lt;code&gt;network&lt;/code&gt; do &lt;em&gt;Docker&lt;/em&gt; é muito extenso para esse artigo, então vou deixar ele para um post dedicado. O que você precisa saber aqui é que na versão &lt;code&gt;3.x&lt;/code&gt; do &lt;code&gt;docker-compose&lt;/code&gt; a &lt;code&gt;network&lt;/code&gt; é definida por arquivos &lt;code&gt;docker-compose.yml&lt;/code&gt; e um container de fora desse arquivo, por padrão, não se comunica com os que estão definidos nele. É possível conectá-lo à &lt;code&gt;network&lt;/code&gt;, mas não está no escopo deste artigo.&lt;/p&gt;

&lt;p&gt;Enfim, todos os nossos containers fazem parte da mesma &lt;code&gt;network&lt;/code&gt; e por isso a comunicação entre eles é muito fácil. O &lt;em&gt;Docker&lt;/em&gt; facilita nossa vida fornecendo um "DNS" para os containers da mesma rede. Vamos utilizar o container do Postgres como exemplo. Para a nossa aplicação usar o container do postgres, tudo o que precisamos fazer é colocar o &lt;strong&gt;nome do container no host do nosso banco de dados na aplicação&lt;/strong&gt;. Simples assim!&lt;/p&gt;

&lt;p&gt;Não se esqueça que outros parâmetros de rede também são importantes. Certifique-se de que a porta correta esteja exposta (&lt;code&gt;expose&lt;/code&gt;) no container desejado e que o request está sendo enviado para aquela porta!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;center&gt;Conclusão&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Espero ter ajudado você na compreensão dessa ótima ferramenta de desenvolvimento! Lidar com o &lt;em&gt;Docker&lt;/em&gt; pode ser complicado no começo, mas é uma excelente ferramenta para cuidar de um pedaço muito importante da aplicação que geralmente deixamos passar: &lt;strong&gt;A Infraestrutura!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Eu acho que o &lt;em&gt;Docker&lt;/em&gt; lida com esse lado de nosso trabalho de forma primorosa, possibilitando e facilitando muito do nosso dia-a-dia! Por isso, é uma ferramenta que vale muito a pena!&lt;/p&gt;

&lt;p&gt;Obrigado pelo seu tempo e até a próxima 🖖&lt;/p&gt;

</description>
      <category>docker</category>
      <category>beginners</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Implementando árvores em Elixir</title>
      <dc:creator>Vinicius Luiz</dc:creator>
      <pubDate>Thu, 16 Apr 2020 14:48:33 +0000</pubDate>
      <link>https://dev.to/ingresse/implementando-arvores-em-elixir-1eha</link>
      <guid>https://dev.to/ingresse/implementando-arvores-em-elixir-1eha</guid>
      <description>&lt;h1&gt;
  
  
  Problema
&lt;/h1&gt;

&lt;p&gt;Com o aumento na demanda de requisições feitas para a API da &lt;a href="https://ingresse.com"&gt;Ingresse&lt;/a&gt; alguns processos se tornaram um tipo de &lt;em&gt;gargalo&lt;/em&gt;. O exemplo que usarei durante este artigo será o nosso processo de definir se a sessão (data/hora) de um evento está disponível para venda ou não.&lt;/p&gt;

&lt;p&gt;Cada requisição feita pelo usuário a nossa API faz uma grande quantidade de buscas no nosso banco de dados e no Redis. São operações simples e que não deveriam ser muito custosas, porém são muitos dados que temos que buscar, e isso em grande escala de requests se torna bastante custoso.&lt;/p&gt;




&lt;h1&gt;
  
  
  Prova de conceito
&lt;/h1&gt;

&lt;p&gt;Desde o início dos estudos para completar esta tarefa de refatoração nós optamos por dividi-la em duas partes, sendo elas:&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Construir a árvore completa de um evento&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A ideia nesta etapa é fazer todo o processo de buscas necessárias nos bancos de dados, percorrer esses dados e construir a árvore que será consumida por outros processos.&lt;/p&gt;

&lt;p&gt;Aqui foram criados os dois principais &lt;em&gt;módulos&lt;/em&gt; (ou classes para quem estiver mais habituado com linguagens OOP) que são os que representam os nós e a árvore em si. Esses dois módulos são uma implementação simples de uma árvore e com eles nós conseguimos criá-la a partir de uma estrutura de &lt;strong&gt;evento&lt;/strong&gt; que é a entidade carregada do banco de dados com suas respectivas associações como sessões, grupo de ingressos e ingressos.&lt;/p&gt;

&lt;h6&gt;
  
  
  node.ex
&lt;/h6&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h6&gt;
  
  
  tree.ex
&lt;/h6&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;





&lt;p&gt;&lt;strong&gt;Calcular os status de sessões a partir de uma árvore já construída&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Esta etapa é a responsável por consumir uma árvore já criada e percorrer sobre os nós dela para calcular o status de cada um. Neste ponto nós usaremos a árvore criada pela etapa anterior a esta, assim, conseguiremos percorrer por todos os nós dentro da árvore utilizando o algoritmo &lt;a href="https://www.programiz.com/dsa/tree-traversal"&gt;Postorder Traversal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Para fazer os cálculos dos status nós decidimos utilizar pesos neles, o que significa que, cada status terá um peso de acordo com o tipo de status que ele é, com o intuito de podermos definir qual status é mais relevante comparado com outros.&lt;/p&gt;

&lt;p&gt;É importante deixar claro que nós temos dois grupos de status que são: Disponível e Indisponível.&lt;br&gt;
Dentro do grupo Indisponível nós temos outros tipos de status, que podem ser: sem estoque, vendas não iniciadas, encerrado, etc, e esses sim tem o peso mencionado acima.&lt;/p&gt;

&lt;p&gt;Nesta estapa também decidimos usar uma tabela &lt;a href="https://elixirschool.com/en/lessons/specifics/ets/"&gt;ETS&lt;/a&gt; para guardar o status de cada nó e dar como resposta para nosso cliente.&lt;/p&gt;


&lt;h6&gt;
  
  
  Recursive Traversal
&lt;/h6&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Depois de termos concluido essas duas etapas, começamos a pesquisar qual seria a melhor forma de construirmos a árvore e evitar ter que construí-la toda vez que alguém fizesse algum request para nosso serviço. Diante disto, pensamos em cachea-la no Redis como JSON, porém algumas árvores seriam muito grandes e parsear o JSON sempre seria algo custoso, depois de algumas pesquisas, achamos algo que poderia funcionar para a gente, em &lt;strong&gt;Elixir&lt;/strong&gt; podemos facilmente transformar uma struct em um binário usando a função &lt;code&gt;term_to_binary&lt;/code&gt; do &lt;strong&gt;Erlang&lt;/strong&gt;, e tendo esse binário podemos usar um algoritmo de hash, assim teremos a hash de uma estrutura válida para guardarmos em algum tipo de cache e então reconstruir a árvore sem executar muitos processos usando a função &lt;code&gt;binary_to_term&lt;/code&gt; do &lt;strong&gt;Erlang&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# iex&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="mi"&gt;55089&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;name:&lt;/span&gt;&lt;span class="mi"&gt;26190&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
       &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="mi"&gt;26230&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Teste arena alterado"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;term_to_binary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&amp;gt;&amp;gt;&lt;/span&gt;


&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;encode64&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="s2"&gt;"g3QAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNsAAAAAnQAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNsAAAAAXQAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNkAANuaWxkAARuYW1lYgAA1zFqZAAEbmFtZWIAAGZOdAAAAANkAApfX3N0cnVjdF9fZAAQRWxpeGlyLlRyZWUuTm9kZWQABmNoaWxkc2pkAARuYW1lYgAAZnZqZAAEbmFtZW0AAAAUVGVzdGUgYXJlbmEgYWx0ZXJhZG8="&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tendo esta hash, podemos voltar à estrutura usando o caminho inverso.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"g3QAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNsAAAAAnQAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNsAAAAAXQAAAADZAAKX19zdHJ1Y3RfX2QAEEVsaXhpci5UcmVlLk5vZGVkAAZjaGlsZHNkAANuaWxkAARuYW1lYgAA1zFqZAAEbmFtZWIAAGZOdAAAAANkAApfX3N0cnVjdF9fZAAQRWxpeGlyLlRyZWUuTm9kZWQABmNoaWxkc2pkAARuYW1lYgAAZnZqZAAEbmFtZW0AAAAUVGVzdGUgYXJlbmEgYWx0ZXJhZG8="&lt;/span&gt;

&lt;span class="n"&gt;decoded_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Base&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode64!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;131&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;69&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;114&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;111&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;104&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;105&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;115&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;108&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&amp;gt;&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;structure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:erlang&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;binary_to_term&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;decoded_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="mi"&gt;55089&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="ss"&gt;name:&lt;/span&gt;&lt;span class="mi"&gt;26190&lt;/span&gt;
     &lt;span class="p"&gt;},&lt;/span&gt;
     &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;Tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="ss"&gt;childs:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
       &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="mi"&gt;26230&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="s2"&gt;"Teste arena alterado"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Resultados Obtidos
&lt;/h1&gt;

&lt;p&gt;Aqui devemos considerar os seguintes atributos&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ips - iterations per second:&lt;/strong&gt; a quantidade de iterações que podemos executar a cada segundo.&lt;br&gt;
&lt;strong&gt;median:&lt;/strong&gt; a mediana dos tempos de execução calculada no benchmark&lt;/p&gt;

&lt;h3&gt;
  
  
  Events
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Id&lt;/th&gt;
&lt;th&gt;Session Qty.&lt;/th&gt;
&lt;th&gt;Groups Qty.&lt;/th&gt;
&lt;th&gt;Tickets Qty.&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;34392&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31627&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;746&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;34477&lt;/td&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;349&lt;/td&gt;
&lt;td&gt;361&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Queries
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.34392&lt;/td&gt;
&lt;td&gt;1.54&lt;/td&gt;
&lt;td&gt;648.62 ms&lt;/td&gt;
&lt;td&gt;±6.75%&lt;/td&gt;
&lt;td&gt;631.75 ms&lt;/td&gt;
&lt;td&gt;756.44 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.31627&lt;/td&gt;
&lt;td&gt;1.20&lt;/td&gt;
&lt;td&gt;833.57 ms&lt;/td&gt;
&lt;td&gt;±9.18%&lt;/td&gt;
&lt;td&gt;826.11 ms&lt;/td&gt;
&lt;td&gt;930.56 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.34477&lt;/td&gt;
&lt;td&gt;1.09&lt;/td&gt;
&lt;td&gt;913.59 ms&lt;/td&gt;
&lt;td&gt;±0.41%&lt;/td&gt;
&lt;td&gt;913.63 ms&lt;/td&gt;
&lt;td&gt;919.02 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.34392&lt;/td&gt;
&lt;td&gt;0.111 MB&lt;/td&gt;
&lt;td&gt;±0.09%&lt;/td&gt;
&lt;td&gt;0.111 MB&lt;/td&gt;
&lt;td&gt;0.111 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.31627&lt;/td&gt;
&lt;td&gt;1.08 MB&lt;/td&gt;
&lt;td&gt;±0.30%&lt;/td&gt;
&lt;td&gt;1.08 MB&lt;/td&gt;
&lt;td&gt;1.08 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;repo.by_id.34477&lt;/td&gt;
&lt;td&gt;3.76 MB&lt;/td&gt;
&lt;td&gt;±0.13%&lt;/td&gt;
&lt;td&gt;3.76 MB&lt;/td&gt;
&lt;td&gt;3.77 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Builds
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.34392&lt;/td&gt;
&lt;td&gt;215.20 K&lt;/td&gt;
&lt;td&gt;4.65 μs&lt;/td&gt;
&lt;td&gt;±425.27%&lt;/td&gt;
&lt;td&gt;3.46 μs&lt;/td&gt;
&lt;td&gt;19.62 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.31627&lt;/td&gt;
&lt;td&gt;5.94 K&lt;/td&gt;
&lt;td&gt;168.23 μs&lt;/td&gt;
&lt;td&gt;±60.08%&lt;/td&gt;
&lt;td&gt;137.62 μs&lt;/td&gt;
&lt;td&gt;654.07 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.34477&lt;/td&gt;
&lt;td&gt;1.98 K&lt;/td&gt;
&lt;td&gt;506.14 μs&lt;/td&gt;
&lt;td&gt;±59.40%&lt;/td&gt;
&lt;td&gt;392.54 μs&lt;/td&gt;
&lt;td&gt;1864.66 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.34392&lt;/td&gt;
&lt;td&gt;4.66 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.31627&lt;/td&gt;
&lt;td&gt;188.73 KB - 40.53x memory usage +184.08 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.build.34477&lt;/td&gt;
&lt;td&gt;429.12 KB - 92.16x memory usage +424.46 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Recursive Traversal
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.34392&lt;/td&gt;
&lt;td&gt;101.38 K&lt;/td&gt;
&lt;td&gt;9.86 μs&lt;/td&gt;
&lt;td&gt;±101.58%&lt;/td&gt;
&lt;td&gt;9.18 μs&lt;/td&gt;
&lt;td&gt;21.58 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.31627&lt;/td&gt;
&lt;td&gt;10.18 K&lt;/td&gt;
&lt;td&gt;98.19 μs&lt;/td&gt;
&lt;td&gt;±51.78%&lt;/td&gt;
&lt;td&gt;86.70 μs&lt;/td&gt;
&lt;td&gt;264.75 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.34477&lt;/td&gt;
&lt;td&gt;0.84 K&lt;/td&gt;
&lt;td&gt;1188.36 μs&lt;/td&gt;
&lt;td&gt;±3.93%&lt;/td&gt;
&lt;td&gt;1183.79 μs&lt;/td&gt;
&lt;td&gt;1387.74 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.34392&lt;/td&gt;
&lt;td&gt;6.18 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.31627&lt;/td&gt;
&lt;td&gt;43.16 KB - 6.98x memory usage +36.98 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;recursive.traversal.tree.34477&lt;/td&gt;
&lt;td&gt;1010.42 KB - 163.51x memory usage +1004.24 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Tree to binary
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.34392&lt;/td&gt;
&lt;td&gt;177.49 K&lt;/td&gt;
&lt;td&gt;5.63 μs&lt;/td&gt;
&lt;td&gt;±470.90%&lt;/td&gt;
&lt;td&gt;4.18 μs&lt;/td&gt;
&lt;td&gt;23.35 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.31627&lt;/td&gt;
&lt;td&gt;5.89 K&lt;/td&gt;
&lt;td&gt;169.79 μs&lt;/td&gt;
&lt;td&gt;±32.19%&lt;/td&gt;
&lt;td&gt;152.80 μs&lt;/td&gt;
&lt;td&gt;411.31 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.34477&lt;/td&gt;
&lt;td&gt;2.21 K&lt;/td&gt;
&lt;td&gt;451.81 μs&lt;/td&gt;
&lt;td&gt;±60.66%&lt;/td&gt;
&lt;td&gt;344.38 μs&lt;/td&gt;
&lt;td&gt;1628.34 μs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.34392&lt;/td&gt;
&lt;td&gt;48 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.31627&lt;/td&gt;
&lt;td&gt;48 B - 1.00x memory usage +0 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.to.binary.34477&lt;/td&gt;
&lt;td&gt;48 B - 1.00x memory usage +0 B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Binary to Hash
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.34392&lt;/td&gt;
&lt;td&gt;22191.97&lt;/td&gt;
&lt;td&gt;0.0451 ms&lt;/td&gt;
&lt;td&gt;±53.24%&lt;/td&gt;
&lt;td&gt;0.0379 ms&lt;/td&gt;
&lt;td&gt;0.132 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.31627&lt;/td&gt;
&lt;td&gt;475.17&lt;/td&gt;
&lt;td&gt;2.10 ms&lt;/td&gt;
&lt;td&gt;±34.34%&lt;/td&gt;
&lt;td&gt;1.83 ms&lt;/td&gt;
&lt;td&gt;4.86 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.34477&lt;/td&gt;
&lt;td&gt;298.97&lt;/td&gt;
&lt;td&gt;3.34 ms&lt;/td&gt;
&lt;td&gt;±27.40%&lt;/td&gt;
&lt;td&gt;3.02 ms&lt;/td&gt;
&lt;td&gt;6.71 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.34392&lt;/td&gt;
&lt;td&gt;304 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.31627&lt;/td&gt;
&lt;td&gt;376 B - 1.24x memory usage +72 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;binary.to.hash.34477&lt;/td&gt;
&lt;td&gt;376 B - 1.24x memory usage +72 B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Serialize
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Performance Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;ips&lt;/th&gt;
&lt;th&gt;average&lt;/th&gt;
&lt;th&gt;deviation&lt;/th&gt;
&lt;th&gt;median&lt;/th&gt;
&lt;th&gt;99th %&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.34392&lt;/td&gt;
&lt;td&gt;21510.67&lt;/td&gt;
&lt;td&gt;0.0465 ms&lt;/td&gt;
&lt;td&gt;±78.93%&lt;/td&gt;
&lt;td&gt;0.0374 ms&lt;/td&gt;
&lt;td&gt;0.149 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.31627&lt;/td&gt;
&lt;td&gt;520.52&lt;/td&gt;
&lt;td&gt;1.92 ms&lt;/td&gt;
&lt;td&gt;±33.44%&lt;/td&gt;
&lt;td&gt;1.69 ms&lt;/td&gt;
&lt;td&gt;4.42 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.34477&lt;/td&gt;
&lt;td&gt;280.24&lt;/td&gt;
&lt;td&gt;3.57 ms&lt;/td&gt;
&lt;td&gt;±30.92%&lt;/td&gt;
&lt;td&gt;3.13 ms&lt;/td&gt;
&lt;td&gt;7.16 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Memory Usage Statistics
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Memory usage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.34392&lt;/td&gt;
&lt;td&gt;424 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.31627&lt;/td&gt;
&lt;td&gt;424 B - 1.00x memory usage +0 B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tree.serialize.34477&lt;/td&gt;
&lt;td&gt;424 B - 1.00x memory usage +0 B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Com esses resultados temos apenas uma preocupação no momento que é a quantidade de memória utilizada no algoritmo &lt;code&gt;recursive traversal&lt;/code&gt;, por ser uma função recursiva nós já tinhamos em mente que ela usaria bastante memória e isso pode nos trazer problemas em um cenário de um evento gigante, o evento exemplo &lt;code&gt;34477&lt;/code&gt; já é um evento considerado grande para nós devido a quantidade de ingressos e sessões que ele possui. Talvez iremos procurar resoluções para esse possível problema e acredito que se conseguirmos achar algo iremos trazer em um futuro post.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;No final dessa POC conseguimos comprovar que nós conseguimos ter o mesmo cálculo que temos hoje, porém utilizando a estrutura de árvore que montamos para esse caso que se provou muito mais eficiente que o que temos hoje, pois os resultados que tivemos se provaram muito eficientes para diversos casos que temos hoje em nosso sistema.&lt;/p&gt;




&lt;p&gt;Agradecimentos especiais ao &lt;a href="https://github.com/arthurmartins"&gt;Arthur&lt;/a&gt; por me orientar e acompanhar durante o processo de desenvolvimento! &lt;/p&gt;

&lt;p&gt;Espero que gostem do post.&lt;/p&gt;

&lt;p&gt;Até uma próxima!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ingresse</category>
      <category>ptbr</category>
      <category>datastructures</category>
    </item>
    <item>
      <title>GitHub Actions - Elixir</title>
      <dc:creator>Vitor Leal</dc:creator>
      <pubDate>Tue, 07 Apr 2020 01:55:45 +0000</pubDate>
      <link>https://dev.to/ingresse/github-actions-elixir-2351</link>
      <guid>https://dev.to/ingresse/github-actions-elixir-2351</guid>
      <description>&lt;p&gt;O &lt;a href="https://github.com/features/actions"&gt;Actions&lt;/a&gt; é uma ferramenta integrada aos seus repositórios do GitHub para automatizar os seus &lt;code&gt;workflows&lt;/code&gt; de CI/CD (&lt;em&gt;continuous delivery&lt;/em&gt; / &lt;em&gt;continuous deploy&lt;/em&gt;). Você consegue rodar esses &lt;code&gt;workflows&lt;/code&gt; baseado em diversos eventos do GitHub, como um novo &lt;em&gt;push&lt;/em&gt; em uma &lt;em&gt;branch&lt;/em&gt; a criação de uma nova &lt;em&gt;issue&lt;/em&gt; ou uma nova &lt;em&gt;release&lt;/em&gt; publicada.&lt;/p&gt;

&lt;h1&gt;
  
  
  Contexto
&lt;/h1&gt;

&lt;p&gt;Desde que o GitHub lançou a versão beta do &lt;a href="https://github.com/features/actions"&gt;Actions&lt;/a&gt;, a &lt;a href="https://www.ingresse.com/"&gt;Ingresse&lt;/a&gt; vem a testando. No final do ano passado o Actions saiu da versão beta e a gente decidiu finalmente migrar nossos &lt;em&gt;workflows&lt;/em&gt; para lá.&lt;/p&gt;

&lt;p&gt;Já que &lt;code&gt;Elixir&lt;/code&gt; é a nossa &lt;a href="https://dev.to/ingresse/adotando-o-elixir-na-ingresse-362m"&gt;linguagem principal&lt;/a&gt; na Ingresse, começamos a migrar primeiro os &lt;em&gt;workflows&lt;/em&gt; dos serviços em &lt;code&gt;Elixir&lt;/code&gt; para o Actions e aqui tem algumas dicas de como a gente faz.&lt;/p&gt;

&lt;h1&gt;
  
  
  Básico
&lt;/h1&gt;




&lt;p&gt;Antes de tudo vou apresentar um pouco do básico do &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;, se você já tem familiaridade pode seguir passar direto essa seção.&lt;/p&gt;




&lt;p&gt;O Actions vai ler os arquivos &lt;code&gt;.yml&lt;/code&gt; ou &lt;code&gt;.yaml&lt;/code&gt; dentro da pasta &lt;code&gt;.github/workflows&lt;/code&gt; na raiz do seu projeto.&lt;/p&gt;

&lt;p&gt;Primeiro vamos criar a pasta &lt;code&gt;.github&lt;/code&gt; com a pasta &lt;code&gt;workflows&lt;/code&gt; dentro:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p .github/workflows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos criar um arquivo que a gente pode chamar de &lt;code&gt;ci.yml&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;touch .github/workflows/ci.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora vamos adicionar o seguinte conteúdo nele:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Meu Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos aos detalhes do conteúdo desse arquivo.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;name&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;O nome do seu &lt;em&gt;workflow&lt;/em&gt;. É um campo opcional.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;on&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;O nome do evento do GitHub que vai iniciar esse workflow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pode ser um evento apenas:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Vai rodar sempre que alguém realizar um push no repositório&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Pode ser uma lista de eventos:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Vai rodar sempre que alguém realizar um push no repositório&lt;/span&gt;
&lt;span class="c1"&gt;# e quando for criado um novo pull request&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Pode ser customizado por evento:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Vai rodar sempre que um pull request for criado&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Mas quando estiver apontando para a master&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;master&lt;/span&gt;

  &lt;span class="c1"&gt;# Vai rodar sempre que uma release for criada&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Mas se ela estiver com o status de publicada&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;published&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;code&gt;jobs&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Um &lt;em&gt;workflow&lt;/em&gt; pode ter um ou mais &lt;em&gt;jobs&lt;/em&gt;. Por padrão, múltiplos jobs rodam em paralelo.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;jobs.&amp;lt;id-do-job&amp;gt;.run-on&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Em que tipo de máquina o &lt;em&gt;job&lt;/em&gt; vai ser executado.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pode ser em um tipo de máquina:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Podem ser em múltiplos tipos de máquinas, incluindo &lt;code&gt;ubuntu&lt;/code&gt;, &lt;code&gt;macos&lt;/code&gt; e &lt;code&gt;windows&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matrix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;platform&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;macos-latest&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;windows-latest&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ matrix.platform }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;code&gt;jobs.&amp;lt;id-do-job&amp;gt;.steps&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Um &lt;em&gt;job&lt;/em&gt; pode ter uma ou mais tarefas que vão ser executadas. Uma tarefa pode executar comandos, rodar setups ou rodar outras actions. O próprio GitHub tem uma série de actions publicadas que facilitam muitos trabalhos. Nesse exemplo estamos usando a action &lt;code&gt;actions/checkout&lt;/code&gt; na versão &lt;code&gt;v1&lt;/code&gt; para clonar o repositório do projeto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Primeira tarefa a ser executada vai ser clonar o repositório&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Próximos passos
&lt;/h1&gt;

&lt;p&gt;Bom agora que a gente já sabe um pouco mais sobe a estrutura básica de um &lt;em&gt;workflow&lt;/em&gt; do GitHub Actions vamos começar a moldar ele para executar por exemplo uma tarefa de &lt;code&gt;mix format&lt;/code&gt; e uma tarefa de &lt;code&gt;mix test&lt;/code&gt; em um projeto &lt;code&gt;Elixir&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Para evitar ter que instalar o &lt;code&gt;Elixir&lt;/code&gt; no processo de build, vamos utilizar o atributo &lt;code&gt;container&lt;/code&gt; para baixar uma imagem Docker já existente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Meu Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;jobs.&amp;lt;id-do-job&amp;gt;.container&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Em qual imagem Docker vai rodar as tarefas desse &lt;em&gt;job&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Agora que nosso ambiente já tem &lt;code&gt;Elixir&lt;/code&gt;, podemos criar as tarefas para executar o &lt;code&gt;mix format&lt;/code&gt; e &lt;code&gt;mix test&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Meu Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Formatar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix format --check-formatted&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Instalar as dependências&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix deps.get&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Testar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pronto já temos um &lt;em&gt;workflow&lt;/em&gt; que clona nosso repositório, verifica se nosso código está formatado de acordo com as configurações do projeto, instala as dependências e roda nossos testes.&lt;/p&gt;




&lt;h1&gt;
  
  
  Utilizando serviços
&lt;/h1&gt;

&lt;p&gt;O cenário anterior funciona perfeitamente para quando a gente tem um &lt;code&gt;lib&lt;/code&gt; escrita em &lt;code&gt;Elixir&lt;/code&gt;, mas para casos que a gente esteja trabalhando em um projeto com &lt;a href="https://www.phoenixframework.org/"&gt;Phoenix&lt;/a&gt; por exemplo, a gente vai precisar provavelmente conectar em um banco de dados para poder executar alguns testes.&lt;/p&gt;

&lt;p&gt;Nesse momento a gente consegue utilizar os &lt;em&gt;services&lt;/em&gt; para criar containers de um banco de dados &lt;a href="https://www.postgresql.org/"&gt;Postgres&lt;/a&gt;, por exemplo, para que os nossos &lt;em&gt;jobs&lt;/em&gt; possam ter onde se conectar.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;jobs.&amp;lt;id-do-job&amp;gt;.services&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;

    &lt;span class="c1"&gt;# Mapeia a porta 5432 no container Docker para a porta 5432 no container do Postgres&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5432:5432&lt;/span&gt;

    &lt;span class="c1"&gt;# Configura os dados de acesso ao banco de teste&lt;/span&gt;
    &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;usuario&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;senha&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;banco&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora que o nosso &lt;em&gt;workflow&lt;/em&gt; vai criar o banco de dados pra gente poder conectar, tem um detalhe que temos que alterar nas nossas tarefas que vão rodar para conectar nesse banco. No caso, a nossa tarefa &lt;code&gt;mix test&lt;/code&gt; tem que receber uma variável de ambiente para poder conectar corretamente no banco criado pelo Actions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Testar&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix test&lt;/span&gt;
   &lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
     &lt;span class="na"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
     &lt;span class="na"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$❴❴ job.services.postgres.ports[5672] ❵❵&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O exemplo completo fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Meu Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;elixir:1.10&lt;/span&gt;

    &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;

        &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5432:5432&lt;/span&gt;

        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;usuario&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;senha&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;banco&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Formatar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix format --check-formatted&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Instalar as dependências&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix deps.get&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Testar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix test&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
          &lt;span class="na"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$❴❴ job.services.postgres.ports[5432] ❵❵&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora basta alterar as configurações da nosso ambiente de teste para receber utilizar as variáveis de ambiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Config&lt;/span&gt;

&lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="ss"&gt;:meu_app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Meu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;adapter:&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Adapters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Postgres&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;username:&lt;/span&gt; &lt;span class="s2"&gt;"usuario"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;password:&lt;/span&gt; &lt;span class="s2"&gt;"senha"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;database:&lt;/span&gt; &lt;span class="s2"&gt;"banco"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;port:&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"POSTGRES_PORT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"5432"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="ss"&gt;hostname:&lt;/span&gt; &lt;span class="no"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"POSTGRES_HOST"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="ss"&gt;pool:&lt;/span&gt; &lt;span class="no"&gt;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Adapters&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;SQL&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Sandbox&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Docker Compose
&lt;/h1&gt;

&lt;p&gt;Se você já utiliza &lt;a href="https://docs.docker.com/compose/"&gt;Docker Compose&lt;/a&gt; nos seus projetos você não precisa criar os &lt;code&gt;services&lt;/code&gt; no arquivo do Actions e pode criar esses serviços direto no seu arquivo do Docker Compose de teste.&lt;/p&gt;

&lt;p&gt;Exemplo do arquivo &lt;code&gt;docker-compose-test.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.3"&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;meu_servico&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;meu_postgres&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000:4000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MIX_ENV=test&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mix phx.server&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;meu_postgres&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=banco&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=usuario&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=senha&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5433:5432"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para rodar os testes com o Docker Compose, o ideal é mudar a imagem que roda no Actions para uma imagem que tenha já tenha o &lt;code&gt;compose&lt;/code&gt; instalado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/compose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O exemplo completo fica assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Meu Workflow&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/compose&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v1&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Formatar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose -f docker-compose-test.yml run meu_servico mix format --check-formatted&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Testar&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker-compose -f docker-compose-test.yml run meu_servico mix test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Espero que tenha ajudado vocês a entender um pouco melhor como rodar projetos &lt;code&gt;Elixir&lt;/code&gt; no GitHub Actions. &lt;/p&gt;

&lt;p&gt;Até a próxima!&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ci</category>
      <category>cd</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Adotando o Elixir na Ingresse</title>
      <dc:creator>Vitor Leal</dc:creator>
      <pubDate>Fri, 06 Mar 2020 20:26:57 +0000</pubDate>
      <link>https://dev.to/ingresse/adotando-o-elixir-na-ingresse-362m</link>
      <guid>https://dev.to/ingresse/adotando-o-elixir-na-ingresse-362m</guid>
      <description>&lt;p&gt;Com o crescimento acelerado da &lt;a href="https://www.ingresse.com/"&gt;Ingresse&lt;/a&gt; nos últimos anos, tivemos que reformular nossa arquitetura e infraestrutura inicial para poder escalar com essa demanda.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://www.ingresse.com/"&gt;Ingresse&lt;/a&gt; nasceu com uma base em &lt;code&gt;PHP&lt;/code&gt;, um &lt;a href="https://pt.wikipedia.org/wiki/Aplica%C3%A7%C3%A3o_monol%C3%ADtica"&gt;Monolito&lt;/a&gt; que atendeu bem o MVP e os primeiros anos do produto, mas com o passar do tempo acabou dificultando a evolução dele.&lt;/p&gt;

&lt;p&gt;No processo de reformulação da arquitetura em 2016 nasceram os primeiros serviços em &lt;code&gt;Python&lt;/code&gt; que resolveram bem os problemas para qual a linguagem foi escolhida. No início de 2017 quando estávamos com uma &lt;em&gt;stack&lt;/em&gt; com um misto de &lt;code&gt;PHP&lt;/code&gt; e &lt;code&gt;Python&lt;/code&gt; começamos a olhar para outras linguagens que nos ajudasse a escalar e aproveitar melhor todos os recursos disponíveis da nossa infra. Mas para essa linguagem a gente tinha um foco muito importante, ela tinha que ser &lt;em&gt;developer friendly&lt;/em&gt;, estávamos buscando uma linguagem que nos ajudasse na escalabilidade e performance mas principalmente na produtividade do nosso time.&lt;/p&gt;

&lt;h1&gt;
  
  
  Prova de conceito
&lt;/h1&gt;

&lt;p&gt;Para começar fizemos uma prova de conceito de um &lt;a href="https://www.redhat.com/pt-br/topics/microservices/what-are-microservices"&gt;microserviço&lt;/a&gt; novo implementando poucas &lt;em&gt;features&lt;/em&gt;, mas desenvolvendo as mesmas &lt;em&gt;features&lt;/em&gt; utilizando duas das linguagens que estávamos analisando. A idéia não era comparar só a performance do serviço entre essas duas linguagens, mas também, como é o dia a dia desenvolvendo com essas linguagens.&lt;/p&gt;

&lt;h1&gt;
  
  
  Escolhendo o Elixir
&lt;/h1&gt;

&lt;p&gt;Uma das linguagens escolhidas para o teste foi o &lt;a href="https://elixir-lang.org/"&gt;Elixir&lt;/a&gt;. Uma linguagem &lt;em&gt;open source&lt;/em&gt; criada pelo José Valim na Plataformatec, empresa recentemente adquirida pelo Nubank.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;Elixir&lt;/code&gt; é uma linguagem moderna que executa na Máquina Virtual &lt;a href="https://www.erlang.org/"&gt;Erlang&lt;/a&gt; (BEAM), conhecida por executar sistemas de baixa latência, distribuídos e tolerantes a falhas.&lt;/p&gt;

&lt;p&gt;Além disso tem uma comunidade muito ativa e frameworks para desenvolvimento web como o &lt;a href="https://www.phoenixframework.org/"&gt;Phoenix&lt;/a&gt; que tem foco em criar uma estrutura produtiva que não compromete a velocidade de desenvolvimento nem a manutenção.&lt;/p&gt;

&lt;p&gt;Alguns pontos altos do &lt;code&gt;Elixir&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Instalação simples
&lt;/h4&gt;

&lt;p&gt;A instalação do &lt;code&gt;Elixir&lt;/code&gt; é muito simples, tem instalador para &lt;a href="https://elixir-lang.org/install.html#unix-and-unix-like"&gt;Linux&lt;/a&gt;, &lt;a href="https://elixir-lang.org/install.html#macos"&gt;Mac&lt;/a&gt;, &lt;a href="https://elixir-lang.org/install.html#windows"&gt;Windows&lt;/a&gt; e para quem prefere container como eu, imagens &lt;a href="https://elixir-lang.org/install.html#docker"&gt;Docker&lt;/a&gt; para não sujar seu ambiente.&lt;/p&gt;

&lt;h4&gt;
  
  
  Documentação e conteúdo
&lt;/h4&gt;

&lt;p&gt;A &lt;a href="https://hexdocs.pm/elixir/Kernel.html"&gt;documentação&lt;/a&gt; é bem completa e fácil de navegar. O &lt;a href="https://elixir-lang.org/learning.html"&gt;site&lt;/a&gt; da linguagem aponta diversos materiais de leitura, cursos e &lt;em&gt;screencasts&lt;/em&gt; para quem quer começar. Tem muito material gerado pela comunidade, tanto aqui no &lt;a href="https://dev.to/search?q=elixir"&gt;Dev.to&lt;/a&gt; quanto no &lt;a href="https://medium.com/search?q=elixir"&gt;Medium&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Um ótimo lugar para iniciar com conteúdo em português é o &lt;a href="https://elixirschool.com/pt/"&gt;ElixirSchool&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Gerenciador de pacotes
&lt;/h4&gt;

&lt;p&gt;Uma coisa que a gente espera em todas as linguagens modernas é um gerenciador de pacotes decente. E esse é o caso do &lt;a href="https://hex.pm/"&gt;Hex&lt;/a&gt;, um gerenciador de pacotes para as linguagens que compilam para rodar na Maquina Virtual do Erlang (BEAM).&lt;/p&gt;

&lt;h4&gt;
  
  
  Ferramenta de &lt;em&gt;build&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;O &lt;a href="https://hexdocs.pm/mix/Mix.html"&gt;Mix&lt;/a&gt; é uma ferramenta de &lt;em&gt;build&lt;/em&gt; que fornece &lt;em&gt;tasks&lt;/em&gt; para criar, compilar e testar projetos &lt;code&gt;Elixir&lt;/code&gt;, gerenciar suas dependências e muito mais. É uma ferramenta que facilita o dia a dia no desenvolvimento e nos processos de automatização.&lt;/p&gt;

&lt;h4&gt;
  
  
  Testes
&lt;/h4&gt;

&lt;p&gt;O &lt;a href="https://hexdocs.pm/ex_unit/ExUnit.html"&gt;ExUnit&lt;/a&gt; é um framework completo para testes no &lt;code&gt;Elixir&lt;/code&gt;. Totalmente integrado para ser executado com um simples &lt;code&gt;mix test&lt;/code&gt; e com capacidade de rodar os testes de forma assíncrona.&lt;/p&gt;

&lt;h4&gt;
  
  
  Produtividade
&lt;/h4&gt;

&lt;p&gt;A velocidade de desenvolvimento no &lt;code&gt;Elixir&lt;/code&gt; é muito boa. Tem um &lt;em&gt;syntax&lt;/em&gt; que é fácil escrever um código limpo e compreensível sem sacrificar a produtividade de um desenvolvedor.&lt;/p&gt;

&lt;h1&gt;
  
  
  Processo de mudança
&lt;/h1&gt;

&lt;p&gt;Hoje ainda temos microserviços em outras linguagens rodando em produção, simplesmente porque estão dando conta do recado. Já até pensamos em migrar alguns mas se ainda estão funcionando bem não tem porque mexer.&lt;/p&gt;

&lt;p&gt;Com o tempo o nosso time foi pegando pequenas tarefas para executar em &lt;code&gt;Elixir&lt;/code&gt; até sentirem que tinham o domínio na linguagem para poder dar manutenção e criar novos microserviços do zero. A troca de conhecimento entre as equipes é essencial para que esse tipo de mudança tenha sucesso.&lt;/p&gt;

&lt;p&gt;Com certeza não é um processo rápido adotar uma nova linguagem em produção, quando se tem uma quantidade enorme de acessos, mas acredito que os benefícios de ter uma linguagem moderna com um grande foco no desenvolvedor e na sua produtividade é um grande diferencial para a equipe e para o futuro da empresa.&lt;/p&gt;

&lt;p&gt;Um dos nossos desenvolvedores Backend escreveu um &lt;a href="https://dev.to/leonimella/entendendo-elixir-com-ajuda-de-php-20n2"&gt;post&lt;/a&gt; sobre &lt;code&gt;Elixir&lt;/code&gt;, com uma visão de quem veio do &lt;code&gt;PHP&lt;/code&gt;. Muito útil pra quem está tendo seu primeiro contato com a linguagem e com o paradigma funcional.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Essa prova de conceito hoje se tornou um dos nossos principais serviços e está em produção desde o final de 2017.&lt;/p&gt;

&lt;p&gt;Ele é responsável por transacionar &lt;strong&gt;centenas de milhões de Reais&lt;/strong&gt; em ingressos todo ano, não só na &lt;a href="https://www.ingresse.com/"&gt;Ingresse&lt;/a&gt; mas em outras "tiqueteiras" do mercado que utilizam nossas API's. É um &lt;em&gt;Gateway&lt;/em&gt; de pagamentos, com múltiplos adquirentes e plataformas de pagamento integradas como &lt;code&gt;Cielo&lt;/code&gt;, &lt;code&gt;Stone&lt;/code&gt;, &lt;code&gt;Getnet&lt;/code&gt;, &lt;code&gt;PicPay&lt;/code&gt;, &lt;code&gt;StarkBank&lt;/code&gt;, &lt;code&gt;Iugu&lt;/code&gt; e &lt;code&gt;PayPal&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Hoje todos os nossos serviços novos são desenvolvidos em &lt;code&gt;Elixir&lt;/code&gt;. Até agora temos &lt;strong&gt;5&lt;/strong&gt; deles em produção e no momento mais &lt;strong&gt;3&lt;/strong&gt; sendo desenvolvidos em 2020.&lt;/p&gt;

&lt;p&gt;Se já trabalha com &lt;code&gt;Elixir&lt;/code&gt; ou estiver querendo aprender estamos sempre com &lt;a href="https://sobre.ingresse.com/vagas"&gt;vagas abertas&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>ingresse</category>
      <category>ptbr</category>
    </item>
    <item>
      <title>Learning Elixir with PHP help</title>
      <dc:creator>Leoni Mella</dc:creator>
      <pubDate>Tue, 18 Feb 2020 12:00:24 +0000</pubDate>
      <link>https://dev.to/ingresse/learning-elixir-with-php-help-47mn</link>
      <guid>https://dev.to/ingresse/learning-elixir-with-php-help-47mn</guid>
      <description>&lt;p&gt;🇧🇷 &lt;em&gt;Artigo original em português: &lt;a href="https://dev.to/leonimella/entendendo-elixir-com-ajuda-de-php-20n2"&gt;Entendendo Elixir com a ajuda de PHP&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After some years and differents experiences with PHP and some frameworks like WordPress, Laravel, Symfony and Phalcon, I had the opportunity to work with Elixir and since then it has been my go to language for new projects.&lt;/p&gt;

&lt;p&gt;For those who have never had a previous experience with a functional language this first contact could be a little confusing, that was my case when I first start with Elixir.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "help" offered in this article by PHP it's just a merely comparison made between the two languages, which by the way are NOTHING similar.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article I've just implemented the same functionalities using both languages so you can compare the &lt;strong&gt;logic&lt;/strong&gt; of a new programming paradigm with a more familiar one offered by PHP.&lt;/p&gt;

&lt;p&gt;I will approach the Elixir functionalities that I most use on a daily basis applying the 80/20 rule, but I'm sure that with this simple knowledge you can read a &lt;code&gt;.ex&lt;/code&gt; or &lt;code&gt;.exs&lt;/code&gt; file and don't lose yourself on the way.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before we begin...
&lt;/h4&gt;

&lt;p&gt;If you don't know Elixir at all I suggest that you read at least the &lt;a href="https://elixir-lang.org/getting-started/introduction.html"&gt;&lt;em&gt;Starting Guide&lt;/em&gt;&lt;/a&gt; on their docs. It will show the syntax, the primitives types and operators of the language.&lt;/p&gt;

&lt;p&gt;Without further ado, let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Pattern Matching&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;The best &lt;em&gt;pattern matching&lt;/em&gt; definition is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pattern matching is a powerful part of Elixir. It allows us to match simple values, data structures, and even functions - &lt;a href="https://elixirschool.com/en/lessons/basics/pattern-matching/"&gt;Elixir School&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But what exactly does this mean? To better understand this we need to take a look at the &lt;em&gt;match operator&lt;/em&gt; &lt;code&gt;=&lt;/code&gt;. This operator can attribute values to variables and can be used to decompose more complex structures, like tuples and lists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;a, b, c&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; a
&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;3&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; b
&lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;4&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; c
&lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;

&lt;span class="c"&gt;# Another example&lt;/span&gt;
iex&lt;span class="o"&gt;(&lt;/span&gt;5&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;_, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, country&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;6&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; country
&lt;span class="s2"&gt;"Chile"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, you can fetch the first item of a list&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Olá"&lt;/span&gt;, &lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Olá"&lt;/span&gt;, &lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;span class="s2"&gt;"Olá"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;3&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tail&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Case a tuple can't be match against the left hand side of the operator, that means, maybe a tuple don't have the same number of fields or the same expected value of the left side of the &lt;code&gt;=&lt;/code&gt; a exception will occur:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;a, b&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# ** (MatchError) no match of right hand side value: {"São Paulo", "Rio de Janeiro", "Fortaleza"}&lt;/span&gt;
&lt;span class="c"&gt;#    (stdlib) erl_eval.erl:453: :erl_eval.expr/5&lt;/span&gt;
&lt;span class="c"&gt;#    ...&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;_, &lt;span class="s2"&gt;"United States"&lt;/span&gt;, country&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# ** (MatchError) no match of right hand side value: {"Brasil", "Ecuador", "Chile"}&lt;/span&gt;
&lt;span class="c"&gt;#    (stdlib) erl_eval.erl:453: :erl_eval.expr/5&lt;/span&gt;
&lt;span class="c"&gt;#    ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code gave us an understanding of the first half of the &lt;em&gt;pattern matching&lt;/em&gt; definition. What about the other half that allow us to look for patterns in functions definitions? Let's take a look:&lt;/p&gt;

&lt;p&gt;To help with this part I'll create a PHP class so you can compare with the equivalent Elixir module. To start with let's just create a class and module that have a &lt;code&gt;hello/1&lt;/code&gt; function that receive the &lt;code&gt;user_name&lt;/code&gt; as parameter.&lt;/p&gt;

&lt;p&gt;PHP class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Elixir module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, so good, right? We have a &lt;code&gt;hello/1&lt;/code&gt; function that will print "Hello, Joe" both in PHP class and in Elixir module.&lt;/p&gt;

&lt;p&gt;But let's assume that the &lt;code&gt;user_name&lt;/code&gt; parameter could be &lt;code&gt;nil&lt;/code&gt; (&lt;code&gt;null&lt;/code&gt; in PHP). How can we adjust our code to attend this requirement?&lt;/p&gt;

&lt;p&gt;PHP class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using PHP we could add a default value to the &lt;code&gt;$userName&lt;/code&gt; and handle this with a &lt;code&gt;if&lt;/code&gt; statement inside our function in case &lt;code&gt;$userName&lt;/code&gt; is really &lt;code&gt;null&lt;/code&gt; and display a different message.&lt;/p&gt;

&lt;p&gt;If execute &lt;code&gt;GreetUser.php&lt;/code&gt; we would get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s2"&gt;"Hello, Joe"&lt;/span&gt;
&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the same solution is possible in Elixir, we can use &lt;em&gt;pattern matching&lt;/em&gt; and remove the complexity of the code from our function by get rid of the &lt;code&gt;if&lt;/code&gt; statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As there are two functions with the same name, the chosen one will be the one that has the correct parameter value.&lt;/p&gt;

&lt;p&gt;This means that only when &lt;code&gt;user_name = nil&lt;/code&gt; the first function will be executed, in any other case it will skip this function definition and go to the next &lt;code&gt;hello/1&lt;/code&gt; declared within this module.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It's important to say that due to function arity &lt;code&gt;GreetUser.hello(nil)&lt;/code&gt; is different then &lt;code&gt;GreetUser.hello()&lt;/code&gt;. In the former we would call &lt;code&gt;hello/1&lt;/code&gt; and the last we would call &lt;code&gt;hello/0&lt;/code&gt; which does not exists and would break. &lt;strong&gt;Always have the arity in mind&lt;/strong&gt;!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Any primitive of the language can be used in &lt;em&gt;pattern matching&lt;/em&gt;. So let's assume that the &lt;code&gt;GreetUser&lt;/code&gt; module now have to greet a specific message to users that have the name &lt;code&gt;"Jane"&lt;/code&gt;, we could achieve this by doing this:&lt;/p&gt;

&lt;p&gt;PHP Class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Nice to see you, Jane!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Elixir Module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nice to see you, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time we specified the &lt;code&gt;user_name&lt;/code&gt; value and add the &lt;em&gt;match operator&lt;/em&gt; to the parameter: &lt;code&gt;("Jane" = user_name)&lt;/code&gt;. By doing this we are matching &lt;code&gt;user_name&lt;/code&gt; to &lt;code&gt;"Jane"&lt;/code&gt; and them we can use the variable inside our function. If you don't want to use the parameter inside your function you can dismiss it by prepending it with an &lt;em&gt;underscore&lt;/em&gt;: &lt;code&gt;("Jane" = _user_name)&lt;/code&gt;. Elixir understand that this variable will never be used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Declared variables that are not used will raise a warning in compilation time, keep that in mind!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I hope that with this example you began to see how &lt;em&gt;pattern matching&lt;/em&gt; can remove complexity away from our code. Doesn't Elixir module look more simple and better to read than the class in PHP? We no longer have to "calculate" &lt;code&gt;if&lt;/code&gt;s statement to know what a function will return, pretty good, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Guards&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;If you enjoy the wonders of &lt;em&gt;pattern matching&lt;/em&gt; you can go beyond using &lt;em&gt;guards&lt;/em&gt;. It will allow you to make more complex parameter validation in your functions declaration.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Guards&lt;/em&gt; are defined using a &lt;code&gt;when&lt;/code&gt; after a function declaration. While &lt;em&gt;pattern matching&lt;/em&gt; is useful to check explicit values, with &lt;em&gt;guards&lt;/em&gt; we can apply some boolean logic to it. We can check a parameter's type, length, if it is &lt;code&gt;nil&lt;/code&gt;, if it is higher or lower given a determined number and some others validations.&lt;/p&gt;

&lt;p&gt;Back to our &lt;code&gt;GreetUser&lt;/code&gt;, we will use &lt;em&gt;guard&lt;/em&gt; to validate if &lt;code&gt;user_name&lt;/code&gt; is a &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Elixir module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;is_binary/1&lt;/code&gt; function will return a boolean value and according to it (&lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt;) &lt;code&gt;hello/1&lt;/code&gt; get invoked or not. Elixir has several &lt;a href="https://hexdocs.pm/elixir/Kernel.html#is_atom/1"&gt;type-checks&lt;/a&gt;” functions like this so you can check a expression type.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here is a tip. Either using a &lt;em&gt;pattern matching&lt;/em&gt; or &lt;em&gt;guard&lt;/em&gt; it's always a good practice to at least think about a alternative in case of a parameter mismatch. You could get a runtime error if a parameter won't match a function&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;** (FunctionClauseError) no function clause matching in GreetUser.hello/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above error will happen if we call &lt;code&gt;hello/1&lt;/code&gt; with an integer: &lt;code&gt;GreetUser.hello(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As an alternative we could add another declaration of &lt;code&gt;hello/1&lt;/code&gt; just dismissing the parameter, so everything that is not a &lt;code&gt;string&lt;/code&gt; will be direct to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only string is allowed in this function"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Important!
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;The function declaration order is extremely important!!&lt;/strong&gt;&lt;br&gt;
In the above example we restrict &lt;code&gt;hello/1&lt;/code&gt; to only accept &lt;code&gt;string&lt;/code&gt;. No problem there, but what if we had reversed the function declaration orders by placing &lt;code&gt;hello(_)&lt;/code&gt; before the &lt;code&gt;hello(user_name) when is_binary(user_name)&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only string is allowed in this function"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the code we would get the following:&lt;br&gt;
    warning: this clause cannot match because a previous clause at line 5 always matches&lt;/p&gt;

&lt;p&gt;Our code still run with no errors, but &lt;code&gt;hello/1&lt;/code&gt; with the &lt;em&gt;guard&lt;/em&gt; &lt;code&gt;when is_binary/1&lt;/code&gt; would never be called because &lt;code&gt;hello/1&lt;/code&gt; without the guard will &lt;strong&gt;ALWAYS&lt;/strong&gt; be evaluated first! &lt;strong&gt;So pay attention to function's declaration order&lt;/strong&gt;!!&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;center&gt;Pipe Operator&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;This one is a bit trick, but in a nutshell the &lt;em&gt;pipe operator&lt;/em&gt; is represented by the symbol &lt;code&gt;|&amp;gt;&lt;/code&gt; and all that it does is pass an expression evaluation (or result) as the first parameter to the next one.&lt;/p&gt;

&lt;p&gt;With this you can create a function &lt;em&gt;pipeline&lt;/em&gt; (get the name?) given a expression (variable or function).&lt;/p&gt;

&lt;p&gt;To illustrate this concept, now &lt;code&gt;GreetUser&lt;/code&gt; has a new requirement, we'll need to greet some users which their names will came in a list. To do that we'll create another function named &lt;code&gt;hello_group/1&lt;/code&gt;. This new function will receive the list of names as &lt;code&gt;users_name&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;# code&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We declared the function and added a &lt;em&gt;guard&lt;/em&gt; so we can validate that the parameter is indeed a list, and defined a "default" &lt;code&gt;hello_group/1&lt;/code&gt; in the chance that &lt;code&gt;users_name&lt;/code&gt; is not a list.&lt;/p&gt;

&lt;p&gt;The next step it's to handle the &lt;code&gt;users_name&lt;/code&gt; using the &lt;em&gt;pipe operator&lt;/em&gt;. First we'll go through the list and normalize the names. The first part can be achieve using the &lt;code&gt;map/2&lt;/code&gt; function from Elixir's &lt;code&gt;Enum&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's breakdown this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We called &lt;code&gt;users_name&lt;/code&gt; inside our function&lt;/li&gt;
&lt;li&gt;Then we added the &lt;code&gt;|&amp;gt;&lt;/code&gt; (&lt;em&gt;pipe operator&lt;/em&gt;) bellow &lt;code&gt;users_name&lt;/code&gt;. It could be called by the right side as well.&lt;/li&gt;
&lt;li&gt;To loop the list, we use the &lt;code&gt;map/2&lt;/code&gt;, that will return another list.&lt;/li&gt;
&lt;li&gt;As &lt;code&gt;map/2&lt;/code&gt; second parameter we gave a anonymous function &lt;code&gt;fn user_name -&amp;gt; ... end&lt;/code&gt; that will be executed for each element on the list&lt;/li&gt;
&lt;li&gt;Inside the anonymous function we called the &lt;a href="https://hexdocs.pm/elixir/String.html#capitalize/2"&gt;&lt;code&gt;capitalize/2&lt;/code&gt;&lt;/a&gt; from Elixir &lt;code&gt;String&lt;/code&gt; module to capitalize the names.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The bit that you need understand is that we pass only &lt;code&gt;map/2&lt;/code&gt; second parameter because the first parameter is passed by the &lt;code&gt;|&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Remember: "The &lt;em&gt;pipe operator&lt;/em&gt; forwards the result of an expression as the first parameter on to the next expression". In our case the first expression is the variable &lt;code&gt;users_name&lt;/code&gt; and when it gets evaluated will return the list of names. And our pipeline worked because &lt;code&gt;map/2&lt;/code&gt; expected as the first parameter a list!&lt;/p&gt;

&lt;p&gt;Using PHP we could achieve the same with this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next step is to "glue" all the names in a single &lt;code&gt;string&lt;/code&gt;. We'll use &lt;code&gt;join/2&lt;/code&gt; which is another function from &lt;code&gt;Enum&lt;/code&gt; module. This function will receive in the first parameter a list and in the second parameter receives a string as the joiner element. We'll use just a &lt;code&gt;", "&lt;/code&gt; to separate the names.&lt;/p&gt;

&lt;p&gt;Elixir module&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PHP class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our pipeline still functions because &lt;code&gt;map/2&lt;/code&gt; will return a new list and the &lt;code&gt;|&amp;gt;&lt;/code&gt; forwards it as the first parameter to the &lt;code&gt;join/2&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Great! &lt;code&gt;hello_group/1&lt;/code&gt; is able to normalize and glue together the names. Now we just need to print a message to the user.&lt;/p&gt;

&lt;p&gt;So far the result of &lt;code&gt;hello_group/1&lt;/code&gt; would be a string with the users names. We could use &lt;code&gt;hello/1&lt;/code&gt;, which receives a string as first parameter to print the message to our user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only strings are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;hello/1&lt;/code&gt; in the pipeline we fulfill all the requirements for &lt;code&gt;hello_group/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Take a look at the same feature in PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nv"&gt;$usersName&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersNameString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We could make the above code better by splitting in different functions, but do notice that even if we make such change the code in Elixir has a LOT more readability and less complexity.&lt;/p&gt;

&lt;p&gt;Here is another way to visualize the same code without using the &lt;em&gt;pipe operator&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:notpiped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s2"&gt;", "&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:notpiped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we defined another function: &lt;code&gt;hello_group/2&lt;/code&gt;, despite the arity, both functions will return the same result.&lt;br&gt;
But &lt;code&gt;hello_group/1&lt;/code&gt; is cleaner and easier to understand.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;center&gt;Control Structures&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;In Elixir we have access to certain tools that allow us to remove complexity from our code, but sometimes we have no other option and we have to use a &lt;code&gt;if&lt;/code&gt; or a &lt;code&gt;switch&lt;/code&gt;.&lt;br&gt;
The control structures available to us are: &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;unless&lt;/code&gt;, &lt;code&gt;case&lt;/code&gt;, &lt;code&gt;cond&lt;/code&gt; and &lt;code&gt;with&lt;/code&gt;. This article is an overview of the language and because of that I'm not write about all this structures. I'll focus in the &lt;code&gt;with&lt;/code&gt; because this one can be harder to understand than the others.&lt;/p&gt;

&lt;p&gt;The first thing that we need to understand is that in a functional language the result of a function is always the result of the last expression that get executed, we don't have the &lt;code&gt;return&lt;/code&gt; keyword in this functional world. Because of this, control structures will return the result of the last expression, so you need to be careful when write them. This can be challenging at first, but you get used to it quite fast.&lt;/p&gt;

&lt;p&gt;In a functional language we cannot do some like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;anotherFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PHP"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above PHP code we are defining a default value to &lt;code&gt;$param&lt;/code&gt; and based on &lt;code&gt;$condition&lt;/code&gt;'s his value will change. This wouldn't work in a Elixir code because de &lt;code&gt;if&lt;/code&gt; is an expression! If this was an &lt;code&gt;Elixir&lt;/code&gt; code, all that this if expression was doing is to match &lt;code&gt;$param&lt;/code&gt; to &lt;code&gt;"PHP"&lt;/code&gt;, and the return of this expression would be an &lt;code&gt;:ok&lt;/code&gt; atom. The &lt;code&gt;$param&lt;/code&gt; variable would never match &lt;code&gt;"PHP"&lt;/code&gt; outside the &lt;code&gt;if&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;To this work in Elixir, one could do as the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;another_function&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="s2"&gt;"Elixir"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this, the &lt;strong&gt;return&lt;/strong&gt; of the &lt;code&gt;if&lt;/code&gt; would be matched to the &lt;code&gt;param&lt;/code&gt; variable.&lt;br&gt;
With that in mind, let's move on.&lt;/p&gt;
&lt;h2&gt;
  
  
  With
&lt;/h2&gt;

&lt;p&gt;You can think in &lt;code&gt;with&lt;/code&gt; like a pipeline that checks the result of each expression and if some of those return an unexpected value the code inside the &lt;code&gt;with&lt;/code&gt; block won't get executed. You can also add fallback clausules to handle some unexpected behaviour or errors.&lt;/p&gt;

&lt;p&gt;Let's add this structure in our &lt;code&gt;hello/1&lt;/code&gt; function and see how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We created an &lt;code&gt;dummy_function/0&lt;/code&gt; that will only return an &lt;code&gt;:ok&lt;/code&gt; atom and we added an &lt;code&gt;with&lt;/code&gt; block to check the returned value. If the returned value was indeed an &lt;code&gt;:ok&lt;/code&gt; atom, them we print &lt;code&gt;"Hello, Joe"&lt;/code&gt; on the screen.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;dummy_function/0&lt;/code&gt; won't return an &lt;code&gt;:ok&lt;/code&gt; we could add a fallback clausule to handle this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:error&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion didn't return an :ok atom"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can match variables and other structures on the left side of the &lt;code&gt;&amp;lt;-&lt;/code&gt; operator, so we can use the value returned by the function inside de &lt;code&gt;with&lt;/code&gt; block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"dummy function"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_response&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion return an error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I can't figure what dummy_function has returned"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We checked if &lt;code&gt;dummy_function/0&lt;/code&gt; will return an &lt;code&gt;{:ok, response}&lt;/code&gt; result, if it does the function proceed and print the greeting. If &lt;code&gt;dummy_function/0&lt;/code&gt; returns an &lt;code&gt;{:error, message}&lt;/code&gt; it prints the message with the error. And at last if &lt;code&gt;dummy_function/0&lt;/code&gt; returns something unexpected the last clausule, which matches everything, will be executed printing the generic error message. The last clausule will not match on the other cases (&lt;code&gt;{:ok, response}&lt;/code&gt; and &lt;code&gt;{:error, message}&lt;/code&gt;) because the others two clausules will match first, remember, &lt;strong&gt;the declaration other matter&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;With this knowledge we can create an &lt;em&gt;pipeline&lt;/em&gt; of functions that will be validated in each step and handle any possible error individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_response2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reponse1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion return an error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I can't figure what dummy_function has returned"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;center&gt; And there you have it!&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;If you can wrap your mind around these Elixir's concepts I'm guarantee that you will have the basic knowledge to handle quite some understanding of an Elixir's code.&lt;/p&gt;

&lt;p&gt;Here are some topics for you to get deeper into the language and its ecosystem&lt;/p&gt;

&lt;h4&gt;
  
  
  Mix
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Task runner&lt;/em&gt; (similar to &lt;em&gt;composer&lt;/em&gt; on PHP), link to the &lt;a href="https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html"&gt;guide&lt;/a&gt; and &lt;a href="https://hexdocs.pm/mix/Mix.html"&gt;docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Phoenix
&lt;/h4&gt;

&lt;p&gt;Web framework (similar to &lt;em&gt;Symfony&lt;/em&gt;, &lt;em&gt;Laravel&lt;/em&gt;, etc... on PHP), link to the &lt;a href="https://www.phoenixframework.org/"&gt;site&lt;/a&gt; and &lt;a href="https://hexdocs.pm/phoenix/Phoenix.html"&gt;docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Ecto
&lt;/h4&gt;

&lt;p&gt;ORM (similar to &lt;em&gt;Doctrine&lt;/em&gt; on php), link to the &lt;a href="https://elixirschool.com/pt/lessons/ecto/basics/"&gt;guide&lt;/a&gt; and &lt;a href="https://hexdocs.pm/ecto/Ecto.html"&gt;docs&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Hex
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Package repository&lt;/em&gt; (similar to &lt;em&gt;Packgist&lt;/em&gt; of &lt;em&gt;Composer&lt;/em&gt;), link to the &lt;a href="https://hex.pm/"&gt;site&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt; References &lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;And here, some usefull links and references that I used to write this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official website: &lt;a href="https://elixir-lang.org/"&gt;https://elixir-lang.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Elixir School: &lt;a href="https://elixirschool.com/pt/"&gt;https://elixirschool.com/pt/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tiny documentary of the language: &lt;a href="https://www.youtube.com/watch?v=lxYFOM3UJzo"&gt;https://www.youtube.com/watch?v=lxYFOM3UJzo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Elixir lang on twitter: &lt;a href="https://twitter.com/elixirlang"&gt;https://twitter.com/elixirlang&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope that you enjoyed read this article and that was useful to you. If you have any suggestion or feedback leave a comment. This is one of my first articles and I would like to know how I'm doing 😁&lt;/p&gt;

&lt;p&gt;Thank you for your time! See you soon 🖖&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>php</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Entendendo Elixir com ajuda de PHP</title>
      <dc:creator>Leoni Mella</dc:creator>
      <pubDate>Thu, 30 Jan 2020 16:32:31 +0000</pubDate>
      <link>https://dev.to/ingresse/entendendo-elixir-com-ajuda-de-php-20n2</link>
      <guid>https://dev.to/ingresse/entendendo-elixir-com-ajuda-de-php-20n2</guid>
      <description>&lt;p&gt;🇬🇧 &lt;em&gt;Would you like to read this article in english? &lt;a href="https://dev.to/leonimella/learning-elixir-with-php-help-47mn"&gt;Learning Elixir with PHP help&lt;br&gt;
&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Depois de alguns anos e diversas experiências em PHP utilizando WordPress, Laravel, Symfony e Phalcon, tive a oportunidade de trabalhar com Elixir e desde então ela tem sido a minha linguagem para desenvolvimento de novos projetos&lt;/p&gt;

&lt;p&gt;Para quem nunca teve contato com uma linguagem funcional pode ser um pouco difícil entender como Elixir funciona, foi o meu caso quando comecei a utilizá-la.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A “ajuda” oferecida por PHP, nesse artigo, não passa de uma mera comparação feita entre as duas linguagens que por sinal não são NADA semelhante.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O que fiz foi implementar a mesma funcionalidade com linguagens diferentes para que você possa comparar a &lt;strong&gt;lógica&lt;/strong&gt; de uma linguagem mais familiar com uma que talvez não seja.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vou abordar as funcionalidades do Elixir que mais utilizo no dia-a-dia&lt;/strong&gt;, meio que aplicando a regra 80/20, mas tenho certeza que com esse conhecimento você poderá ao menos ler um arquivo &lt;code&gt;.ex&lt;/code&gt; ou &lt;code&gt;.exs&lt;/code&gt; e não se perder completamente, caso você seja novo na linguagem.&lt;/p&gt;
&lt;h4&gt;
  
  
  Antes de começarmos...
&lt;/h4&gt;

&lt;p&gt;Caso você não conheça absolutamente nada sobre Elixir, como é a syntax, seus operadores e primitivos sugiro a leitura do &lt;a href="https://elixir-lang.org/getting-started/introduction.html"&gt;&lt;em&gt;Starting Guide&lt;/em&gt;&lt;/a&gt; na documentação oficial.&lt;/p&gt;

&lt;p&gt;Sem mais demoras, vamos ao código!&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;center&gt;Pattern Matching&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Acho que a melhor definição do conceito de &lt;em&gt;pattern matching&lt;/em&gt; é a seguinte:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pattern matching é uma poderosa parte de Elixir que nos permite procurar padrões simples em valores, estruturas de dados, e até funções - &lt;a href="https://elixirschool.com/pt/lessons/basics/pattern-matching/"&gt;Elixir School&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mas o que exatamente significa? Para entender melhor precisamos falar sobre o &lt;em&gt;match operator&lt;/em&gt; &lt;code&gt;=&lt;/code&gt;. Além de utilizado para atribuir valores à variáveis, ele também pode ser usado para decompor estruturas mais complexas como tuplas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;a, b, c&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; a
&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;3&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; b
&lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;4&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; c
&lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;

&lt;span class="c"&gt;# Another example&lt;/span&gt;
iex&lt;span class="o"&gt;(&lt;/span&gt;5&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;_, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, country&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;6&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; country
&lt;span class="s2"&gt;"Chile"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou obter o primeiro valor de uma lista&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;head&lt;/span&gt; | &lt;span class="nb"&gt;tail&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Olá"&lt;/span&gt;, &lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Olá"&lt;/span&gt;, &lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;2&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;span class="s2"&gt;"Olá"&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;3&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tail&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Hello"&lt;/span&gt;, &lt;span class="s2"&gt;"Hola"&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso uma tupla não possa ser equiparada com o lado esquerdo do operador, isso é, caso a tupla tenha número de campos diferente ou algum valor que não condiz com o lado esquerdo do &lt;code&gt;=&lt;/code&gt; uma &lt;em&gt;exception&lt;/em&gt; acontecerá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# iex&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;a, b&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"São Paulo"&lt;/span&gt;, &lt;span class="s2"&gt;"Rio de Janeiro"&lt;/span&gt;, &lt;span class="s2"&gt;"Fortaleza"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# ** (MatchError) no match of right hand side value: {"São Paulo", "Rio de Janeiro", "Fortaleza"}&lt;/span&gt;
&lt;span class="c"&gt;#    (stdlib) erl_eval.erl:453: :erl_eval.expr/5&lt;/span&gt;
&lt;span class="c"&gt;#    ...&lt;/span&gt;

iex&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;_, &lt;span class="s2"&gt;"United States"&lt;/span&gt;, country&lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"Brasil"&lt;/span&gt;, &lt;span class="s2"&gt;"Ecuador"&lt;/span&gt;, &lt;span class="s2"&gt;"Chile"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# ** (MatchError) no match of right hand side value: {"Brasil", "Ecuador", "Chile"}&lt;/span&gt;
&lt;span class="c"&gt;#    (stdlib) erl_eval.erl:453: :erl_eval.expr/5&lt;/span&gt;
&lt;span class="c"&gt;#    ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os exemplos acima exemplificam a primeira parte da definição de &lt;em&gt;pattern matching&lt;/em&gt;. E quanto a parte que fala que podemos procurar padrões em funções? Vamos dar uma olhada.&lt;/p&gt;

&lt;p&gt;Para ajudar no entendimento dessa vez vou criar uma classe semelhante em PHP.&lt;/p&gt;

&lt;p&gt;Classe PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Módulo Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Até aqui, sem novidades, certo? Se chamarmos a função &lt;code&gt;hello/1&lt;/code&gt; ela vai exibir na tela a mensagem “Hello, Joe”. Mesma coisa com a função &lt;code&gt;hello()&lt;/code&gt; da classe em PHP.&lt;/p&gt;

&lt;p&gt;Mas vamos supor que nem sempre eu teria o nome do meu usuário disponível. Em determinadas vezes a variável &lt;code&gt;user_name&lt;/code&gt; poderia ser &lt;code&gt;nil&lt;/code&gt; (&lt;code&gt;null&lt;/code&gt; em PHP). Como podemos ajustar nosso código para esse requisito?&lt;/p&gt;

&lt;p&gt;Classe PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;is_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Em PHP poderíamos adicionar um valor default para o parâmetro &lt;code&gt;$userName&lt;/code&gt; e tratar esse caso com um &lt;code&gt;if&lt;/code&gt; dentro da nossa função exibindo uma mensagem diferente caso o argumento seja &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Executando &lt;code&gt;GreetUser.php&lt;/code&gt; obteríamos o resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s2"&gt;"Hello, Joe"&lt;/span&gt;
&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Embora a mesma solução seja possível, em Elixir podemos utilizar o &lt;em&gt;pattern matching&lt;/em&gt; ao nosso favor para simplificar o nosso código sem a necessidade do &lt;code&gt;if&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Módulo Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como existem duas funções com o mesmo nome a escolhida será aquela que possuir o parâmetro correto.&lt;/p&gt;

&lt;p&gt;Isso quer dizer que somente quando &lt;code&gt;user_name = nil&lt;/code&gt; é que a primeira função será executada, caso contrário ele “pula” essa função e vai para a próxima &lt;code&gt;hello/1&lt;/code&gt; declarada neste módulo.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Importante dizer que devido à aridade da função, &lt;code&gt;GreetUser.hello(nil)&lt;/code&gt; é diferente de &lt;code&gt;GreetUser.hello()&lt;/code&gt;. Em uma expressão invocamos &lt;code&gt;hello/1&lt;/code&gt; e na outra &lt;code&gt;hello/0&lt;/code&gt;, que não existe e portanto nos retornaria um erro, fique atento a aridade!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Qualquer tipo primitivo da linguagem pode ser utilizado para &lt;em&gt;pattern matching&lt;/em&gt;. Se o módulo &lt;code&gt;GreetUser&lt;/code&gt; agora tem que enviar uma mensagem específica para usuários que tenham o nome &lt;code&gt;"Jane”&lt;/code&gt;, poderíamos fazer da seguinte forma&lt;/p&gt;

&lt;p&gt;Classe em PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Nice to see you, Jane!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Módulo Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nice to see you, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa vez além de especificarmos qual seria o valor de &lt;code&gt;user_name&lt;/code&gt; nós também adicionamos o &lt;em&gt;match operator&lt;/em&gt; no parâmetro da função: &lt;code&gt;("Jane" = user_name)&lt;/code&gt;. Fizemos isso para que possamos utilizar o valor dentro da função. Caso não quiséssemos utilizar o parâmetro podemos omiti-lo &lt;code&gt;("Jane")&lt;/code&gt; ou adicionar um &lt;code&gt;_&lt;/code&gt; &lt;em&gt;underscore&lt;/em&gt; na frente dele &lt;code&gt;("Jane" = _user_name)&lt;/code&gt;. Com isso o Elixir entende que você está desprezando esse valor e que ele não será utilizado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Variáveis declaradas, mas não utilizadas recebem um&lt;/strong&gt; &lt;code&gt;warning&lt;/code&gt; &lt;strong&gt;no momento da compilação do seu código, fique atento!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aqui já é possível enxergar um pouco melhor como esse conceito reduz a complexidade em nossas funções. Agora que você entende pattern matching não fica melhor ler a função em Elixir do que em PHP? Não precisamos mais ficar “calculando” &lt;code&gt;if&lt;/code&gt;s para saber qual o resultado esperado, uma bela vantagem, não?&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Guards&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Se você gostou do conceito de &lt;em&gt;pattern matching&lt;/em&gt; você pode ir além utilizando &lt;em&gt;guards&lt;/em&gt;. Eles permitem verificações mais completas dos parâmetros que sua função está recebendo.&lt;/p&gt;

&lt;p&gt;Guards são definidos com um &lt;code&gt;when&lt;/code&gt; após a declaração da função. Enquanto o &lt;em&gt;pattern matching&lt;/em&gt; é útil para valores explícitos, com &lt;em&gt;guards&lt;/em&gt; podemos criar diversas condições para serem checadas. Podemos checar o tipo de um parâmetro, o tamanho dele se ele é ou não &lt;code&gt;nil&lt;/code&gt;, se ele é maior ou menor que determinado valor entre outras.&lt;/p&gt;

&lt;p&gt;Voltando ao nosso exemplo &lt;code&gt;GreetUser&lt;/code&gt;, podemos utilizar um &lt;em&gt;guard&lt;/em&gt; para verificar se &lt;code&gt;user_name&lt;/code&gt; é uma &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Módulo Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A função utilizada no guard &lt;code&gt;is_binary/1&lt;/code&gt; retorna um booleano e com esse resultado (&lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt;) &lt;code&gt;hello/1&lt;/code&gt; é invocada ou não. Elixir possui diversas funções “&lt;a href="https://hexdocs.pm/elixir/Kernel.html#is_atom/1"&gt;type-checks&lt;/a&gt;” como essa que usamos para checar tipos.&lt;/p&gt;

&lt;p&gt;Lembrando, que usando &lt;em&gt;guard&lt;/em&gt; ou &lt;em&gt;pattern matching&lt;/em&gt; você precisa pensar em uma alternativa para o caso em que um parâmetro não se enquadre em nenhuma validação caso contrário um &lt;em&gt;runtime error&lt;/em&gt; será lançado&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;** (FunctionClauseError) no function clause matching in GreetUser.hello/1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;O Erro acima aconteceria se nós invocarmos com um inteiro, por exemplo:&lt;code&gt;GreetUser.hello(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como alternativa podemos adicionar mais uma declaração de &lt;code&gt;hello/1&lt;/code&gt; desprezando o parâmetro &lt;code&gt;user_name&lt;/code&gt;. Como vimos antes, basta adicionarmos o &lt;em&gt;undersocre&lt;/em&gt; na frente do nome do parâmetro: &lt;code&gt;_user_name&lt;/code&gt;. Ou simplesmente substituirmos pelo &lt;code&gt;_&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only string is allowed in this function"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Importante!
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;A ordem de declaração das funções em linguagens funcionais é de extrema importância!&lt;/strong&gt;&lt;br&gt;
No exemplo acima o uso de &lt;code&gt;hello/1&lt;/code&gt; ficou restrita à parâmetros do tipo &lt;code&gt;string&lt;/code&gt;. Como alternativa declaramos novamente &lt;code&gt;hello/1&lt;/code&gt; &lt;strong&gt;desprezando&lt;/strong&gt; o parâmetro &lt;code&gt;user_name&lt;/code&gt;. Até ai tudo legal, mas e se tivéssemos invertido as ordens de declaração das funções colocando &lt;code&gt;hello(_)&lt;/code&gt; antes da &lt;code&gt;hello/1&lt;/code&gt; que possui &lt;em&gt;guard&lt;/em&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only string is allowed in this function"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Executando o código acima teríamos o seguinte aviso:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;warning: this clause cannot match because a previous clause at line 5 always matches
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nosso código rodaria sem problemas, mas a função &lt;code&gt;hello/1&lt;/code&gt; com o &lt;em&gt;guard&lt;/em&gt; &lt;code&gt;when is_binary/1&lt;/code&gt; nunca seria executada porque a &lt;code&gt;hello/1&lt;/code&gt; sem &lt;em&gt;guard&lt;/em&gt; é sempre validada antes. Por isso preste sempre atenção à ordem de declaração de suas funções!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Pipe Operator&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Esse pode ser um pouco mais complicado para entender, mas em resumo o &lt;em&gt;pipe operator&lt;/em&gt; é representado por esse símbolo &lt;code&gt;|&amp;gt;&lt;/code&gt; e o trabalho dele é passar o resultado de uma expressão como primeiro parâmetro de outra expressão.&lt;/p&gt;

&lt;p&gt;Com isso você pode criar &lt;em&gt;pipelines&lt;/em&gt; (sacou o nome?) de execução dada determinada expressão (variável ou função).&lt;/p&gt;

&lt;p&gt;Para exemplificar, agora nosso módulo &lt;code&gt;GreetUser&lt;/code&gt; deve ser capaz de cumprimentar diversas pessoas cujo os nomes serão enviados em forma de uma lista. Para fazer isso vamos criar uma função &lt;code&gt;hello_group/1&lt;/code&gt; que recebe como argumento &lt;code&gt;users_name&lt;/code&gt; que nada mais é do que uma lista contendo o nome dos usuários em string.&lt;/p&gt;

&lt;p&gt;Além disso precisamos também tratar os nomes dos usuários para que eles fiquem capitalizados, isso é, somente a primeira letra do seu nome em maiúsculo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="c1"&gt;# code&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aproveitamos para adicionar um guard na nossa função para nos certificar de que o parâmetro é mesmo uma lista e também definimos uma &lt;code&gt;hello_group/1&lt;/code&gt; default para ser utilizada caso &lt;code&gt;users_name&lt;/code&gt; não seja uma lista.&lt;/p&gt;

&lt;p&gt;O próximo passo é manipular a lista aplicando os requisitos acima utilizando o &lt;em&gt;pipe operator&lt;/em&gt;. Como primeiro passo, vamos percorrer a lista e normalizar os nomes. Faremos isso com a ajuda do módulo &lt;code&gt;Enum&lt;/code&gt; que é um módulo nativo do Elixir para trabalhar com elementos enumeráveis, o que é o caso da nossa lista de nomes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vamos quebrar o código acima em pontos chaves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Invocamos &lt;code&gt;users_name&lt;/code&gt; dentro da nossa função&lt;/li&gt;
&lt;li&gt;Invocamos &lt;code&gt;|&amp;gt;&lt;/code&gt; (pipe operator) abaixo de &lt;code&gt;users_name&lt;/code&gt; poderia ser do lado direito também.&lt;/li&gt;
&lt;li&gt;Invocamos &lt;code&gt;map/2&lt;/code&gt; do módulo &lt;code&gt;Enum&lt;/code&gt; para percorrer a lista de nomes e nos retornar uma lista&lt;/li&gt;
&lt;li&gt;Passamos como segundo parâmetro de &lt;code&gt;map/2&lt;/code&gt; uma função anônima &lt;code&gt;fn user_name -&amp;gt; end&lt;/code&gt; que será executada para cada nome da lista&lt;/li&gt;
&lt;li&gt;Dentro da função anônima utilizamos a função &lt;a href="https://hexdocs.pm/elixir/String.html#capitalize/2"&gt;&lt;code&gt;capitalize/2&lt;/code&gt;&lt;/a&gt; do módulo &lt;code&gt;String&lt;/code&gt; também nativo do Elixir para capitalizar os nomes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O que precisa ser entendido desse código é que só passamos o segundo argumento para a função &lt;code&gt;map/2&lt;/code&gt; porque o primeiro argumento que deve ser uma lista (no nosso caso a lista com os nomes dos usuários) já foi passada à essa função pelo &lt;code&gt;|&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lembre que: “O &lt;em&gt;pipe operator&lt;/em&gt; é responsável por passar o valor de uma expressão como o primeiro parâmetro da próxima expressão” No caso nossa primeira expressão é a variável &lt;code&gt;users_name&lt;/code&gt; que ao ser processada retorna nossa lista de nomes e uma lista é justamente o que &lt;code&gt;map/2&lt;/code&gt; recebe no primeiro parâmetro, por isso nossa pipeline funciona!&lt;/p&gt;

&lt;p&gt;E o segundo parâmetro passado ao &lt;code&gt;map/2&lt;/code&gt; foi uma função anônima (requerida por &lt;code&gt;map/2&lt;/code&gt;) que recebe como argumento o elemento da lista que está sendo percorrida para que possamos manipulá-lo.&lt;/p&gt;

&lt;p&gt;Em PHP podemos obter o mesmo resultado até aqui dessa forma:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O próximo passo nessa função é juntarmos todos os nomes em uma única string. Para isso utilizaremos outra função nativa do Elixir, a &lt;code&gt;join/2&lt;/code&gt; do módulo &lt;code&gt;Enum&lt;/code&gt;. Ela recebe como primeiro parâmetro uma lista e como segundo parâmetro um elemento de junção, no nosso caso utilizaremos uma vírgula seguida de espaço em branco, para separar os nomes dentro da string.&lt;/p&gt;

&lt;p&gt;Módulo Elixir&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classe PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nossa pipeline continua funcionando porque &lt;code&gt;map/2&lt;/code&gt;, após ser executada, retorna uma lista e o &lt;code&gt;|&amp;gt;&lt;/code&gt; passa essa lista como primeiro parâmetro para a próxima função &lt;code&gt;join/2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ótimo! &lt;code&gt;hello_group/1&lt;/code&gt; já consegue normalizar e juntar os nomes enviados como lista em uma única string! Agora só nos resta imprimir nossa mensagem para o usuário.&lt;/p&gt;

&lt;p&gt;Até agora o retorno de &lt;code&gt;hello_group/1&lt;/code&gt; seria uma string contendo os nomes de usuários que foi passado à ela. Podemos utilizar &lt;code&gt;hello/1&lt;/code&gt;, que recebe como primeiro parâmetro uma string, para exibir a mensagem padrão&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only strings are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;when&lt;/span&gt; &lt;span class="n"&gt;is_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Only lists are allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicionamos &lt;code&gt;hello/1&lt;/code&gt; no final de nossa pipeline concluindo os requisitos exigidos para &lt;code&gt;hello_group/1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Veja como ficaria o mesmo código em PHP&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;
&lt;span class="c1"&gt;// ./GreetUser.php&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;$userName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;is_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersName&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Only arrays are allowed"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;array_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;ucfirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="nv"&gt;$usersName&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nv"&gt;$usersNameString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;implode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$usersNameNormalized&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$usersNameString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;$greetUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GreetUser&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$greetUser&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;helloGroup&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Poderíamos melhorar o código PHP quebrando-o em diferentes funções, mas repare que mesmo dessa forma em Elixir temos um código MUITO mais limpo e legível.&lt;/p&gt;

&lt;p&gt;Caso você ainda esteja um pouco confuso em como o &lt;em&gt;pipe operator&lt;/em&gt; funciona, aqui está uma outra forma de visualizar o mesmo código:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;users_name&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;", "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:notpiped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="n"&gt;users_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;capitalize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="s2"&gt;", "&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello_group&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"joe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"jim"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;:notpiped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Definimos duas funções &lt;code&gt;hello_group()&lt;/code&gt;. Uma com &lt;a href="https://elixirschool.com/en/lessons/basics/functions/#function-naming-and-arity"&gt;aridade&lt;/a&gt; &lt;code&gt;hello_group/1&lt;/code&gt; e outra com &lt;code&gt;hello_group/2&lt;/code&gt;. Apesar da aridade diferente, as duas executam o mesmo papel, mas a &lt;code&gt;hello_group/1&lt;/code&gt; cria uma &lt;em&gt;pipeline&lt;/em&gt; enquanto a &lt;code&gt;hello_group/2&lt;/code&gt; não, mas as duas chegam no mesmo resultado.&lt;/p&gt;

&lt;p&gt;Porém &lt;code&gt;hello_group/1&lt;/code&gt; é bem mais legível e de fácil entendimento se comparada a &lt;code&gt;hello_group/2&lt;/code&gt;, concordam? Esse é o propósito do &lt;em&gt;pipe operator&lt;/em&gt;, deixar nosso código mais legível.&lt;/p&gt;

&lt;p&gt;Para concluir aqui vai uma observação muito importante! Em linguagens funcionais nós não temos a opção de utilizar &lt;code&gt;return&lt;/code&gt;s dentro das funções. As funções retornarão o resultado da última expressão executada, vamos explorar mais sobre isso no próximo tópico.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Estruturas de Controle&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Vimos que em Elixir é possível simplificar muito nossas funções removendo condicionais através do &lt;em&gt;pattern matching&lt;/em&gt; e &lt;em&gt;guards&lt;/em&gt;. Mas as vezes não temos outra alternativa a não ser utilizar um &lt;code&gt;if&lt;/code&gt; ou &lt;code&gt;switch&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As estruturas de controles presentes em Elixir são: &lt;code&gt;if&lt;/code&gt;, &lt;code&gt;unless&lt;/code&gt;, &lt;code&gt;case&lt;/code&gt;, &lt;code&gt;cond&lt;/code&gt; e &lt;code&gt;with&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como esse é um overview da linguagem, não vou me aprofundar em todas elas com exceção do  &lt;code&gt;with&lt;/code&gt;, talvez ele cause mais estranheza enquanto as outras são mais familiares.&lt;/p&gt;

&lt;p&gt;É importante notar que essas estruturas de controles se comportam como funções e por isso alguns hábitos de outras linguagens devem ser evitados em Elixir. Um exemplo disso é quando você define um valor default para uma variável e dentro de um &lt;code&gt;if&lt;/code&gt; você troca esse valor. Algo parecido com isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;anotherFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$condition&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PHP"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$param&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse código não funciona do jeito que você espera em Elixir, como &lt;code&gt;if&lt;/code&gt; se comporta como uma função ela vai retornar o resultado que foi executado dentro do seu body. Sendo assim o valor que você atribuiu dentro dele para a sua variável não será aplicado pois não faz parte do escopo da função.&lt;/p&gt;

&lt;p&gt;Para que isso funcionasse você teria que fazer algo desse gênero:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;another_function&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;param&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="s2"&gt;"Elixir"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="no"&gt;nil&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dessa forma o retorno de &lt;code&gt;if&lt;/code&gt; seria atribuído à nossa variável.&lt;/p&gt;

&lt;h2&gt;
  
  
  With
&lt;/h2&gt;

&lt;p&gt;Você pode pensar nele como uma &lt;em&gt;pipeline&lt;/em&gt; que checa o resultado de cada expressão e caso o resultado dessa expressão não foi o que você havia descrito ela não executa o código dentro dela. Ou você também pode validar o erro gerado pela expressão para tratá-lo de uma forma mais coerente.&lt;/p&gt;

&lt;p&gt;Para ilustrar melhor, vamos adicionar essa estrutura na nossa função &lt;code&gt;hello/1&lt;/code&gt;. Criaremos também uma &lt;code&gt;dummy_function/0&lt;/code&gt; que a única coisa que ela faz é retornar o &lt;em&gt;atom&lt;/em&gt; &lt;code&gt;:ok&lt;/code&gt;, e em &lt;code&gt;hello/1&lt;/code&gt; verificamos se &lt;code&gt;dummy_function/0&lt;/code&gt; realmente volta &lt;code&gt;:ok&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima, a mensagem só será exibida caso &lt;code&gt;dummy_function/0&lt;/code&gt; retornar &lt;code&gt;:ok&lt;/code&gt;. Se o retorno for outro a mensagem não será exibida.&lt;/p&gt;

&lt;p&gt;Se &lt;code&gt;dummy_function/0&lt;/code&gt; não retornar o esperado, podemos adicionar uma cláusula para tratar o resultado.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:error&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion didn't return an :ok atom"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos também atribuir variáveis do lado esquerdo do &lt;code&gt;&amp;lt;-&lt;/code&gt; ou &lt;code&gt;-&amp;gt;&lt;/code&gt; que nem fizemos quando vimos sobre &lt;em&gt;pattern matching&lt;/em&gt;. Com isso é possível verificar o retorno da função e já atribuir uma variável&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# ./greet_user.exs&lt;/span&gt;

&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;GreetUser&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"dummy function"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_response&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion return an error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
                &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I can't figure what dummy_function has returned"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;GreetUser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Joe"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No código acima checamos se &lt;code&gt;dummy_function/0&lt;/code&gt; retorna &lt;code&gt;{:ok, _response}&lt;/code&gt; Caso um erro ocorra e &lt;code&gt;dummy_function/0&lt;/code&gt; retornar &lt;code&gt;{:error, "dummy function"}&lt;/code&gt; nós vamos exibir &lt;code&gt;"dummy function"&lt;/code&gt;, que foi o erro retornado. E ainda adicionamos uma cláusula default se &lt;code&gt;dummy_function/0&lt;/code&gt; retornar algo totalmente inesperado.&lt;/p&gt;

&lt;p&gt;Agora que já temos um bom entendimento sobre o &lt;em&gt;with&lt;/em&gt; podemos criar uma &lt;em&gt;pipeline&lt;/em&gt; de funções cujo os retornos são verificados pelo with e podemos também tratar individualmente cada etapa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;response1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
         &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_response2&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;dummy_function_2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reponse1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Hello, &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"dummy_functtion return an error: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class="no"&gt;IO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;puts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"I can't figure what dummy_function has returned"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código acima cria uma &lt;em&gt;pipeline&lt;/em&gt; que checa passo a passo o retorno das funções possibilitando o tratamento personalizado para cada erro que possa acontecer.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;And there you have it!&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Embora Elixir seja um mundo de funcionalidades e paradigmas diferentes se você possuir um bom entendimento dos tópicos acima você conseguirá se localizar muito bem no código escrito nessa linguagem.&lt;/p&gt;

&lt;p&gt;Estes são alguns tópicos importantes para você que deseja continuar interagindo com a linguagem:&lt;/p&gt;

&lt;h4&gt;
  
  
  Mix
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Task runner&lt;/em&gt; da linguagem (equivalente ao &lt;em&gt;composer&lt;/em&gt; em PHP), link para o &lt;a href="https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html"&gt;guia&lt;/a&gt; e &lt;a href="https://hexdocs.pm/mix/Mix.html"&gt;documentação&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Phoenix
&lt;/h4&gt;

&lt;p&gt;Web framework (equivalente ao &lt;em&gt;Symfony&lt;/em&gt;, &lt;em&gt;Laravel&lt;/em&gt;, etc... em PHP), link para o &lt;a href="https://www.phoenixframework.org/"&gt;site&lt;/a&gt; e &lt;a href="https://hexdocs.pm/phoenix/Phoenix.html"&gt;documentação&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Ecto
&lt;/h4&gt;

&lt;p&gt;ORM (equivalente ao &lt;em&gt;Doctrine&lt;/em&gt; em php), link para o &lt;a href="https://elixirschool.com/pt/lessons/ecto/basics/"&gt;guia&lt;/a&gt; e &lt;a href="https://hexdocs.pm/ecto/Ecto.html"&gt;documentação&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Hex
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;Package repository&lt;/em&gt; (equivalente ao &lt;em&gt;Packgist&lt;/em&gt; do &lt;em&gt;Composer&lt;/em&gt;), link para o &lt;a href="https://hex.pm/"&gt;site&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;center&gt;Referências&lt;/center&gt;
&lt;/h2&gt;

&lt;p&gt;Abaixo uma lista de sites, vídeos e outros materiais para você ler e que foram utilizados para compor esse artigo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Site oficial da linguagem: &lt;a href="https://elixir-lang.org/"&gt;https://elixir-lang.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Para aprender mais: &lt;a href="https://elixirschool.com/pt/"&gt;https://elixirschool.com/pt/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Mini documentário da origem da linguagem: &lt;a href="https://www.youtube.com/watch?v=lxYFOM3UJzo"&gt;https://www.youtube.com/watch?v=lxYFOM3UJzo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Hipster ponto tech com o José Valim sobre Elixir: &lt;a href="https://hipsters.tech/elixir-a-linguagem-hipster-hipsters-48/"&gt;https://hipsters.tech/elixir-a-linguagem-hipster-hipsters-48/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Principal evento da linguagem no Brasil: &lt;a href="https://twitter.com/elixir_brasil"&gt;https://twitter.com/elixir_brasil&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Espero que esse artigo tenha sido útil para você. Caso tenha alguma sugestão e/ou feedback deixe nos comentários, esse é um dos meus primeiros artigos e gostaria de saber como estou me saindo 😁&lt;/p&gt;

&lt;p&gt;Obrigado pelo seu tempo e até a próxima 🖖&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>elixir</category>
      <category>php</category>
      <category>ptbr</category>
    </item>
  </channel>
</rss>
