<?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: Zoey de Souza Pessanha</title>
    <description>The latest articles on DEV Community by Zoey de Souza Pessanha (@zoedsoupe).</description>
    <link>https://dev.to/zoedsoupe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F369999%2F94f2acbb-bb0e-44a7-9846-0a928d0d1d6b.jpg</url>
      <title>DEV Community: Zoey de Souza Pessanha</title>
      <link>https://dev.to/zoedsoupe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/zoedsoupe"/>
    <language>en</language>
    <item>
      <title>Técnicas de Concorrência e Gerenciamento de Estado em Elixir com FSM</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Fri, 21 Jun 2024 19:09:00 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/tecnicas-de-concorrencia-e-gerenciamento-de-estado-em-elixir-com-fsm-3f83</link>
      <guid>https://dev.to/zoedsoupe/tecnicas-de-concorrencia-e-gerenciamento-de-estado-em-elixir-com-fsm-3f83</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Elixir é uma linguagem funcional que roda na máquina virtual BEAM, a mesma do Erlang, famosa por suas capacidades de concorrência e tolerância a falhas. Um dos padrões poderosos que podem ser implementados em Elixir é a Máquina de Estado Finito (FSM - Finite State Machine), combinada com processamento assíncrono. Este artigo explora como esses padrões podem beneficiar programas em Elixir, proporcionando controle sobre o fluxo de eventos e melhorando a eficiência e a robustez dos sistemas.&lt;/p&gt;

&lt;h2&gt;
  
  
  Máquinas de Estado Finito (FSM)
&lt;/h2&gt;

&lt;p&gt;Uma Máquina de Estado Finito é um modelo computacional que consiste em um número finito de estados, transições entre esses estados, e ações, que podem ser acionadas por eventos. Em um sistema FSM, um objeto pode estar em apenas um estado de cada vez, e ele pode mudar de estado em resposta a um evento. Cada transição pode ser associada a uma ação específica.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefícios da FSM
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organização e Clareza&lt;/strong&gt;: FSM ajuda a organizar e clarear o comportamento de sistemas complexos, tornando o fluxo de eventos mais previsível e fácil de entender.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Controle de Fluxo&lt;/strong&gt;: Com FSM, o controle do fluxo de estados é explícito e definido claramente, permitindo transições apenas quando condições específicas são atendidas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Facilidade de Manutenção&lt;/strong&gt;: FSM permite encapsular a lógica de estado em um único lugar, facilitando a manutenção e atualização do sistema sem introduzir bugs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Exemplo de FSM
&lt;/h3&gt;

&lt;p&gt;Considere um sistema simples de autorização de pagamento com os seguintes estados: &lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;authorized&lt;/code&gt;, &lt;code&gt;denied&lt;/code&gt; e &lt;code&gt;failed&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Estado Inicial&lt;/strong&gt;: O pagamento começa no estado &lt;code&gt;pending&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transição para &lt;code&gt;authorized&lt;/code&gt;&lt;/strong&gt;: Quando uma solicitação de autorização é aprovada, o estado muda para &lt;code&gt;authorized&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transição para &lt;code&gt;denied&lt;/code&gt;&lt;/strong&gt;: Se a solicitação for negada, o estado muda para &lt;code&gt;denied&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transição para &lt;code&gt;failed&lt;/code&gt;&lt;/strong&gt;: Se houver um erro no processamento, o estado muda para &lt;code&gt;failed&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Um fluxo simplificado de FSM poderia ser representado assim:&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentFSM&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Define a FSM para estados de pagamento.
  """&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Fsmx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Fsm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;transitions:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="s2"&gt;"pending"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"authorized"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"denied"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s2"&gt;"authorized"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="s2"&gt;"denied"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="s2"&gt;"failed"&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Aqui usamos a biblioteca &lt;code&gt;Fsmx&lt;/code&gt;, mas é possível usar funções simples ou mesmo o ecto para definir uma FSM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Neste exemplo, um pagamento pode mudar de &lt;code&gt;pending&lt;/code&gt; para &lt;code&gt;authorized&lt;/code&gt;, &lt;code&gt;denied&lt;/code&gt;, ou &lt;code&gt;failed&lt;/code&gt;. Uma vez que está em &lt;code&gt;authorized&lt;/code&gt;, &lt;code&gt;denied&lt;/code&gt;, ou &lt;code&gt;failed&lt;/code&gt;, ele não pode transitar para outros estados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Processamento Assíncrono
&lt;/h2&gt;

&lt;p&gt;O processamento assíncrono permite que operações sejam executadas em paralelo ou de maneira não bloqueante, aumentando a eficiência e capacidade de resposta do sistema. Em Elixir, isso é conseguido utilizando processos leves gerenciados pela máquina virtual BEAM.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefícios do Processamento Assíncrono
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Escalabilidade&lt;/strong&gt;: O processamento assíncrono permite que múltiplas tarefas sejam executadas simultaneamente, aumentando a escalabilidade do sistema.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Responsividade&lt;/strong&gt;: Sistemas assíncronos podem continuar a responder a novas requisições enquanto outras operações estão em andamento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tolerância a Falhas&lt;/strong&gt;: A arquitetura de supervisão de Elixir permite que processos falhem e sejam reiniciados sem afetar o restante do sistema.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Exemplo de Processamento Assíncrono
&lt;/h3&gt;

&lt;p&gt;Imagine um sistema que processa eventos de pagamento. Cada evento pode desencadear várias operações, como verificação de saldo, registro de transações, etc. Para não bloquear o processamento de novos eventos, podemos usar tarefas assíncronas.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@moduledoc&lt;/span&gt; &lt;span class="sd"&gt;"""
  Processa eventos de pagamento de forma assíncrona.
  """&lt;/span&gt;

  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;GenServer&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_opts&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;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_link&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&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="ss"&gt;name:&lt;/span&gt; &lt;span class="bp"&gt;__MODULE__&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;process_event&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="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;GenServer&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;__MODULE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:process&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="k"&gt;end&lt;/span&gt;

  &lt;span class="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;init&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="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="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="nv"&gt;@impl&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;handle_cast&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="ss"&gt;:process&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="n"&gt;deadletter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;handle_event&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="k"&gt;do&lt;/span&gt;
      &lt;span class="ss"&gt;:ok&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;deadletter&lt;/span&gt;&lt;span class="p"&gt;}&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;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:noreply&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;deadletter&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="c1"&gt;# dependendo da complexidade, podem existir&lt;/span&gt;
  &lt;span class="c1"&gt;# diferentes módulos de handler para eventos&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;handle_event&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="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# Lógica para processar o evento de pagamento&lt;/span&gt;
    &lt;span class="c1"&gt;# Efeitos colaterais&lt;/span&gt;
    &lt;span class="c1"&gt;# Observabilidade&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;"Processando evento: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, cada evento é processado em uma nova tarefa, permitindo que o sistema continue a receber e enfileirar novos eventos sem esperar que os eventos anteriores sejam processados.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lock Otimista
&lt;/h2&gt;

&lt;p&gt;O Lock Otimista é uma técnica utilizada para lidar com concorrência em sistemas distribuídos. Ao contrário do Lock Pessimista, que bloqueia os recursos até que uma transação seja concluída, o Lock Otimista assume que as colisões são raras e permite que múltiplas transações ocorram simultaneamente, verificando conflitos apenas no momento da confirmação.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefícios do Lock Otimista
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Melhor Desempenho&lt;/strong&gt;: Reduz a quantidade de bloqueios, permitindo maior paralelismo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Menos Deadlocks&lt;/strong&gt;: Minimiza a chance de deadlocks, uma vez que os recursos não são bloqueados por longos períodos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maior Escalabilidade&lt;/strong&gt;: Facilita a escalabilidade horizontal, essencial para sistemas distribuídos de grande porte.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Exemplo de Lock Otimista
&lt;/h3&gt;

&lt;p&gt;Vamos adicionar a lógica de lock otimista em nosso sistema de pagamentos. A ideia é verificar e atualizar o estado do pagamento apenas se ele não foi modificado por outro processo.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;Payments&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;PaymentSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Repo&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;PaymentSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Payments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Payment&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;update_payment_with_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&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;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;updated_payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;updated_payment&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_payment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:ok&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;changeset&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;Repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;changeset&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="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;Neste exemplo, usamos uma transação para garantir que o pagamento seja atualizado apenas se ele não tiver sido modificado por outro processo desde a última leitura.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integração de FSM, Lock Otimista e Processamento Assíncrono
&lt;/h2&gt;

&lt;p&gt;Combinar FSM, Lock Otimista e Processamento Assíncrono em Elixir pode levar a sistemas altamente eficientes e robustos. A FSM controla o fluxo de estados, garantindo que as transições sejam ordenadas e previsíveis. O Lock Otimista permite que transações concorrentes sejam gerenciadas eficientemente, enquanto o Processamento Assíncrono garante que operações de longa duração não bloqueiem o sistema.&lt;/p&gt;

&lt;h3&gt;
  
  
  Exemplo Completo
&lt;/h3&gt;

&lt;p&gt;Vamos combinar os conceitos discutidos anteriormente em um exemplo completo:&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentFSM&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Fsmx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Fsm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;transitions:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="s2"&gt;"pending"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"authorized"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"denied"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"failed"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="s2"&gt;"authorized"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="s2"&gt;"denied"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="s2"&gt;"failed"&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;def&lt;/span&gt; &lt;span class="n"&gt;start_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;process_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"start"&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;defp&lt;/span&gt; &lt;span class="n"&gt;process_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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="k"&gt;do&lt;/span&gt;
    &lt;span class="no"&gt;PaymentProcessor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;process_event&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="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;handle_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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="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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_payment&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;"Evento processado com sucesso: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_payment&lt;/span&gt;&lt;span class="p"&gt;)&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="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;reason&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;"Erro ao processar evento: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;)&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;defp&lt;/span&gt; &lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"start"&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;Fsmx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"authorized"&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;PaymentProcessor&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;PaymentSystem&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="no"&gt;Payments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;PaymentFSM&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;process_payment_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;Task&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;defp&lt;/span&gt; &lt;span class="n"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;payment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;PaymentFSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;authorize_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&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;payment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="no"&gt;Payments&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_payment_with_lock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="s2"&gt;"authorized"&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;"Pagamento processado com sucesso: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&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;reason&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;PaymentFSM&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fail_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&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;"Falha ao processar pagamento: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. Motivo: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;reason&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, a FSM gerencia o estado do pagamento, o Lock Otimista garante que as atualizações de estado ocorram de maneira concorrente segura, e o processamento de eventos é feito de forma assíncrona, garantindo que o sistema permaneça responsivo e eficiente.&lt;/p&gt;

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

&lt;p&gt;O uso de Máquinas de Estado Finito (FSM) e processamento assíncrono interno pode trazer inúmeros benefícios para programas em Elixir, desde melhor organização e controle de fluxo até maior resiliência e escalabilidade. Ao combinar esses padrões, é possível criar sistemas robustos, capazes de lidar com complexidade e alta carga de forma eficaz.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>elixir</category>
      <category>programming</category>
    </item>
    <item>
      <title>Parse, Don’t Validate: Embracing Data Integrity in Elixir</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Wed, 19 Jun 2024 13:30:00 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/parse-dont-validate-embracing-data-integrity-in-elixir-5c94</link>
      <guid>https://dev.to/zoedsoupe/parse-dont-validate-embracing-data-integrity-in-elixir-5c94</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In the world of functional programming, ensuring data integrity is paramount. One effective way to achieve this is by adopting the principle of &lt;strong&gt;"Parse, Don’t Validate"&lt;/strong&gt;. This approach emphasizes the transformation of raw input data into structured, well-defined data early in the application flow, thereby enhancing reliability and maintainability. While this concept is not new, its application in Elixir—a functional and concurrent programming language—offers unique benefits and challenges. This article delves into the theory behind parsing over validation and how it aligns with Elixir's paradigms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Theoretical Foundations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Parsing vs. Validation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt; involves checking if data meets certain criteria, often at multiple points in an application. This can lead to redundancy and inconsistencies, as the same checks are repeated, and errors may not be handled uniformly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parsing&lt;/strong&gt;, on the other hand, transforms data into a structured format that inherently satisfies the required criteria. This approach ensures that once data is parsed successfully, it is guaranteed to be valid throughout the application, eliminating the need for repeated checks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Parsing over Validation?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Early Error Detection&lt;/strong&gt;: Parsing catches errors at the boundaries of your system, preventing invalid data from entering the core logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplified Code&lt;/strong&gt;: By transforming data into a well-defined structure upfront, the core application logic becomes simpler and more focused on business requirements rather than data validation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced Maintainability&lt;/strong&gt;: Centralizing data integrity checks in parsing functions makes the system easier to understand and maintain.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Functional Programming and Parsing
&lt;/h3&gt;

&lt;p&gt;In functional programming, functions are first-class citizens, and immutability is a core principle. Parsing fits naturally into this paradigm as it allows data to be transformed in a pure, deterministic manner. Once data is parsed into a well-defined structure, it remains immutable, ensuring consistency and reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Concurrency and Data Integrity in Elixir
&lt;/h3&gt;

&lt;p&gt;Elixir, built on the Erlang VM, excels in building concurrent, distributed systems. In such environments, data integrity is crucial, as concurrent processes need to operate on reliable data. By parsing data at the boundaries, Elixir applications can ensure that all processes work with valid, consistent data, thereby reducing the risk of concurrency-related bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying the "Parse, Don’t Validate" Principle in Elixir
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Conceptual Approach
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Define Data Structures&lt;/strong&gt;: Use Elixir structs or maps to define the shape of your data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parse Input Data&lt;/strong&gt;: Transform raw input data into these well-defined structures at the earliest possible point in your application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralize Parsing Logic&lt;/strong&gt;: Encapsulate parsing logic in dedicated modules or functions to ensure uniformity and reuse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leverage Pattern Matching&lt;/strong&gt;: Utilize Elixir’s powerful pattern matching to simplify the parsing process and handle different data shapes effectively.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example Scenario
&lt;/h3&gt;

&lt;p&gt;Consider an API endpoint that accepts user registration data. Instead of validating fields individually, parse the entire payload into a &lt;code&gt;User&lt;/code&gt; struct.&lt;/p&gt;

&lt;h4&gt;
  
  
  Defining the Data Structure
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Parsing the Input Data
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserParser&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&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;name&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;validate_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"name"&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;email&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;validate_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"email"&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;age&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;validate_age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"age"&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;address&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;validate_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"address"&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="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;address:&lt;/span&gt; &lt;span class="n"&gt;address&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;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&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;reason&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;defp&lt;/span&gt; &lt;span class="n"&gt;validate_name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;byte_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_name&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="p"&gt;:&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="s2"&gt;"Invalid name"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&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;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&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;contains?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&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;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="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_email&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="p"&gt;:&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="s2"&gt;"Invalid email"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&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_integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_age&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="p"&gt;:&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="s2"&gt;"Invalid age"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&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_map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&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="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;validate_address&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="p"&gt;:&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="s2"&gt;"Invalid address"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using the Parser in Your Application
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;UserParser&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;register_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;UserParser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;# Proceed with business logic using the parsed user&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;})&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;reason&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;# Handle parsing errors&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;reason:&lt;/span&gt; &lt;span class="n"&gt;reason&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Parsing with Peri
&lt;/h2&gt;

&lt;p&gt;While the above example demonstrates a manual approach to parsing, the &lt;a href="https://hexdocs.pm/peri"&gt;Peri&lt;/a&gt; library offers a more structured way to define and enforce schemas in Elixir.&lt;/p&gt;

&lt;h3&gt;
  
  
  Defining a Schema with Peri
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;MySchemas&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Peri&lt;/span&gt;

  &lt;span class="n"&gt;defschema&lt;/span&gt; &lt;span class="ss"&gt;:user&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="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;address:&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="ss"&gt;street:&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;city:&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:enum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parsing Data with Peri
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserController&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="no"&gt;MyApp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;MySchemas&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;register_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="no"&gt;MySchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;# Proceed with business logic using the parsed user&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;})&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;errors&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class="c1"&gt;# Handle parsing errors&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;status:&lt;/span&gt; &lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;errors:&lt;/span&gt; &lt;span class="n"&gt;errors&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Adopting the "Parse, Don’t Validate" principle in Elixir ensures data integrity, simplifies code, and enhances maintainability. By transforming raw input data into structured, well-defined data at the system's boundaries, you create a robust foundation for your application.&lt;/p&gt;

&lt;p&gt;Elixir's functional and concurrent nature makes it an ideal language for embracing this approach. While manual parsing is effective, libraries like Peri offer powerful tools to define and enforce schemas, ensuring consistency and reliability throughout your application.&lt;/p&gt;

&lt;p&gt;Embrace the power of parsing in Elixir, and let your code benefit from cleaner, more maintainable, and type-safe data handling.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Parsing and Validating Data in Elixir</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Tue, 18 Jun 2024 22:40:53 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/parsing-and-validating-data-in-elixir-1310</link>
      <guid>https://dev.to/zoedsoupe/parsing-and-validating-data-in-elixir-1310</guid>
      <description>&lt;p&gt;In the enchanting world of Elixir programming, data validation is a quest every developer embarks on. It's a journey through the land of schemas, types, and constraints, ensuring data integrity and correctness. Today, we'll explore four powerful artifacts: Ecto, Norm, Drops, and Peri. Each of these tools offers unique powers for taming your data. We'll delve into their strengths, use cases, and compare them to help you choose the right one for your quest.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Quest: Parse, Don't Validate
&lt;/h2&gt;

&lt;p&gt;Before we embark on our journey, let's discuss a guiding principle in functional programming: &lt;strong&gt;Parse, Don't Validate&lt;/strong&gt;. This pattern emphasizes transforming data into a well-defined structure as early as possible. By doing so, you avoid scattered, ad-hoc validation throughout your codebase, leading to clearer, more maintainable code. It's like casting a spell to organize the chaos of raw data into a neat, structured form.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Artifacts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Ecto
&lt;/h3&gt;

&lt;p&gt;Ecto is a robust toolkit primarily designed for interacting with databases. However, it also offers powerful capabilities for embedded schemas and schemaless changesets, making it versatile for data validation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Embedded Schemas
&lt;/h4&gt;

&lt;p&gt;Ecto allows defining schemas that don't map to a database table, ideal for validating nested data structures.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&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;Schema&lt;/span&gt;

  &lt;span class="n"&gt;embedded_schema&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
    &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&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;def&lt;/span&gt; &lt;span class="n"&gt;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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="no"&gt;User&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;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&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;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validate_required&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Schemaless Changesets
&lt;/h4&gt;

&lt;p&gt;For dynamic data, Ecto provides schemaless changesets, offering flexibility at the cost of increased complexity.&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;changeset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&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;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cast&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="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt; &lt;span class="n"&gt;data&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="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&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;Ecto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Changeset&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;validate_required&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:email&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Norm
&lt;/h3&gt;

&lt;p&gt;Norm focuses on defining and conforming to data structures with custom predicates, offering a clean syntax and powerful validation.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Norm&lt;/span&gt;

  &lt;span class="n"&gt;defschema&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;(%{&lt;/span&gt;
      &lt;span class="ss"&gt;name:&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_binary&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
      &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_integer&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;18&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;Norm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conform&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;"Jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:ok, %{name: "Jane", age: 25}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Drops
&lt;/h3&gt;

&lt;p&gt;Drops is a newer library that provides a rich set of tools for defining and validating schemas, leveraging Elixir's type system.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;UserContract&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="no"&gt;Drops&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Contract&lt;/span&gt;

  &lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="p"&gt;%{&lt;/span&gt;
      &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&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;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:filled?&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:age&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;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;gt?:&lt;/span&gt; &lt;span class="mi"&gt;18&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;UserContract&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;conform&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;"Jane"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:ok, %{name: "Jane", age: 21}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Peri
&lt;/h3&gt;

&lt;p&gt;Peri is inspired by Clojure's Plumatic Schema, focusing on validating raw maps with nested schemas and optional fields. It's designed to be powerful yet simple, embracing the "Parse, Don't Validate" pattern.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;MySchemas&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Peri&lt;/span&gt;

  &lt;span class="n"&gt;defschema&lt;/span&gt; &lt;span class="ss"&gt;:user&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="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:required&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:enum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;defschema&lt;/span&gt; &lt;span class="ss"&gt;:profile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;
    &lt;span class="ss"&gt;user:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:custom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="no"&gt;MySchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;bio:&lt;/span&gt; &lt;span class="ss"&gt;:string&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;MySchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&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;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;role:&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:ok, %{name: "John", age: 30, email: "john@example.com", role: :admin}}&lt;/span&gt;

&lt;span class="no"&gt;MySchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&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;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="s2"&gt;"thirty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:error, [%Peri.Error{path: [:age], message: "expected integer received \"thirty\""}]}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conditional and Composable Types in Peri
&lt;/h3&gt;

&lt;p&gt;Peri shines with its support for conditional and composable types, making it a powerful tool for complex validation scenarios.&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;AdvancedSchemas&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="no"&gt;Peri&lt;/span&gt;

  &lt;span class="n"&gt;defschema&lt;/span&gt; &lt;span class="ss"&gt;:user&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="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:cond&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;:integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:nil&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="ss"&gt;email:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:either&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:nil&lt;/span&gt;&lt;span class="p"&gt;}},&lt;/span&gt;
    &lt;span class="ss"&gt;preferences:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;:oneof&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:atom&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="no"&gt;AdvancedSchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&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;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;email:&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;preferences:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"coding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:reading&lt;/span&gt;&lt;span class="p"&gt;]})&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:ok, %{name: "Alice", age: 25, email: nil, preferences: ["coding", :reading]}}&lt;/span&gt;

&lt;span class="no"&gt;AdvancedSchemas&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user&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;"Bob"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;age:&lt;/span&gt; &lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; {:ok, %{name: "Bob", age: 17, email: nil, preferences: nil}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Each of these tools offers unique advantages and caters to different needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ecto&lt;/strong&gt; is great for data associated with databases but can handle schemaless and embedded data structures too.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Norm&lt;/strong&gt; provides a clean and powerful way to define and validate data structures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drops&lt;/strong&gt; leverages Elixir's type system and offers rich schema definitions and validations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Peri&lt;/strong&gt; emphasizes simplicity and power, supporting complex types and conditional validations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By understanding the strengths and weaknesses of each, you can choose the right tool for your data validation needs in Elixir. Happy coding, fellow sorcerers of Elixiria!&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/ecto/Ecto.html"&gt;Ecto Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/norm/Norm.html"&gt;Norm Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/drops/Drops.html"&gt;Drops Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hexdocs.pm/peri/Peri.html"&gt;Peri Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Feel free to dive into the source code and contribute to these projects to make Elixiria an even more magical place!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>elixir</category>
      <category>parsing</category>
      <category>programming</category>
    </item>
    <item>
      <title>Introdução a programação funcional com War game</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Sun, 30 Apr 2023 03:04:00 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/introducao-a-programacao-funcional-com-war-game-22l7</link>
      <guid>https://dev.to/zoedsoupe/introducao-a-programacao-funcional-com-war-game-22l7</guid>
      <description>&lt;p&gt;Durante um freela, o cliente pediu para que fosse implementado  o jogo &lt;code&gt;War&lt;/code&gt; em três linguagens de programação:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;Elixir&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Rust&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Clojure&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Essas são minhas linguagens favoritas, não necessariamente pela sintaxe mas pelo modelo diferente de se programar, pois todas pertencem ao paradigma funcional, mesmo que parcialmente como no caso de &lt;code&gt;Rust&lt;/code&gt;, mas também possuem suas peculiaridades.&lt;/p&gt;

&lt;p&gt;Durante essa série de artigos, será explicado minuciosamente as decisões de implementação, sempre tentando usar o máximo de cada linguagem de programação.&lt;/p&gt;

&lt;p&gt;Porém antes, nos artigos iniciais, gostaria de introduzir as linguagens de programação utilizadas e o paradigma funcional, além de descrever como funciona o jogo de cartas War.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boas vindas ao Paradigma Funcional
&lt;/h2&gt;

&lt;p&gt;Muitas pessoas se assustam quando o tópico é programação funcional (FP). De fato, tanto no mercado quanto no ensino superior, o paradigma padrão a ser usado é o imperativo/estrutural em conjunto com o Orientado a Objetos (OO), mas o que essa sopa de palavras quer dizer, na prática?&lt;/p&gt;

&lt;h2&gt;
  
  
  Senta que lá vem história...
&lt;/h2&gt;

&lt;p&gt;Vocês já devem ter ouvido que Alan Turing, pai da computação moderna, descreveu um modelo computacional no qual todos (bem, quase todos...) os sistemas computacionais se baseiam até hoje, certo? Esse modelo foi descrito conforme a &lt;code&gt;Máquina de Turing&lt;/code&gt;. Mas como ela funciona?&lt;/p&gt;

&lt;h3&gt;
  
  
  Máquina de Turing
&lt;/h3&gt;

&lt;p&gt;A Máquina de Turing é um modelo matemático descrito na tese de Church-Turing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Falaremos sobre Alonzo Church logo a seguir!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse modelo matemático tem a capacidade de descrever qualquer algoritmo, apesar de ser um modelo relativamente simples.&lt;/p&gt;

&lt;p&gt;Para entendê-la, imagine uma fita horizontal, de tamanho variável, separada por células que possuem uma marcação, que se chama "alfabeto" da máquina. Nesse exemplo vamos usar &lt;code&gt;0&lt;/code&gt; e &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Em conjunto existe uma máquina, imagine uma caixa, onde possui uma agulha, que é a "cabeça" da máquina, permitindo ler e modificar a marcação da célula atual. A mesma consegue se movimentar por essa fita e realizar comandos por ela, como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mova para a esquerda;&lt;/li&gt;
&lt;li&gt;mova para a direita;&lt;/li&gt;
&lt;li&gt;deixe o valor da célula como está;&lt;/li&gt;
&lt;li&gt;modifique a célula;&lt;/li&gt;
&lt;li&gt;apague a marcação desta célula;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A célula onde a caixa está seria seu estado atual e o propósito da máquina é chegar no "estado de espera", que representaria o final do algoritmo. Portanto, os valores das marcações nas células após a execução dos comandos direcionados à caixa representa a solução da computação/algoritmo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cálculo Lambda
&lt;/h3&gt;

&lt;p&gt;Lembra do Alonzo Church citado anteriormente? O mesmo foi orientador do Turing e também tinha proposto um modelo matemático para computações, diferente da máquina de Turing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hoje em dia entendemos que os dois modelos são equivalentes. Logo, toda computação realizada por uma Máquina de Turing pode ser computada pelo Cálculo Lambda e vice-versa!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;O modelo consiste na definição de termos e na &lt;a href="https://pt.wikipedia.org/wiki/C%C3%A1lculo_lambda#Redu%C3%A7%C3%A3o" rel="noopener noreferrer"&gt;redução&lt;/a&gt; dos mesmos. Na sua versão mais simples, descrita na década de 30, os termos são construídos seguindo as seguintes regras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; variável, que representa um parâmetro ou um valor lógico/matemático;&lt;/li&gt;
&lt;li&gt;abstração, que representa a definição de uma função, como: &lt;code&gt;λx. M&lt;/code&gt;, onde &lt;code&gt;M&lt;/code&gt; é um outro termo qualquer e &lt;code&gt;x&lt;/code&gt; um parâmetro;&lt;/li&gt;
&lt;li&gt;aplicação de uma função, como &lt;code&gt;M N&lt;/code&gt;, que aplica a função &lt;code&gt;M&lt;/code&gt; (um termo) sobre outro termo &lt;code&gt;N&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esse modelo matemático é a base do paradigma funcional! A seguir, vamos implementar lógica booleana usando apenas as regras citadas acima:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;true = λx.λ.y x
false = λx.λy y

not = λx.x false true
and = λx.λy.x y false
or = λx.λy.x true y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para ficar mais entendível, vamos usar uma linguagem de programação de alto nível (&lt;code&gt;JavaScript&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TRUE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;FALSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se utilizando das funções lambda (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" rel="noopener noreferrer"&gt;arrow functions&lt;/a&gt;), que possuem esse nome de forma proposital, criamos duas funções que representam os valores lógicos "verdadeiro", que retorna o primeiro termo recebido, e "falso" , que retorna o segundo termo passado como parâmetro.&lt;/p&gt;

&lt;p&gt;Vamos agora criar as operações de negação (&lt;code&gt;not&lt;/code&gt;), conjunção (&lt;code&gt;and&lt;/code&gt;) e disjunção inclusiva (&lt;code&gt;or&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;termo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;termo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// NOT(TRUE) - [Function: FALSE]&lt;/span&gt;
&lt;span class="c1"&gt;// NOT(FALSE) - [Function: TRUE]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A negação é a definição de uma função lambda onde recebe um termo, e aplica esse termo aos termos &lt;code&gt;FALSE&lt;/code&gt; e &lt;code&gt;TRUE&lt;/code&gt;, respectivamente. &lt;/p&gt;

&lt;p&gt;Como &lt;code&gt;TRUE&lt;/code&gt; retorna o primeiro termo recebido, caso o termo passado para &lt;code&gt;NOT&lt;/code&gt; seja &lt;code&gt;TRUE&lt;/code&gt;, o termo a ser resolvido é &lt;code&gt;FALSE&lt;/code&gt;, e contrário acontece caso o parâmetro de &lt;code&gt;NOT&lt;/code&gt; seja &lt;code&gt;FALSE&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Agora, vamos para a conjunção lógica (&lt;code&gt;and&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AND&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;termo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;outro_termo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;termo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;outro_termo&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// AND(TRUE)(TRUE) - [Function: TRUE)&lt;/span&gt;
&lt;span class="c1"&gt;// AND(TRUE)(FALSE) - [Function: FALSE)&lt;/span&gt;
&lt;span class="c1"&gt;// AND(FALSE)(TRUE) - [Function: FALSE)&lt;/span&gt;
&lt;span class="c1"&gt;// AND(FALSE)(FALSE) - [Function: FALSE)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se utilizando do que chamamos de "avaliação de curto-circuito", o termo &lt;code&gt;AND&lt;/code&gt; recebe dois termos e aplica o primeiro sobre o segundo e o termo &lt;code&gt;FALSE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por fim, vamos implementar a disjunção lógica (&lt;code&gt;or&lt;/code&gt;), que é bem semelhante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;OR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;termo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;outro_termo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;termo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TRUE&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;outro_termo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// OR(TRUE)(TRUE) - [Function: TRUE)&lt;/span&gt;
&lt;span class="c1"&gt;// OR(TRUE)(FALSE) - [Function: TRUE)&lt;/span&gt;
&lt;span class="c1"&gt;// OR(FALSE)(TRUE) - [Function: TRUE)&lt;/span&gt;
&lt;span class="c1"&gt;// OR(FALSE)(FALSE) - [Function: FALSE)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essa definições, podemos expandir ainda mais e definir a operação de controle de fluxo &lt;code&gt;if&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IF_THEN_ELSE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;predicado&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;else_branch&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;predicado&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;else_branch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// IF_THEN_ELSE(TRUE)(1)(2) - 1&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(FALSE)(1)(2) - 2&lt;/span&gt;

&lt;span class="c1"&gt;// IF_THEN_ELSE(NOT(TRUE))(1)(2) - 2&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(NOT(FALSE))(1)(2) - 1&lt;/span&gt;

&lt;span class="c1"&gt;// IF_THEN_ELSE(AND(TRUE)(TRUE))(1)(2) - 1&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(AND(TRUE)(FALSE))(1)(2) - 2&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(AND(FALSE)(TRUE))(1)(2) - 2&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(AND(FALSE)(FALSE))(1)(2) - 2&lt;/span&gt;

&lt;span class="c1"&gt;// IF_THEN_ELSE(OR(TRUE)(TRUE))(1)(2) - 1&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(OR(TRUE)(FALSE))(1)(2) - 1&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(OR(FALSE)(TRUE))(1)(2) - 1&lt;/span&gt;
&lt;span class="c1"&gt;// IF_THEN_ELSE(OR(FALSE)(FALSE))(1)(2) - 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A operação &lt;code&gt;IF&lt;/code&gt; recebe um primeiro termo que chamamos de "predicado", que será avaliado em &lt;code&gt;TRUE&lt;/code&gt; ou &lt;code&gt;FALSE&lt;/code&gt;. Caso o termo avaliado seja &lt;code&gt;TRUE&lt;/code&gt;, o termo &lt;code&gt;then&lt;/code&gt; é retornado, caso contrário o termo &lt;code&gt;else_branch&lt;/code&gt; é devolvida.&lt;/p&gt;

&lt;p&gt;O que acabamos de implementar é equivalente à:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;predicado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;then&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;else_branch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&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="nx"&gt;predicado&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="nx"&gt;then&lt;/span&gt;&lt;span class="p"&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;else_branch&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;h2&gt;
  
  
  O que torna um linguagem "funcional"?
&lt;/h2&gt;

&lt;p&gt;Para uma linguagem de programação ser considerada funcional, ela precisa atender alguns requisitos. É importante notar, que mesmo que uma linguagem não pertença ao paradigma funcional, a mesma pode implementar funcionalidades funcionais, como &lt;code&gt;Python&lt;/code&gt; e &lt;code&gt;JavaScript&lt;/code&gt;, que pertencem ao paradigma Orientado a Objetos porém possuem características do paradigma funcional!&lt;/p&gt;

&lt;p&gt;Vamos entender esses requisitos!&lt;/p&gt;

&lt;h3&gt;
  
  
  Imutabildiade
&lt;/h3&gt;

&lt;p&gt;O conceito mais básico de uma linguagem funcional é ter seus valores imutáveis. Isso significa que não é possível modificar o valor de termo em memória, apenas criar novos valores a partir dele. Alguns exemplos usando &lt;code&gt;TypeSript&lt;/code&gt; e &lt;code&gt;Elixir&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Joe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;431&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// válido&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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="c1"&gt;// válido&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// inválido&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma das maneiras mais primitivas de exigir imutabilidade dentro do universo &lt;code&gt;JS/TS&lt;/code&gt; é usando &lt;code&gt;Object.freeze&lt;/code&gt;. Essa função força um objeto a ter um certo formato, porém permite que os valores de uma chave válida seja modificada em memória, o que não queremos!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ReadOnly&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;um-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dantas&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="c1"&gt;// erro de compilação&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// erro de compilação&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E caso quisermos atualizar nosso &lt;code&gt;user&lt;/code&gt;?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;User&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;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;({},&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;outro-id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// false&lt;/span&gt;

&lt;span class="nx"&gt;newUser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// erro de compilação&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora sim temos imutabilidade! Mas me parece um tanto quanto verboso 🤔. Vamos ver o mesmo exemplo em &lt;code&gt;Elixir&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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@enforce_keys&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;defstruct&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&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;update_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&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;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&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="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt;&lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="s2"&gt;"123"&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;"Joe"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"4321"&lt;/span&gt; &lt;span class="c1"&gt;# erro de compilação&lt;/span&gt;

&lt;span class="n"&gt;new_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;%{&lt;/span&gt;&lt;span class="ss"&gt;id:&lt;/span&gt; &lt;span class="s2"&gt;"4321"&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;"Dantas"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;new_user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"123"&lt;/span&gt; &lt;span class="o"&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;Neste exemplo foi criado um &lt;code&gt;Struct&lt;/code&gt; para forçar um formato, porém a mesma lógica se aplica a hashmaps planos! Todo termo em &lt;code&gt;Elixir&lt;/code&gt; é imutável, ou seja, sempre que precisar atualizar um termo, um novo será gerado. As expressões na linguagem já foram implementadas para retornar novos termos, sendo muito menos verboso!&lt;/p&gt;

&lt;h3&gt;
  
  
  Funções como valores de primeira classe
&lt;/h3&gt;

&lt;p&gt;Outra característica básica de uma linguagem de programação funcional é que as funções são valores da mesma ordem dos tipos primitivos como &lt;code&gt;integer&lt;/code&gt; ou &lt;code&gt;string&lt;/code&gt;. Isso significa que funções podem ser passadas como parâmetro de outra função ou serem retornadas de outra função. Vamos acompanhar alguns exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inc&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [2, 3, 4, 5, 6]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passamos a função &lt;code&gt;inc&lt;/code&gt;, que incrementa o valor de um termo, como parâmetro da função &lt;code&gt;map&lt;/code&gt;, que itera sobre um array de termos e aplica a função recebida em cada termo, retornando um novo valor modificado. Vamos ver uma função retornando outra:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;soma_parcial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&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="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;soma5&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;soma_parcial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;soma5&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="c1"&gt;// 15;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo criamos uma função &lt;code&gt;soma _parcial&lt;/code&gt;, que recebe um número e devolve uma outra função, que também recebe um número, onde a avaliação dessa ultima retorna a soma dos dois números.&lt;/p&gt;

&lt;p&gt;Chamamos essa técnica de &lt;code&gt;closure&lt;/code&gt;, quando uma função interna utiliza o contexto do nível acima dentro do próprio escopo. O termo &lt;code&gt;x&lt;/code&gt;, criado pelo contexto da função &lt;code&gt;soma_parcial&lt;/code&gt; fica guardado na memória até a segunda função que é retornada, usá-lo.&lt;/p&gt;

&lt;p&gt;Portanto, quando criamos o termo &lt;code&gt;soma5&lt;/code&gt;, fazemos o que é chamado de "aplicação parcial", pois podemos entender que a função &lt;code&gt;soma_parcial&lt;/code&gt; recebe dois parâmetros, porém apenas passamos o primeiro! Neste caso &lt;code&gt;x&lt;/code&gt; terá o valor de &lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Como o retorno da aplicação parcial é uma outra função, &lt;code&gt;soma5&lt;/code&gt; pode receber outro termo, que no exemplo passamos &lt;code&gt;10&lt;/code&gt;, no que resulta na avaliação de &lt;code&gt;x = 5 + y = 10&lt;/code&gt;, sendo retornado &lt;code&gt;15&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Funções puras e Transparência Referencial
&lt;/h3&gt;

&lt;p&gt;Uma função pura é uma função que dado o mesmo termo como parâmetro, o mesmo resultado será retornado. Para ser pura, a função também não pode modificar o contexto externo dela. Vamos ver alguns exemplos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;somaX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;y&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="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&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;Essa função é impura, pois a mesma modifica/utiliza o contexto externo a si mesma!&lt;/p&gt;

&lt;p&gt;Um exemplo claro de função pura são as operações matemáticas, como soma, multiplicação, subtração e divisão. Todas elas recebem dois parâmetros e aplica a operação sobre os dois. Dado os mesmos parâmetros, o mesmo termo será retornado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;soma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;soma&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nf"&gt;soma&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="c1"&gt;// ... assim infinitamente&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, conseguimos introduzir outro conceito: Transparência Referencial, acontece quando podemos substituir a chamada de uma função pelo seu retorno, uma vez que dado o mesmo parâmetro, será retornado o mesmo resultado. Uma função só pode sofrer transparência referencial quando a mesma for pura!&lt;/p&gt;

&lt;h3&gt;
  
  
  Recursão
&lt;/h3&gt;

&lt;p&gt;Como linguagens de programação funcionais são imutáveis, iterar sobre uma coleção de termos usando &lt;code&gt;loops&lt;/code&gt; perde seu significado. Por isso, o mais comum quando precisamos iterar sob uma coleção é usarmos recursão, que é o ato de uma função chamar a si mesma, criando uma pilha de execução! Vamos ver a diferença entre loops e recursão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fatorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&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="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;fact&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;Com um &lt;code&gt;for&lt;/code&gt; loop, criamos uma variável de estado &lt;code&gt;fact&lt;/code&gt; que é modificada a cada iteração do loop com um novo valor do fatorial calculado. Vamos ver como seria a implementação com recursão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&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="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;factorial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&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;Apesar de ter menos código, a lógica por trás da recursão pode ser um tanto quanto mais complexa. Toda recursão precisa de uma "condição de parada", que é uma condição base para que a recursão seja finalizada. No caso do cálculo do fatorial, o caso base é quando o número for menor que &lt;code&gt;2&lt;/code&gt;, onde será retornado o valor &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Depois, temos a definição da recursão, onde o resultado é o termo &lt;code&gt;number&lt;/code&gt; multiplicado pelo resultado da chamada &lt;code&gt;factorial(number - 1)&lt;/code&gt;. Veja na imagem a seguir a sequência de avaliação da recursão:&lt;/p&gt;

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

&lt;p&gt;Conforme a imagem, é possível notar que é criada uma pilha  de avaliação, onde a cada resultado a pilha diminui, fazendo o caminho "inverso" da avaliação.&lt;/p&gt;

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

&lt;p&gt;Neste artigo entendemos a história da programação funcional e as características que fazem com que uma linguagem de programação possa ser considerada "funcional". &lt;/p&gt;

&lt;p&gt;Vimos que a base da programação funcional é a definição e aplicação de funções, num modelo matemático, podendo ser funções puras ou não.&lt;/p&gt;

&lt;p&gt;No próximo artigo, as linguagens &lt;code&gt;Elixir&lt;/code&gt;, &lt;code&gt;Rust&lt;/code&gt; e &lt;code&gt;Clojure&lt;/code&gt; serão introduzidas, seguida pela introdução ao jogo de cartas War!&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=dNRDvLACg5Q" rel="noopener noreferrer"&gt;Máquina de Turing Explicada - Computerphile (EN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eis11j_iGMs" rel="noopener noreferrer"&gt;Calculus Lambda - Computerphile (EN)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@ahlechandre/lambda-calculus-com-javascript-5db88c3b45a" rel="noopener noreferrer"&gt;Lambda Calculus com JavaScript (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://mundoeducacao.uol.com.br/matematica/logica-matematica-1.htm" rel="noopener noreferrer"&gt;Lógica matemática (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://segredo.dev/o-que-e-imutabilidade/" rel="noopener noreferrer"&gt;O que é imutabildiade (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://natahouse.com/pt/qual-e-a-melhor-maneira-de-utilizar-as-funcoes-puras" rel="noopener noreferrer"&gt;Qual é a melhor maneira de se utilizar funções puras (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pt.stackoverflow.com/questions/74992/programa%C3%A7%C3%A3o-funcional-e-transpar%C3%AAncia-referencial" rel="noopener noreferrer"&gt;Programação Funcional e Transparência Referencial (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://henriquebraga92.medium.com/algoritmos-recursividade-recurs%C3%A3o-c4aff7291bb4" rel="noopener noreferrer"&gt;Algoritmos: entendendo recursividade (PTBR)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>algorithms</category>
      <category>functional</category>
      <category>wargame</category>
    </item>
    <item>
      <title>Identificação de caracteres Unicode em Elixir</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Thu, 30 Sep 2021 07:15:12 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/identificacao-de-caracteres-unicode-em-elixir-f4j</link>
      <guid>https://dev.to/zoedsoupe/identificacao-de-caracteres-unicode-em-elixir-f4j</guid>
      <description>&lt;p&gt;&lt;em&gt;AVISO INICIAL&lt;/em&gt;&lt;br&gt;
Este artigo é uma tradução (não direta e com adaptações) de um artigo publicado no blog do &lt;a href="//exercism.io"&gt;exercism.io&lt;/a&gt; pelo &lt;em&gt;Percy Grunwald&lt;/em&gt;. O artigo original pode ser encontrado por &lt;a href="https://exercism.org/blog/unicode-matching-in-elixir"&gt;esse link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Uma das maiores vantagens de usar uma linguagem expressiva como Elixir é a possibilidade de solucionar problemas de forma clara, explícita e com um toque de elegância devido a sua sintaxe!&lt;/p&gt;

&lt;p&gt;Hoje vou mostrar como podemos identificar ou "casar" (&lt;em&gt;it's a match!&lt;/em&gt;) caracteres pertencentes ao padrão Unicode. Para quem não conhece ou não sabe em detalhes, &lt;a href="https://unicode.org/standard/WhatIsUnicode.html"&gt;Unicode&lt;/a&gt; é uma solução criada para evitar o conflito entre diferentes codificadores de caracteres.&lt;br&gt;
Isto é, cada um dos &lt;a href="https://en.wikipedia.org/wiki/Character_encoding#Common_character_encodings"&gt;codificadores de caracteres&lt;/a&gt; implementava números diferentes para representar cada símbolo de uma ou mais línguas.&lt;/p&gt;

&lt;p&gt;Porém, nenhum deles realmente conseguia abranger as extensas possibilidades de combinações, letras, símbolos e pontuações que centenas de línguas possuem. Por isso nasce o Unicode ou, código único (&lt;em&gt;unique code&lt;/em&gt;), onde cada caractere recebe um identificador único, não sendo restingido por nenhuma plataforma, programa ou linguagem!&lt;/p&gt;

&lt;p&gt;Ok, mas vamos falar de Elixir agora! Já de ínicio vou propor um desafio:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Implemente uma função &lt;code&gt;frequencia/1&lt;/code&gt; que dada uma lista de strings devolva a frequência de cada caractere. Lembre que as strings podem estar descritas em qualquer linguagem!"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Exemplo:&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;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Frequencia&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;frequencia&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"ciências"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"naturais"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;%{&lt;/span&gt;
  &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"i"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"ê"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"c"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"n"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"r"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"s"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"t"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s2"&gt;"u"&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;Aqui estão alguns casos de teste:&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="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Eorum"&lt;/span&gt; &lt;span class="s2"&gt;"argumentum"&lt;/span&gt; &lt;span class="s2"&gt;"audiri"&lt;/span&gt; &lt;span class="s2"&gt;"posse"&lt;/span&gt; &lt;span class="s2"&gt;"per"&lt;/span&gt; &lt;span class="s2"&gt;"raedam"&lt;/span&gt; &lt;span class="s2"&gt;"multum"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"When"&lt;/span&gt; &lt;span class="s2"&gt;"transplanting"&lt;/span&gt; &lt;span class="s2"&gt;"seedlings"&lt;/span&gt; &lt;span class="s2"&gt;"candied"&lt;/span&gt; &lt;span class="s2"&gt;"teapots"&lt;/span&gt; &lt;span class="s2"&gt;"will"&lt;/span&gt; &lt;span class="s2"&gt;"make"&lt;/span&gt; &lt;span class="s2"&gt;"the"&lt;/span&gt; &lt;span class="s2"&gt;"task"&lt;/span&gt; &lt;span class="s2"&gt;"easier"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"El"&lt;/span&gt; &lt;span class="s2"&gt;"zorro"&lt;/span&gt; &lt;span class="s2"&gt;"del"&lt;/span&gt; &lt;span class="s2"&gt;"sombrero"&lt;/span&gt; &lt;span class="s2"&gt;"de"&lt;/span&gt; &lt;span class="s2"&gt;"copa"&lt;/span&gt; &lt;span class="s2"&gt;"le"&lt;/span&gt; &lt;span class="s2"&gt;"susurró"&lt;/span&gt; &lt;span class="s2"&gt;"al"&lt;/span&gt; &lt;span class="s2"&gt;"oído"&lt;/span&gt; &lt;span class="s2"&gt;"del"&lt;/span&gt; &lt;span class="s2"&gt;"conejo"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Estava"&lt;/span&gt; &lt;span class="s2"&gt;"escurecendo"&lt;/span&gt; &lt;span class="s2"&gt;"e"&lt;/span&gt; &lt;span class="s2"&gt;"ainda"&lt;/span&gt; &lt;span class="s2"&gt;"não"&lt;/span&gt; &lt;span class="s2"&gt;"estávamos"&lt;/span&gt; &lt;span class="s2"&gt;"lá"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"E"&lt;/span&gt; &lt;span class="s2"&gt;"ʻike"&lt;/span&gt; &lt;span class="s2"&gt;"ʻoe"&lt;/span&gt; &lt;span class="s2"&gt;"i"&lt;/span&gt; &lt;span class="s2"&gt;"ke"&lt;/span&gt; &lt;span class="s2"&gt;"alahaka"&lt;/span&gt; &lt;span class="s2"&gt;"ānuenue"&lt;/span&gt; &lt;span class="s2"&gt;"ma"&lt;/span&gt; &lt;span class="s2"&gt;"hope"&lt;/span&gt; &lt;span class="s2"&gt;"o"&lt;/span&gt; &lt;span class="s2"&gt;"ka"&lt;/span&gt; &lt;span class="s2"&gt;"ua"&lt;/span&gt; &lt;span class="s2"&gt;"ʻana"&lt;/span&gt; &lt;span class="s2"&gt;"o"&lt;/span&gt; &lt;span class="s2"&gt;"nā"&lt;/span&gt; &lt;span class="s2"&gt;"pōpoki"&lt;/span&gt; &lt;span class="s2"&gt;"a"&lt;/span&gt; &lt;span class="s2"&gt;"me"&lt;/span&gt; &lt;span class="s2"&gt;"nā"&lt;/span&gt; &lt;span class="s2"&gt;"ʻīlio"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Σήμερα"&lt;/span&gt; &lt;span class="s2"&gt;"είναι"&lt;/span&gt; &lt;span class="s2"&gt;"η"&lt;/span&gt; &lt;span class="s2"&gt;"μέρα"&lt;/span&gt; &lt;span class="s2"&gt;"που"&lt;/span&gt; &lt;span class="s2"&gt;"θα"&lt;/span&gt; &lt;span class="s2"&gt;"ξέρω"&lt;/span&gt; &lt;span class="s2"&gt;"επιτέλους"&lt;/span&gt; &lt;span class="s2"&gt;"τι"&lt;/span&gt; &lt;span class="s2"&gt;"γεύση"&lt;/span&gt; &lt;span class="s2"&gt;"έχει"&lt;/span&gt; &lt;span class="s2"&gt;"το"&lt;/span&gt; &lt;span class="s2"&gt;"τούβλο"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vai lá, tenta implementar! Precisa de tempo? Tudo bem, eu espero...&lt;br&gt;
&lt;a href="https://i.giphy.com/media/QUmpqPoJ886Iw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QUmpqPoJ886Iw/giphy.gif" alt="um calango na cadeira de balanço, apenas esperando..." width="320" height="221"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Identificação de letras em Elixir
&lt;/h2&gt;

&lt;p&gt;5 minutos depois... 10 anos depois... Podemos fazer em conjunto! Vamos tentar com testes mais simples!&lt;/p&gt;

&lt;p&gt;Partindo do básico, como podemos determinar que &lt;code&gt;"z"&lt;/code&gt; é uma letra?&lt;/p&gt;

&lt;p&gt;Obs: Existe uma funcionalidade na linguagem Elixir que torna a resolução desse exercício algo, digamos... único e intrigante! Nada prático, mas interessante! Deixarei uma demonstração no final deste artigo!&lt;/p&gt;

&lt;p&gt;O caminho mais "comum" seria escolher o uso de &lt;a href="https://www.regular-expressions.info/quickstart.html"&gt;expressões regulares&lt;/a&gt;. Uma dica: o site &lt;a href="https://regexr.com/"&gt;regexr.com&lt;/a&gt; será seu guia para entender cada modificador e sintaxes específicas.&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;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|[a-z]|&lt;/span&gt;&lt;span class="p"&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;Realmente bem simples, mas e a letra &lt;code&gt;"Z"&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Ah, fácil também:&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;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|[A-Za-z]|&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|[a-z]|i&lt;/span&gt;&lt;span class="p"&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;No segundo exemplo, é adicionado o nosso primeiro modificador: &lt;code&gt;i&lt;/code&gt; &lt;a href="https://hexdocs.pm/elixir/Regex.html#module-modifiers"&gt;modificador caseless&lt;/a&gt; que permite a não diferenciação entre letras maiúsculas ou minúsculas.&lt;/p&gt;

&lt;p&gt;Tudo bem, por enquanto está bem simples, que tal testarmos com um caractere com acento, como &lt;code&gt;"ê"&lt;/code&gt;. Bem, esse caractere também é uma letra, entã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="n"&gt;iex&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;match?&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="sr"&gt;~r|[a-z]|i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opa, estranho, mas esperado, uma vez que &lt;code&gt;"ê"&lt;/code&gt; é um caractere especial. Uma solução poderia ser usar uma expressão regular que falhe caso encontre um caractere especial. Algo como (de forma simplificada):&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;iex&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;match?&lt;/span&gt; &lt;span class="s2"&gt;"É"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|[a-z0-9]|i&lt;/span&gt;
&lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É uma solução válida, mas muito frágil. Como poderíamos cobrir todos os casos possíveis? Fora que seria necessário testar se cada caractere é especial ou não, identificá-lo manualmente e contabilizar sua frequência. Definitivamente tá longe de ser o caminho feliz e muito menos elegante.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expressões regulares com suporte a Unicode
&lt;/h3&gt;

&lt;p&gt;Existe um modificador para expressões regulares que inclui e permite a identificação de caracteres Unicode numa expressão regular. Esse modificador é o &lt;a href="https://hexdocs.pm/elixir/Regex.html#module-modifiers"&gt;&lt;code&gt;u&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;unicode (&lt;code&gt;u&lt;/code&gt;) - habilita a identificação de padrões Unicode específicos como &lt;code&gt;\p&lt;/code&gt; e modifica os já conhecidos operadores &lt;code&gt;\w&lt;/code&gt;, &lt;code&gt;\W&lt;/code&gt; e &lt;code&gt;\s&lt;/code&gt; e similares para que possam detectar caracteres Unicode.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;De fato o modificador &lt;code&gt;u&lt;/code&gt; e em &lt;a href="https://www.regular-expressions.info/unicode.html"&gt;especial o operador &lt;code&gt;\p&lt;/code&gt;&lt;/a&gt;, torna nossa solução bem elegante. O operador &lt;code&gt;\p&lt;/code&gt; permite a identificação de um &lt;em&gt;grafema&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Grafema é a unidade fundamental de um sistema de escrita que pode representar um fonema em escritas alfabéticas, uma ideia numa escrita ou até uma sílaba nas escritas silábicas. Pode ser entendido como um conjunto de caracteres.&lt;/p&gt;

&lt;p&gt;Com este operador é possível detectar um grafema dentro de qualquer &lt;a href="https://en.wikipedia.org/wiki/Unicode_character_property#General_Category"&gt;categoria de caracteres Unicode&lt;/a&gt;. Não incluindo apenas as subcategorias &lt;code&gt;Ll&lt;/code&gt; &lt;a href="https://www.compart.com/en/unicode/category/Ll"&gt;(letra, caixa baixa)&lt;/a&gt; ou &lt;code&gt;Sc&lt;/code&gt; &lt;a href="https://www.compart.com/en/unicode/category/Sc"&gt;(símbolo, moeda)&lt;/a&gt;, mas também as categorias mães &lt;code&gt;L&lt;/code&gt; (letra) e &lt;code&gt;S&lt;/code&gt; (símbolo).&lt;/p&gt;

&lt;p&gt;Em outras palavras, você consegue identificar qualquer caractere, em qualquer tipografia em qualquer &lt;a href="https://www.unicode.org/faq/basic_q.html"&gt;língua humana suportada pelo Unicode&lt;/a&gt; com o padrão &lt;code&gt;\p{L}&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Vamos aos testes então!&lt;/p&gt;

&lt;p&gt;Letras latinas comuns do português são facilmente detectadas:&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;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"o"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"O"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&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;Caracteres latinos com acentos agudos ou trema também não causam nenhum problema:&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;iex&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;match?&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="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="n"&gt;iex&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;match?&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="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&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;Mas então esse padrão não acusaria verdadeiro para qualquer caractere? Veja a seguir:&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;iex&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;match?&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="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;iex&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;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&amp;amp;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Entendido. Esses grafemas parecem letras, mas não são! Mas e quanto ao nosso problema com internacionalizações? Bem...&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;# Grafema que representa "casa" ou "construção" em japônes&lt;/span&gt;
&lt;span class="n"&gt;iex&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;match?&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="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;true&lt;/span&gt;

&lt;span class="c1"&gt;# Grafema que significa "eu" em cingalês&lt;/span&gt;
&lt;span class="n"&gt;iex&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;match?&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="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Aplicando a identificação de caracteres Unicode ao nosso desafio
&lt;/h2&gt;

&lt;p&gt;Agora temos todas as ferramentas necessárias para nos ajudar a decidir se um determinado grafema é ou não uma letra. A seguir, temos uma implementação inicial:&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;Frequencia&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;frequencia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentencas&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;sentencas&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;sentencas&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;separar_grafemas&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;contar_letras&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;defp&lt;/span&gt; &lt;span class="n"&gt;separar_grafemas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sentencas&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;sentencas&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="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;graphemes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# sim, esta função é nativa :P&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;A função principal é a &lt;code&gt;contar_letras/1&lt;/code&gt;, que aplicará a expressão regular &lt;code&gt;~r|\p{L}|u&lt;/code&gt; em cada grafema, decidindo se é ou não uma letra! Aqui está uma implementação de exemplo:&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;defmodule&lt;/span&gt; &lt;span class="no"&gt;Frequencia&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;contar_letras&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafemas&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;for&lt;/span&gt; &lt;span class="n"&gt;grafema&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;grafemas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;letra?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafema&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="ss"&gt;reduce:&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;acc&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grafema&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;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&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;defp&lt;/span&gt; &lt;span class="n"&gt;letra?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafema&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="no"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;~r|\p{L}|u&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nossa função aceita uma lista de grafemas e por meio de &lt;a href="https://hexdocs.pm/elixir/1.12/Kernel.SpecialForms.html#for/1"&gt;compreensões de lista&lt;/a&gt;, iteramos sobre cada elemento da lista, apenas mantendo os elementos que passarem no teste (a chamada da função auxiliar &lt;code&gt;letra?/1&lt;/code&gt;) e reduzimos a lista em um mapa, onde cada chave é uma letra e seu valor é a frequência em que tal caractere aparece!&lt;/p&gt;

&lt;h2&gt;
  
  
  Bônus: Sequências!
&lt;/h2&gt;

&lt;p&gt;No começo deste artigo eu mencionei que Elixir possibilita uma forma bem mais "diferentona" de se resolver esse problema. Isso se deve ao fato de que a própria linguagem em si, suporta caracteres Unicode.&lt;/p&gt;

&lt;p&gt;Uma das funcionalidades mais interessantes da linguagem são as sequências! Dado um valor inicial, um valor final e um "passo", é gerado um conjunto que representa aquela sequência (de forma inclusiva).&lt;/p&gt;

&lt;p&gt;Exemplos!&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;iex&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;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&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="mi"&gt;2&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;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;iex&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;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;//-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;2&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;Mas isso é muito comum, vamos incrementar essa funcionaldiade! Que tal criarmos sequências para letras? A expressão &lt;code&gt;?&lt;/code&gt; antes dos caracteres permite que recupermos seus códigos em decimal:&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;iex&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;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;?a&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sx"&gt;?c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'abc'&lt;/span&gt;

&lt;span class="n"&gt;iex&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;to_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sx"&gt;?c&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sx"&gt;?a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'cba'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uhumm... Mas onde quero chegar com isso? Lembra que Elixir suporta nativamente caracteres Unicode (infelizmente não para criação de variáveis haha)? Vamos usar isso entã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="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;?é&lt;/span&gt;
&lt;span class="mi"&gt;233&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;?ﬦ&lt;/span&gt;
&lt;span class="mi"&gt;64294&lt;/span&gt;

&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="sx"&gt;?😅&lt;/span&gt;
&lt;span class="mi"&gt;128517&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Possível solução para o problema
&lt;/h3&gt;

&lt;p&gt;Com um algumas composições de funções, podemos solucionar nosso problema, não de uma maneira eficiente, não de uma maneira totalmente legível, mas certamente com toda a elegância possí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="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Frequencia&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# [...]&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;contar_letras&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafemas&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grafemas&lt;/span&gt;&lt;span class="p"&gt;,&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;grafema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class="n"&gt;codigo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
        &lt;span class="n"&gt;grafema&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;to_charlist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# charlists são literalmente listas de caracteres&lt;/span&gt;
        &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# logo, precisamos apenas do cabeçalho da mesma, ou seja, um "codepoint"&lt;/span&gt;

      &lt;span class="k"&gt;cond&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;caixa_alta?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&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;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grafema&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;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;caixa_baixa?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&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;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grafema&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;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;latin_A_e_B?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&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;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;grafema&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;amp;&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="no"&gt;true&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;
      &lt;span class="k"&gt;end&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;defp&lt;/span&gt; &lt;span class="n"&gt;caixa_alta?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sx"&gt;?A&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sx"&gt;?Z&lt;/span&gt; &lt;span class="c1"&gt;# 65..90&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;caixa_baixa?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sx"&gt;?a&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sx"&gt;?z&lt;/span&gt; &lt;span class="c1"&gt;# 97..122&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;latin_A_e_B?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ch&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="n"&gt;ch&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="sx"&gt;?À&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="sx"&gt;?ɏ&lt;/span&gt; &lt;span class="c1"&gt;# 192..591&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Descobrimos duas maneiras incríveis de detectar grafemas de múltiplas nacionalidades! Ok, talvez uma delas seja um tanto quanto.. exótica eu diria, mas ainda sim divertida de se implementar!&lt;/p&gt;

&lt;p&gt;Essas funcuionalidades permitam que um leque de outras funcionalidades ou problemas sejam contruídos e solucionados com uma expressividade clara, sucinta e simples.&lt;/p&gt;

&lt;p&gt;Vale lembrar que no exemplo usando sequências eu limitei os códigos Unicode levando emconta apenas os caracteres latinos básicos e as extensões &lt;a href="https://en.wikipedia.org/wiki/Latin_Extended-A"&gt;A&lt;/a&gt; e &lt;a href="https://en.wikipedia.org/wiki/Latin_Extended-B"&gt;B&lt;/a&gt;, além do &lt;a href="https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)"&gt;suplemento 1&lt;/a&gt; latino para fins de exemplificação, mas qualquer caractere Unicode é válido em Elixir!&lt;/p&gt;

</description>
      <category>unicode</category>
      <category>elixir</category>
      <category>iniciante</category>
    </item>
    <item>
      <title>Ambiente de desevolvimento Elixir/Phoenix com Nix</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Thu, 06 May 2021 03:30:38 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/ambiente-de-desevolvimento-elixir-phoenix-com-nix-1lmc</link>
      <guid>https://dev.to/zoedsoupe/ambiente-de-desevolvimento-elixir-phoenix-com-nix-1lmc</guid>
      <description>&lt;p&gt;Nos artigos anteriores, escrevi uma breve introdução ao &lt;code&gt;Nix&lt;/code&gt;, apresentei algumas vantagens e exemplos,&lt;br&gt;
 e a especificação da sintaxe da linaguagem além de apresentar alguns contras e limitações dessa ferramenta!&lt;/p&gt;

&lt;p&gt;Neste artigo irei mostrar um exemplo de configuração para um ambiente de desenvolvimento de projetos na linguagem&lt;br&gt;
&lt;a href="https://elixir-lang.org"&gt;Elixir&lt;/a&gt; com o &lt;code&gt;mix&lt;/code&gt; e também suporte ao framework &lt;a href="https://www.phoenixframework.org"&gt;Phoenix&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Requisitos
&lt;/h2&gt;

&lt;p&gt;Os únicos requisitos para seguir este tutorial é ter um conhecimento brévio sobre o ecossistema &lt;code&gt;Elixir&lt;/code&gt; e&lt;br&gt;
possuir o gerenciador de pacotes &lt;code&gt;Nix&lt;/code&gt; instalado no seu sistema.&lt;/p&gt;

&lt;p&gt;Caso esteja usando a distribuição &lt;code&gt;NixOS&lt;/code&gt;, o gerenciador de pacotes já estará disponível.&lt;/p&gt;
&lt;h2&gt;
  
  
  Projeto base criado com o mix
&lt;/h2&gt;

&lt;p&gt;O &lt;code&gt;mix&lt;/code&gt; é a ferramenta de contrução utilizada no ecossistema &lt;code&gt;Elixir&lt;/code&gt; para compilar seu projeto,&lt;br&gt;
realizar tarefas &lt;code&gt;mix&lt;/code&gt;, rodar os testes de sua apliação dentre outras funcionalidades.&lt;/p&gt;

&lt;p&gt;Para torná-lo acessível num ambiente isolado, crie um arquivo &lt;code&gt;shell.nix&lt;/code&gt;, com esse conteúdo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;elixirDrv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;elixir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.11.4"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"308255bda81e7f76f9bec838cef033e8e869981b"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1y8fbhli29agf84ja0fwz6gf22a46738b50nwy26yvcl2n2zl9d8"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;minimumOTPVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"23"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;mkShell&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"exemplo_dev"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;readline&lt;/span&gt; &lt;span class="nv"&gt;elixirDrv&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nv"&gt;shellHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    mkdir -p .nix-mix&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    mkdir -p .nix-hex&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export MIX_HOME=$PWD/.nix-mix&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export HEX_HOME=$PWD/.nix-hex&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export PATH=$MIX_HOME/bin:$PATH&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export PATH=$HEX_HOME/bin:$PATH&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export LANG=en_US.UTF-8&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export ERL_AFLAGS="-kernel shell_history enabled"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;    export ERL_LIBS=$HEX_HOME/lib/erlang/lib&lt;/span&gt;&lt;span class="err"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, execute &lt;code&gt;nix-shell&lt;/code&gt; ou &lt;code&gt;nix-shell &amp;lt;caminho/para/shell.nix&amp;gt;&lt;/code&gt; e você poderá&lt;br&gt;
utilizar o &lt;code&gt;mix&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Vamos desconstruir esse arquivo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No começo do arquivo importamos os pacotes a aprtir do repositório &lt;code&gt;nixpkgs&lt;/code&gt; e trazemos todas as opções desse&lt;br&gt;
módulo para o escopo léxico atual.&lt;/p&gt;

&lt;p&gt;Já dentro do bloco &lt;code&gt;let...in&lt;/code&gt;, sobrescrevo a versão do pacote da linguagem &lt;code&gt;Elixir&lt;/code&gt;, que atualmente está na versão &lt;code&gt;1.10.4&lt;/code&gt;&lt;br&gt;
no canal estável:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;elixirDrv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;elixir&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.11.4"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"308255bda81e7f76f9bec838cef033e8e869981b"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1y8fbhli29agf84ja0fwz6gf22a46738b50nwy26yvcl2n2zl9d8"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;minimumOTPVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"23"&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;Essa expressão pode ser usada para utilizar qualquer versão da linguagem. Existem versões anteriores já envelopadas&lt;br&gt;
no reposiório &lt;code&gt;nixpkgs&lt;/code&gt; como os pacotes &lt;code&gt;elixir_1_9&lt;/code&gt; e &lt;code&gt;elixir_1_7&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Dentro da derivção especial &lt;code&gt;mkShell&lt;/code&gt;, definimos um nome para esse ambiente e depois definimos a opção &lt;code&gt;buildInputs&lt;/code&gt;,&lt;br&gt;
que presenta quais são as dependências desse ambiente a ser criado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;readline&lt;/span&gt; &lt;span class="nv"&gt;elixirDrv&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E por último declaramos um pequeno script que será executado antes do ambiente ser criado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;shellHook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  mkdir -p .nix-mix&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  mkdir -p .nix-hex&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export MIX_HOME=$PWD/.nix-mix&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export HEX_HOME=$PWD/.nix-hex&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export PATH=$MIX_HOME/bin:$PATH&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export PATH=$HEX_HOME/bin:$PATH&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export LANG=en_US.UTF-8&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export ERL_AFLAGS="-kernel shell_history enabled"&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  export ERL_LIBS=$HEX_HOME/lib/erlang/lib&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo, criamos dois diretórios para abrigar as instalações locais&lt;br&gt;
do &lt;code&gt;mix&lt;/code&gt; e &lt;code&gt;hex&lt;/code&gt;, tornamos disponmíveis os seus executáveis, e definimos duas&lt;br&gt;
variáveis ambiente referentes à &lt;code&gt;BEAM&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;ERL_AFLAGS&lt;/code&gt;: o conteúdo dessa variáveis é adicionado no começo do comando &lt;code&gt;erl&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ERL_LIBS&lt;/code&gt;: necessária caso você já possua uma instalação local de &lt;code&gt;elixir&lt;/code&gt;, suprimindo os
avisos que a biblioteca padrão está sendo redefinida durante a compilação&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Projetos Phoenix
&lt;/h2&gt;

&lt;p&gt;Já para projetos &lt;code&gt;Phoenix&lt;/code&gt;, devemos realizar algumas mudanças no arquivo &lt;code&gt;shell.nix&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Phoenix + PostgreSQL
&lt;/h3&gt;

&lt;p&gt;A primeira mudança é na opção &lt;code&gt;buildInputs&lt;/code&gt;, onde adicionamos algumas dependência para compilação de&lt;br&gt;
algumas dependências do projeto dentre outros utilitários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nv"&gt;gnumake&lt;/span&gt;
  &lt;span class="nv"&gt;gcc&lt;/span&gt;
  &lt;span class="nv"&gt;readline&lt;/span&gt;
  &lt;span class="nv"&gt;openssl&lt;/span&gt;
  &lt;span class="nv"&gt;zlib&lt;/span&gt;
  &lt;span class="nv"&gt;libxml2&lt;/span&gt;
  &lt;span class="nv"&gt;curl&lt;/span&gt;
  &lt;span class="nv"&gt;libiconv&lt;/span&gt;
  &lt;span class="c"&gt;# minha versão do pacote `elixir`&lt;/span&gt;
  &lt;span class="nv"&gt;elixirDrv&lt;/span&gt;
  &lt;span class="nv"&gt;glibcLocales&lt;/span&gt;
  &lt;span class="nv"&gt;nodejs-12_x&lt;/span&gt;
  &lt;span class="nv"&gt;yarn&lt;/span&gt;
  &lt;span class="nv"&gt;postgresql&lt;/span&gt;
  &lt;span class="nv"&gt;gtk-engine-murrine&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;optional&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isLinux&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
      &lt;span class="nv"&gt;inotify-tools&lt;/span&gt; 
      &lt;span class="c"&gt;# dependência do GTK para usar o observer&lt;/span&gt;
      &lt;span class="nv"&gt;gtk-engine-murrine&lt;/span&gt; 
    &lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;optionals&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;isDarwin&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;darwin&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;apple_sdk&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;frameworks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="nv"&gt;CoreFoundation&lt;/span&gt;
      &lt;span class="nv"&gt;CoreServices&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A segunda alteração é no script inicial do ambiente, onde definimos algumas váriaveis ambiente&lt;br&gt;
para configuração do servidor do &lt;code&gt;PostgreSQL&lt;/code&gt; e criamos um usuário padrão.&lt;/p&gt;

&lt;p&gt;Para isso, adicione os seguintes comandos na opção &lt;code&gt;shellHook&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;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGHOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;/.postgres
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGDATA&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PGHOST&lt;/span&gt;/data
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGLOG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PGHOST&lt;/span&gt;/postgres.log
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PGPASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgres

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nv"&gt;$PGDATA&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Initializing postgresql database...'&lt;/span&gt;
  initdb &lt;span class="nt"&gt;--auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;trust &lt;span class="nt"&gt;--no-locale&lt;/span&gt; &lt;span class="nt"&gt;--encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;UTF8 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# inicializando o servidor&lt;/span&gt;
pg_ctl start &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="nv"&gt;$PGLOG&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"--unix_socket_directories='&lt;/span&gt;&lt;span class="nv"&gt;$PGHOST&lt;/span&gt;&lt;span class="s2"&gt;'"&lt;/span&gt;

&lt;span class="c"&gt;# verifica se existe um usuário padrão, caso contrário ele é criado&lt;/span&gt;
psql &lt;span class="nt"&gt;-d&lt;/span&gt; postgres &lt;span class="nt"&gt;-tAc&lt;/span&gt; &lt;span class="s2"&gt;"SELECT 1 FROM pg_roles WHERE rolname='postgres'"&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; 1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;||&lt;/span&gt; createuser &lt;span class="nt"&gt;-s&lt;/span&gt; postgres

&lt;span class="c"&gt;# assim que você sair do ambiente criado pelo `nix-shell`&lt;/span&gt;
&lt;span class="c"&gt;# o servidor do postgres será desligado &lt;/span&gt;
finish&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  pg_ctl &lt;span class="nt"&gt;-D&lt;/span&gt; &lt;span class="nv"&gt;$PGDATA&lt;/span&gt; stop
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;trap &lt;/span&gt;finish EXIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O código completo desta expressão Nix está disponível &lt;a href="https://gist.github.com/Mdsp9070/e562e4caa7349ee26156fce8fd1a945e"&gt;neste gist&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phoenix + MariaDB/MySQL
&lt;/h3&gt;

&lt;p&gt;Caso você esteja usando o &lt;code&gt;MariaDB&lt;/code&gt; ou &lt;code&gt;MySQL&lt;/code&gt; como SGBD, apenas altere a útilma parte do &lt;code&gt;shellHook&lt;/code&gt;, removendo&lt;br&gt;
as opções relacionadas ao &lt;code&gt;PostgreSQL&lt;/code&gt; e adicionando essas linhas:&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="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_BASEDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;.mariadb&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_HOME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;/mysql
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_DATADIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_HOME&lt;/span&gt;/data
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_UNIX_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_HOME&lt;/span&gt;/mysql.sock
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PID_FILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_HOME&lt;/span&gt;/mysql.pid

mysql_install_db &lt;span class="nt"&gt;--datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_DATADIR&lt;/span&gt; &lt;span class="nt"&gt;--basedir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_BASEDIR&lt;/span&gt; &lt;span class="nt"&gt;--pid-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_PID_FILE&lt;/span&gt;
mysqld &lt;span class="nt"&gt;--datadir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_DATADIR&lt;/span&gt; &lt;span class="nt"&gt;--pid-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_PID_FILE&lt;/span&gt; &lt;span class="nt"&gt;--socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_UNIX_PORT&lt;/span&gt; &amp;amp;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_PID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$!&lt;/span&gt;

finish&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  mysqladmin &lt;span class="nt"&gt;--socket&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$MYSQL_UNIX_PORT&lt;/span&gt; shutdown
  &lt;span class="nb"&gt;kill&lt;/span&gt; &lt;span class="nv"&gt;$MYSQL_PID&lt;/span&gt;
  &lt;span class="nb"&gt;wait&lt;/span&gt; &lt;span class="nv"&gt;$MYSQL_PID&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;trap &lt;/span&gt;finish EXIT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Utilizando essas derivações, é possível configurar um ambiente de densenvolvimento totalmente reproduzível&lt;br&gt;
e estável em poucos minutos!&lt;/p&gt;

&lt;p&gt;Vale lembrar que esta derivação é plenamente editável e pode ser adaptada para outros tipo de ambientes, &lt;br&gt;
por exemplo aplicações &lt;code&gt;Rails&lt;/code&gt;, &lt;code&gt;Django&lt;/code&gt; ou mesmo &lt;code&gt;Express&lt;/code&gt; ou &lt;code&gt;AdonisJS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Este post foi publicado com minha ferramenta de linha de comando &lt;code&gt;devit&lt;/code&gt;!&lt;br&gt;
Você pode encontrar instruções para instalação &lt;a href="https://github.com/Mdsp9070/devit"&gt;neste link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nix</category>
      <category>elixir</category>
      <category>phoenix</category>
      <category>programmig</category>
    </item>
    <item>
      <title>Sintaxe e especificação da linguagem Nix</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Thu, 06 May 2021 03:28:49 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/sintaxe-e-especificacao-da-linguagem-nix-gop</link>
      <guid>https://dev.to/zoedsoupe/sintaxe-e-especificacao-da-linguagem-nix-gop</guid>
      <description>&lt;p&gt;Com o &lt;code&gt;Nix&lt;/code&gt; devidamente apresentado no post anterior, agora irei introduzir a&lt;br&gt;
sintaxe da linguagem!&lt;/p&gt;

&lt;p&gt;Este artigo foi feito com a intenção de traduzir, resumidamente, a especificação oficial&lt;br&gt;
da linguagem que pode ser encontrada no link no final do post.&lt;/p&gt;
&lt;h2&gt;
  
  
  Paradigmas da linguagem
&lt;/h2&gt;
&lt;h3&gt;
  
  
  "Preguiçosa"
&lt;/h3&gt;

&lt;p&gt;Isso significa que as expressões somente são executadas caso realmente sejam necessárias.&lt;/p&gt;

&lt;p&gt;Neste exemplo, a função &lt;code&gt;abort&lt;/code&gt; nunca será executada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;abort&lt;/span&gt; &lt;span class="s2"&gt;"nunca irá acontecer"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"olá"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mundo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Funcional
&lt;/h3&gt;

&lt;p&gt;Programação Funcional é um paradigma de linguagens de computação onde a estrutura e elementos de&lt;br&gt;
um programa são tratados como expressões matemáticas, evitando a mutabilidade de estado. Linguagens&lt;br&gt;
funcionais também tendem a fazer parte do paradigma declarativo, onde a construção do programa&lt;br&gt;
é baseado em expressões.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pura
&lt;/h3&gt;

&lt;p&gt;Definimos uma função como pura quando o retorno dela é unicamente definido pelos seus argumentos&lt;br&gt;
de entrada, ou seja, não há efeitos colaterais externos ou "observáveis".&lt;/p&gt;
&lt;h2&gt;
  
  
  Especificação da linguagem
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Expressões
&lt;/h3&gt;

&lt;p&gt;Quando um tutorial referencia uma &lt;strong&gt;expressão Nix&lt;/strong&gt;, significa que ele está descrevendo a&lt;br&gt;
definição de uma função com várias entradas. Porém, uma expressão Nix pode ser definida como&lt;br&gt;
um simples texto, até uma função ou um conjunto de outras expressões!&lt;/p&gt;
&lt;h3&gt;
  
  
  Tipos primitivos
&lt;/h3&gt;
&lt;h4&gt;
  
  
  Texto
&lt;/h4&gt;

&lt;p&gt;Pode ser definido com aspas duplas &lt;code&gt;"&lt;/code&gt; ou duas aspas simples &lt;code&gt;''&lt;/code&gt; para mais de uma linha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# também suportam interpolações&lt;/span&gt;
&lt;span class="s2"&gt;"Diga &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="s2"&gt;''primeira linha&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;  segunda linha&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Números
&lt;/h4&gt;

&lt;p&gt;Existem os tipos &lt;code&gt;interios&lt;/code&gt; e &lt;code&gt;ponto de fltuação&lt;/code&gt; que possuem precisão limitada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Caminhos
&lt;/h4&gt;

&lt;p&gt;Caminhos relativos serão convertidos em absolutos quando a expressão for executada:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="sx"&gt;./ola/mundo&lt;/span&gt;
&lt;span class="c"&gt;# /caminho/asbsoluto/para/ola/mundo&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;nixpkgs/lib&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;# /caminho/para/nixpkgs/lib&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  URIs
&lt;/h4&gt;

&lt;p&gt;URIs podem ser representadas independentemente, como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sx"&gt;https://github.com/Mdsp9070/dotfiles&lt;/span&gt; 
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;fetchTarball&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;uri&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Booleanos
&lt;/h4&gt;

&lt;p&gt;Também existem os booleanos &lt;code&gt;true&lt;/code&gt; e &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nulidade
&lt;/h4&gt;

&lt;p&gt;A nulidade é representada pela expressão &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Funções
&lt;/h4&gt;

&lt;p&gt;Todas as funções são anônimas com o formato: &lt;code&gt;argumento: expressão-Nix&lt;/code&gt;, como: &lt;code&gt;x: x * x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Caso queira nomear a função, você pode declarar: &lt;code&gt;quadrado = x: x * x&lt;/code&gt;. E para executar essa&lt;br&gt;
função com argumento: &lt;code&gt;quadrado 3&lt;/code&gt;;&lt;/p&gt;

&lt;p&gt;Múltiplos argumentos podem ser exigidos no formato: &lt;code&gt;arg1: arg2: expressão-Nix&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;É comum que Conjuntos sejam passados como argumentos para funções, e é possível referenciar apenas&lt;br&gt;
os argumentos necessários:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;a_e_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;conjunto&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;conjunto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;conjunto&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;b&lt;/span&gt;

&lt;span class="nv"&gt;a_e_b&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ola"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mundo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# pode ser reescrita dessa maneira:&lt;/span&gt;
&lt;span class="nv"&gt;a_e_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também é possível definir argumentos padrões:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;

&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="c"&gt;# 3&lt;/span&gt;

&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso um argumento não declarado no cabeçalho da função seja fornecido, ocorrerá um erro, porém&lt;br&gt;
isso pode ser evitado caso use reticências &lt;code&gt;...&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# error: anonymous function at (string):1:2 called with unexpected argument 'c', at (string):1:1&lt;/span&gt;

&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# 7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Você também pode referenciar todos os argumentos num Cojunto com a notação &lt;code&gt;@&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt;
&lt;span class="nv"&gt;soma&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;# 17&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Listas
&lt;/h4&gt;

&lt;p&gt;É um conjunto de diversos valores separados por espaços em branco, que podem ter vários tipos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="sx"&gt;./exemplo.nix&lt;/span&gt; &lt;span class="s2"&gt;"abc"&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;y&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;Define uma lista com quatro elementos. Note que a função &lt;code&gt;f&lt;/code&gt; está dentro parênteses, caso contrário,&lt;br&gt;
haveria cinco elementos na lista, sendo o quarto uma função &lt;code&gt;f&lt;/code&gt; previamente declarada e o quinto um&lt;br&gt;
conjunto.&lt;/p&gt;

&lt;p&gt;Os valores de uma lista são "preguiçosos", mas seu tamanho não.&lt;/p&gt;
&lt;h4&gt;
  
  
  Conjuntos
&lt;/h4&gt;

&lt;p&gt;Esta estrutura é o coração da linguagem, já que o foco principal é criar derivações, que são apenas conjuntos&lt;br&gt;
de atributos que são passados para scripts construtores.&lt;/p&gt;

&lt;p&gt;Conjuntos são estrutas de nome/valor definidos dentro de chaves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;texto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;f&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;tudo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&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;A ordem dos atributos não é importante e é uma boa prática não haver repetições nos nomes das chaves.&lt;/p&gt;

&lt;p&gt;Cada atributo pode ser acessado com o operador &lt;code&gt;.&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Foo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bar"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Retorna &lt;code&gt;"Foo"&lt;/code&gt;. Também é possível definir um valor padrão caso um atributo não exista com a palavra-chave &lt;code&gt;or&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Foo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Bar"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;c&lt;/span&gt; &lt;span class="nv"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;"xyz"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As chaves também podem ser definidas por textos entre aspas duplas &lt;code&gt;"&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"exemplo de &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;chave&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Foo"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="s2"&gt;"exemplo de &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;chave&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caso a chave de atributo tenha o valor nulo, o atributo não é executado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&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="nv"&gt;exemplo&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="s2"&gt;"bar"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;Retorna &lt;code&gt;{}&lt;/code&gt; caso &lt;code&gt;exemplo&lt;/code&gt; seja falso.&lt;/p&gt;

&lt;p&gt;Conjuntos podem ter chaves que referem-se umas às outras com o construtor &lt;code&gt;rec&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kr"&gt;rec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="nv"&gt;l&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Operadores
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="c"&gt;# acesso&lt;/span&gt;
&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="nv"&gt;atributo&lt;/span&gt;

&lt;span class="c"&gt;# chamada de função&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# negação numérica&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;

&lt;span class="c"&gt;# testa a existência de um atributo&lt;/span&gt;
&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nv"&gt;atributo&lt;/span&gt;

&lt;span class="c"&gt;# concatenação de listas&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# multiplicação numérica&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# divisão numérica&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# soma numérica&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# subtração&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# operadores relacionais&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;

&lt;span class="c"&gt;# operadores booleanos&lt;/span&gt;
&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt; &lt;span class="c"&gt;# equivalente a !e1 || e2&lt;/span&gt;

&lt;span class="c"&gt;# concatenação de conjuntos&lt;/span&gt;
&lt;span class="nv"&gt;e1&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="nv"&gt;e2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Importações
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;import&lt;/code&gt; carrega, valida e importa expressões Nix a partir de um caminho, a palavra-chave não faz parte da linguagem em si:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;trace&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hello&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Construtores
&lt;/h3&gt;

&lt;h4&gt;
  
  
  with
&lt;/h4&gt;

&lt;p&gt;O construtor &lt;code&gt;with&lt;/code&gt; introduz o escopo léxico da expressão referenciada na próxima expressão:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;conjunto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt;
  &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;conjunto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="s2"&gt;"Tenho acesso aos atributos &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;toString&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; e &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="kr"&gt;toString&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pode ser muito útil nas expressões onde há necessidade de repetição de um atributo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&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;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;curl&lt;/span&gt; &lt;span class="nv"&gt;rust&lt;/span&gt; &lt;span class="nv"&gt;bat&lt;/span&gt; &lt;span class="nv"&gt;ffmpeg&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# ao invés de&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;buildInputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;curl&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;rust&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;bat&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;ffmpeg&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;h4&gt;
  
  
  let...in
&lt;/h4&gt;

&lt;p&gt;Permite a crição de variáveis locais:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt;
  &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;b&lt;/span&gt;
&lt;span class="c"&gt;# 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  inherit
&lt;/h4&gt;

&lt;p&gt;Traz o escopo léxico externo para um interno:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;buildPythonPackage&lt;/span&gt; &lt;span class="kr"&gt;rec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;pname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ola"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.0"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fetchPypi&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;pname&lt;/span&gt; &lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"01ba..0"&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;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Este artigo é uma tentativa de tornar a documentação do &lt;code&gt;Nix&lt;/code&gt; acessível em português! Sempre irei&lt;br&gt;
referenciar as fontes oficiais no final de cada artigo, junto com alguns recursos adicionais!&lt;/p&gt;

&lt;h2&gt;
  
  
  Fontes e recursos adicionais
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nixos.org/manual/nix/stable/#ssec-values"&gt;Manual oficial do Nix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learnxinyminutes.com/docs/nix/"&gt;Aprenda Nix em Y minutos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nixos.wiki/wiki/Nix_Expression_Language"&gt;Especificação oficial das expressões Nix&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este post foi publicado com minha ferramenta de linha de comando &lt;code&gt;devit&lt;/code&gt;!&lt;br&gt;
Você pode encontrar instruções para instalação &lt;a href="https://github.com/Mdsp9070/devit"&gt;neste link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nix</category>
      <category>nixos</category>
      <category>programmig</category>
      <category>functional</category>
    </item>
    <item>
      <title>O que é Nix e por que você deveria experimentar?</title>
      <dc:creator>Zoey de Souza Pessanha</dc:creator>
      <pubDate>Thu, 06 May 2021 01:00:01 +0000</pubDate>
      <link>https://dev.to/zoedsoupe/o-que-e-nix-e-porque-voce-deveria-experimentar-34ll</link>
      <guid>https://dev.to/zoedsoupe/o-que-e-nix-e-porque-voce-deveria-experimentar-34ll</guid>
      <description>&lt;p&gt;Hoje em dia temos inúmeras opções para configurar um ambiente de desenvolvimento&lt;br&gt;
que seja facilmente reproduzível e encapsulado. A escolha mais comum tem sido os&lt;br&gt;
contêineres &lt;code&gt;Docker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Entretanto, nas minhas pesquisas aventureiras pela internet, descobri uma ferramenta bem&lt;br&gt;
atrativa: o &lt;code&gt;Nix&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nesta breve série de artigos irei discorrer não só sobre o gerenciador de pacotes mas também mostrar&lt;br&gt;
exemplos de ambientes para desenvolvimento que utilizam as vantagens do &lt;code&gt;Nix&lt;/code&gt;!&lt;/p&gt;
&lt;h2&gt;
  
  
  O que é Nix?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nixos.org/learn.html"&gt;Nix&lt;/a&gt; é um gerenciador de pacotes e uma linguagem de programação &lt;br&gt;
funcional-declarativa, preguiçosa (nem sempre), e dinamicamente tipada que usamos&lt;br&gt;
para descrever as _&lt;em&gt;derivações&lt;/em&gt; (resultado das expressões em &lt;code&gt;Nix&lt;/code&gt;) para esse gerenciador.&lt;/p&gt;
&lt;h3&gt;
  
  
  Como o gerenciador de pacotes funciona?
&lt;/h3&gt;

&lt;p&gt;A partir de um arquivo que contenha as instruções para construção do pacote, o &lt;code&gt;Nix&lt;/code&gt; computa&lt;br&gt;
uma derivação. Para uma derivação ser considerada válida, o arquivo precisa ter as seguintes informações:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;referência para as dependências do pacote a ser construído;&lt;/li&gt;
&lt;li&gt;intruções de como construir o pacote;&lt;/li&gt;
&lt;li&gt;metainformações sobre o pacote, como os mantenedores;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Quando o pacote for construído com sucesso, um caminho será criada com o resultado da construção &lt;br&gt;
no formato: &lt;code&gt;/nix/store/&amp;lt;hash&amp;gt;-&amp;lt;nome&amp;gt;-&amp;lt;versão&amp;gt;&lt;/code&gt;, onde o &lt;code&gt;hash&lt;/code&gt; é criado a partir dos dados da derivação.&lt;/p&gt;

&lt;p&gt;Veja o conjunto de expressões Nix que gera a derivação do software &lt;code&gt;GNU hello&lt;/code&gt;, por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;fetchurl&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="nv"&gt;stdenv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;mkDerivation&lt;/span&gt; &lt;span class="kr"&gt;rec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;pname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"2.10"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;fetchurl&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"mirror://gnu/hello/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;pname&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;sha256&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nv"&gt;doCheck&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nv"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;lib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"A program that produces a familiar, friendly greeting"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;longDescription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;''&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      GNU Hello is a program that prints "Hello, world!" when you run it.&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;      It is fully customizable.&lt;/span&gt;&lt;span class="err"&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;homepage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://www.gnu.org/software/hello/manual/"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;changelog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://git.savannah.gnu.org/cgit/hello.git/plain/NEWS?h=v&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;version&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="nv"&gt;license&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;licenses&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;gpl3Plus&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;maintainers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;maintainers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;eelco&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;platforms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;platforms&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;all&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;Dessa forma o &lt;code&gt;Nix&lt;/code&gt; consegue assegurar que a mesma derivação vai sempre construir o mesmo pacote,&lt;br&gt;
a não ser que alguma instrução de construção use informações dependentes de hardware.&lt;/p&gt;
&lt;h2&gt;
  
  
  Vantagens de usar Nix
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Ambiente sempre reproduzível
&lt;/h3&gt;

&lt;p&gt;Essa é a vantagem mais clara da utilização do &lt;code&gt;Nix&lt;/code&gt; para gerir pacotes e dependências, pois como&lt;br&gt;
dito anteriormente, se duas pessoas contruirem um pacote com a mesma derivação, as duas terão o mesmo&lt;br&gt;
resultado final. Mesmo que haja uma diferença na versão de alguma dependência, o caminho gerado pela&lt;br&gt;
derivação irá se alterar, explicitando que houve uma mudança.&lt;/p&gt;
&lt;h3&gt;
  
  
  Múltiplas versões do mesmo pacote simultâneamente
&lt;/h3&gt;

&lt;p&gt;Como cada pacote é instalado em seu próprio caminho, não há colissões. Isso se torna muito atrativo para&lt;br&gt;
desenvolvedores, pois pode ser comparado com os ambientes virtuais de &lt;code&gt;Python&lt;/code&gt;, só que para qualquer programa.&lt;/p&gt;

&lt;p&gt;Além disso, como a cada versão construída do pacote gera um novo caminho, há sempre a possibilidade de retornar&lt;br&gt;
à uma versão antiga, desde que ela não tenha sido apagada pelo &lt;em&gt;garbage-collector&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Construções seguras
&lt;/h3&gt;

&lt;p&gt;Toda a contrução de cada derivação é isolada do sistema, o que torna seguro permitir que usuários&lt;br&gt;
com menos privilégios executem suas derivações.&lt;/p&gt;
&lt;h3&gt;
  
  
  Teste novas ferramentas temporariamente
&lt;/h3&gt;

&lt;p&gt;Digamos que você precisa converter um arquivo escrito com &lt;code&gt;Markdown&lt;/code&gt; para &lt;code&gt;HTML&lt;/code&gt; com o pandoc! Porém, você&lt;br&gt;
se lembra que não possui esse programa e precisa usá-lo apenas uma vez.&lt;/p&gt;

&lt;p&gt;Naturalmente você possui algumas opções:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Baixar o programa dos repositórios oficiais, realizar a conversão e desinstalar;&lt;/li&gt;
&lt;li&gt;Usar uma imagem &lt;code&gt;Docker&lt;/code&gt; do programa, utilizá-la e deixar ela ocupando espaço na sua máquina;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Com o &lt;code&gt;Nix&lt;/code&gt; é possível criar um ambiente sob demanda, mas sempre reprodutível, no qual um pacote não&lt;br&gt;
existente no seu sistema passe a ser utilizável.&lt;/p&gt;

&lt;p&gt;No caso do pandoc, com um simples &lt;code&gt;nix-shell -p pandoc&lt;/code&gt; você tem acesso ao pacote de forma temporária! &lt;/p&gt;
&lt;h2&gt;
  
  
  Ecossistema
&lt;/h2&gt;

&lt;p&gt;Essas vantagens são bem atrativas, mas os casos de uso para o &lt;code&gt;Nix&lt;/code&gt; não param por aí. A seguir,&lt;br&gt;
mostro exemplos do mundo real que usam &lt;code&gt;Nix&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Nixpkgs
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;nixpkgs&lt;/code&gt; é a maior coleção de derivações para o gerenciador de pacotes que podem ser alteradas e combinadas.&lt;br&gt;
Além de derivações específicas para cada linguagem, como um mirror atualizado do &lt;code&gt;Hackage&lt;/code&gt;, existem derivações de&lt;br&gt;
diversos outros softwares.&lt;/p&gt;
&lt;h3&gt;
  
  
  NixOS
&lt;/h3&gt;

&lt;p&gt;Já o &lt;code&gt;NixOS&lt;/code&gt; é uma distribuição GNU/Linux que é configurada a partir de expressões &lt;code&gt;Nix&lt;/code&gt;, além de possuir nativamente&lt;br&gt;
o gerenciador de pacotes. Todo o sistema é tratado como uma grande derivação que depende de todas as outras sub derivações&lt;br&gt;
que você monta.&lt;/p&gt;

&lt;p&gt;Neste trecho de exemplo, mostro como habilitar o uso do &lt;code&gt;pulseaudio&lt;/code&gt; no &lt;code&gt;NixOS&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;sound&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;hardware&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;pulseaudio&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;pulseaudioFull&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 trecho foi retirado da minha &lt;a href="https://github.com/Mdsp9070/dotfiles"&gt;configuração pessoal&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Home Manager
&lt;/h3&gt;

&lt;p&gt;Um projeto muito interessante no ecossistema &lt;code&gt;Nix&lt;/code&gt; é o &lt;a href="https://github.com/nix-community/home-manager"&gt;home-manager&lt;/a&gt;, que permite&lt;br&gt;
gerenciar um ambiente (dotfiles) completo a nível de usuário.&lt;/p&gt;

&lt;p&gt;Neste trecho da minha configuração pessoal, declaro alguns pacotes a nível de usuário:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="nv"&gt;programs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;home-manager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;gpg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;command-not-found&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;clipmenu&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;services&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;emacs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&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;"matthew"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;homeDirectory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/home/matthew"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;home&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;packages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kn"&gt;with&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="c"&gt;# bar&lt;/span&gt;
  &lt;span class="nv"&gt;haskellPackages&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;xmobar&lt;/span&gt;

  &lt;span class="c"&gt;# chat&lt;/span&gt;
  &lt;span class="nv"&gt;tdesktop&lt;/span&gt; &lt;span class="nv"&gt;discord&lt;/span&gt;

  &lt;span class="c"&gt;# browser&lt;/span&gt;
  &lt;span class="nv"&gt;google-chrome&lt;/span&gt;

  &lt;span class="c"&gt;# theme&lt;/span&gt;
  &lt;span class="nv"&gt;lxappearance&lt;/span&gt;

  &lt;span class="c"&gt;# tools&lt;/span&gt;
  &lt;span class="nv"&gt;docker-compose&lt;/span&gt; &lt;span class="nv"&gt;insomnia&lt;/span&gt;
  &lt;span class="nv"&gt;qbittorrent&lt;/span&gt; &lt;span class="nv"&gt;obs-studio&lt;/span&gt;
  &lt;span class="nv"&gt;screenkey&lt;/span&gt; &lt;span class="nv"&gt;gitAndTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;gh&lt;/span&gt;

  &lt;span class="c"&gt;# audio&lt;/span&gt;
  &lt;span class="nv"&gt;spotify&lt;/span&gt;

  &lt;span class="c"&gt;# images&lt;/span&gt;
  &lt;span class="nv"&gt;peek&lt;/span&gt; &lt;span class="nv"&gt;flameshot&lt;/span&gt; &lt;span class="nv"&gt;imagemagick&lt;/span&gt;

  &lt;span class="c"&gt;# others&lt;/span&gt;
  &lt;span class="nv"&gt;any-nix-shell&lt;/span&gt; &lt;span class="nv"&gt;arandr&lt;/span&gt;
  &lt;span class="nv"&gt;bitwarden-cli&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integração com diversas ferramentas
&lt;/h3&gt;

&lt;p&gt;Também é possível usar o &lt;code&gt;Nix&lt;/code&gt; para outras tarefas, como descrever a construção de uma imagem &lt;code&gt;Docker&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"x86_64-linux"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;dockerTools&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;buildLayeredImage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;# função para facilitar a construção da imagem&lt;/span&gt;
  &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nix-hello"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                &lt;span class="c"&gt;# nome da imagem a ser construída&lt;/span&gt;
  &lt;span class="nv"&gt;tag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"latest"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c"&gt;# tag para a imagem&lt;/span&gt;
  &lt;span class="nv"&gt;contents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;hello&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;         &lt;span class="c"&gt;# pacotes presentes na imagem&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Em suma, o &lt;code&gt;Nix&lt;/code&gt; e seu ecossistema é uma boa opção para quem quer ter novas experiências&lt;br&gt;
no mundo Unix, permitindo que um ambiente de desenvolvimento ou até mesmo uma distribuição&lt;br&gt;
GNU/Linux completa possa ser facilmente reproduzida, além de usufruir das vantagens da imutabilidade&lt;br&gt;
de uma linguagem funcional.&lt;/p&gt;

&lt;p&gt;Porém, é importante ter em mente que assim como qualquer ferramenta, o &lt;code&gt;Nix&lt;/code&gt; não funciona como&lt;br&gt;
"bala de prata". Existem alguns contras que você deve levar em consideração:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O número de pacotes envelopados, apesar de serem inúmeros, não se comparam (ainda) com os repositórios
oficiais de algumas distribuições, por exemplo.&lt;/li&gt;
&lt;li&gt;Alguns pacotes podem não ser atualizados com frequência. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Fontes e recursos adicionais
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nixos.org"&gt;Site oficial para o Nix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/NixOS/nixpkgs"&gt;Repositório para nixpkgs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://serokell.io/blog/what-is-nix"&gt;Post usado como inspiração&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://t.me/nixosbr"&gt;Grupo brasileiro de usuários do NixOS no Telegram&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Este post foi publicado com minha ferramenta de linha de comando &lt;code&gt;devit&lt;/code&gt;!&lt;br&gt;
Você pode encontrar instruções para instalação &lt;a href="https://github.com/Mdsp9070/devit"&gt;neste link&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nix</category>
      <category>nixos</category>
      <category>unix</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
