<?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: Lucas Perez</title>
    <description>The latest articles on DEV Community by Lucas Perez (@lucassperez).</description>
    <link>https://dev.to/lucassperez</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%2F490879%2F05e142c0-02ad-4b45-9947-48d41b5ba4b1.jpeg</url>
      <title>DEV Community: Lucas Perez</title>
      <link>https://dev.to/lucassperez</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucassperez"/>
    <language>en</language>
    <item>
      <title>Não use uma variável chamada path dentro de funções quando estiver usando o zsh</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 20 Mar 2024 21:56:23 +0000</pubDate>
      <link>https://dev.to/lucassperez/nao-use-uma-variavel-chamada-path-dentro-de-funcoes-quando-estiver-usando-o-zsh-1ob8</link>
      <guid>https://dev.to/lucassperez/nao-use-uma-variavel-chamada-path-dentro-de-funcoes-quando-estiver-usando-o-zsh-1ob8</guid>
      <description>&lt;p&gt;🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version &lt;a href="https://dev.to/lucassperez/til-dont-set-a-variable-named-path-inside-functions-when-using-zsh-30k5"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Antigamente eu criava aliases para coisas comuns, como uma sequência de comandos ou comandos com flags e opções específicas. Porém, quando ficava muito complicado, eu criava um shell script para lidar com coisas mais complexas. Aí então eu criava aliases que simplesmente chamavam esses scripts. Eu preferia isso do que por o script no meu path porque daí meus scripts podiam ter nomes descritivos e eu não teria que ficar lidando com alterar a variável &lt;code&gt;PATH&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Mas daí em algum momento eu percebi que eu podia simplesmente criar funções nos arquivos de configuração do meu shell (como por exemplo o .bashrc, o .zshrc etc) e daí eu teria essas funções disponíveis para mim. Além disso, usando a estratégia script+alias, quando eu executava &lt;code&gt;which &amp;lt;comando&amp;gt;&lt;/code&gt;, eu não teria uma saída tão útil assim, pois aparecia para mim algo como &lt;code&gt;comando=/caminho/para/o/script&lt;/code&gt;. Mas quando eu defino funções, executar &lt;code&gt;which &amp;lt;função&amp;gt;&lt;/code&gt; me mostra a implementação dela.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Eu acho que o comportamento de &lt;code&gt;which&lt;/code&gt; não é o mesmo em todas as distros, mas no Fedora ele faz isso.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;É claro que se a implementação de tal função for muito grande, talvez mostrá-la não seja tão útil assim, mas enfim.&lt;/p&gt;

&lt;p&gt;Você pode basicamente copiar e colar seus shell scripts em definições de funções, só tem que lembrar que muito provavelmente você vai querer trocar &lt;code&gt;exit&lt;/code&gt; por &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ou será que não?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Hoje eu queria criar uma função que chamaria um curl pra pegar um token de autorização, e depois usaria esse token em outro curl para uma rota fornecida como argumento. Isso para que eu não tenha que sair copiando e colando tokens o dia todo e ficar passando um &lt;code&gt;--header&lt;/code&gt; pro curl toda hora só pra trabalhar na minha API.&lt;/p&gt;

&lt;p&gt;Então eu fiz algo mais ou menos assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl-da-minha-api&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;curl ... | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.token'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;shift
  &lt;/span&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:3000/&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O que eu queria era passar o caminho como primeiro argumento pra função e colocar depois de &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; (para que eu não tenha que escrever isso toda hora. Somos preguiçosos, certo?). Eu também queria poder passar mais opções para o segundo curl que é feito. Então eu pego o primeiro argumento com &lt;code&gt;$1&lt;/code&gt;, faço um shift pra removê-lo da lista de argumentos, e simplesmente passo o resto pro segundo curl.&lt;/p&gt;

&lt;p&gt;Então eu posso fazer coisas assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Faz um GET para http://localhost:3000/posts&lt;/span&gt;
curl-da-minha-api /posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas também posso fazer coisas assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Faz um POST para http://localhost:3000/posts com aquele corpo&lt;/span&gt;
curl-da-minha-api /posts &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"title": "Post Legal"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso deixa minha função flexível, eu apenas &lt;strong&gt;tenho que saber&lt;/strong&gt; que exatamente o &lt;strong&gt;PRIMEIRO&lt;/strong&gt; argumento é o path. Eu poderia iterar sobre os argumentos, usar getopts ou algo assim, mas eu apenas queria fazer algo rápido e que funcionasse.&lt;/p&gt;

&lt;p&gt;Porém!!&lt;/p&gt;

&lt;p&gt;Quando eu fui executar essa função, eu tive um erro esquisito:&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="nv"&gt;$ &lt;/span&gt;curl-da-minha-api /posts
curl: Command not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Eu pensei, o quê? Como assim? Eu tenho curl instalado. Vamos editar o arquivo onde eu defini a função:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim ~/.zshrc
vim: Command not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Praticamente todo comando que eu tentei a partir daqui dava o mesmo erro, inclusive &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;O que está acontecendo? Por que minha função não só não funcionou, como também aparentemente estragou minha sessão no terminal?&lt;/p&gt;

&lt;p&gt;A mensagem de erro não é muito claro. Eu pensei, vou por essa função num shell script e executá-lo com a opção &lt;code&gt;-x&lt;/code&gt; pra conseguir debugar melhor. Mas quando eu fiz isso, a função simplesmente funcionou! Sem problemas com nada!&lt;/p&gt;

&lt;p&gt;Depois de quebrar minha cabeça, eu tive uma ideia. Talvez a linha &lt;code&gt;path=...&lt;/code&gt; fosse um problema. Eu renomeei a variável simplesmente para &lt;code&gt;p&lt;/code&gt; e agora a função funcionava perfeitamente.&lt;/p&gt;

&lt;p&gt;E ainda mais esquisito, eu tentei executar a mesma função usando nosso bom e velho amigo &lt;strong&gt;bash&lt;/strong&gt;, e eu sabe o quê? Não teve nenhum problema usando a variável chamada &lt;code&gt;path&lt;/code&gt;. Então parece que tem alguma magia misteriosa acontecendo com o &lt;strong&gt;zsh&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;E por falar nisso, eu alterei minha função para usar &lt;code&gt;local p=...&lt;/code&gt; quando definia a variável. Usando o &lt;code&gt;local&lt;/code&gt; impedia a função de estragar tudo quando eu usava o nome path, assim: &lt;code&gt;local path=...&lt;/code&gt;. Porém, a função continuava não funcionava. Interessante. E daí eu pensei, será que o &lt;strong&gt;zsh&lt;/strong&gt; pode usar tanto &lt;code&gt;path&lt;/code&gt; como &lt;code&gt;PATH&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Bom, parece que sim! No &lt;strong&gt;zsh&lt;/strong&gt;, se você fizer &lt;code&gt;echo $path&lt;/code&gt;, você vai receber a mesma coisa que se fizer &lt;code&gt;echo $PATH&lt;/code&gt;! Então aí está, como eu estava criando uma variável chamada &lt;code&gt;path&lt;/code&gt;, ela estava sobreescrevendo a minha variável de ambiente &lt;strong&gt;PATH&lt;/strong&gt;! Por isso que usar &lt;code&gt;local&lt;/code&gt; salvou meu terminal, porque quando não usava, esse valor sobreescrito afetava tudo mesmo após a função ter terminado.&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;bash&lt;/strong&gt;, executar &lt;code&gt;echo $path&lt;/code&gt; simplesmente não retorna nada. Eu também tentei no &lt;strong&gt;zsh&lt;/strong&gt; fazer &lt;code&gt;echo $home&lt;/code&gt;, mas isso não mostra nada também. Então estranhamente, o &lt;strong&gt;zsh&lt;/strong&gt; não faz diferença entre maiúsculas e minúsculas somente para a variável do path. Mas em todas as outras variáveis que tentei, maiúsculas e minúsculas importavam, seja &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;minhavariável&lt;/code&gt; ou &lt;code&gt;shell&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Além disso, todos os meus scripts eu faço usando o shebang &lt;code&gt;/sh&lt;/code&gt;, por isso eu não tive problemas quando copiei e colei minha função em um script. Seja lá o que estiver em &lt;code&gt;/sh&lt;/code&gt; no meu computador, ele faz diferença entre &lt;code&gt;path&lt;/code&gt; e &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;E enquanto eu escrevia isso, eu decidi googlear um pouco (mas não enquanto tentava resolver esse problema, porque a gente é preguiçoso apenas para escrever localhost, e não para depurar programas, certo?). Aparentemente, esse comportamento de usar &lt;code&gt;path&lt;/code&gt; e &lt;code&gt;PATH&lt;/code&gt; também está presente no &lt;strong&gt;csh&lt;/strong&gt; e no &lt;strong&gt;tcsh&lt;/strong&gt;. Além disso, eu &lt;em&gt;ACHO&lt;/em&gt; que o &lt;strong&gt;zsh&lt;/strong&gt; foi baseado/inspirado no &lt;strong&gt;tcsh&lt;/strong&gt; e no &lt;strong&gt;ksh&lt;/strong&gt; (eu acho, não me cobrem depois), então talvez venha daí essa coisa.&lt;/p&gt;

&lt;p&gt;E também para deixar claro, não é que o &lt;strong&gt;zsh&lt;/strong&gt; não diferencia maiúsuclas e minúsculas para o path. O que acontece é que ele entende ambos &lt;code&gt;path&lt;/code&gt; e &lt;code&gt;PATH&lt;/code&gt;, porque coisas como &lt;code&gt;PaTh&lt;/code&gt; e &lt;code&gt;PAth&lt;/code&gt; não funcionam). Percebi isso posteriormente com mais testes.&lt;/p&gt;

&lt;p&gt;Pra ser sincero, eu acho isso meio esquisito e fere um pouco o "princípio da surpresa mínima" (tem esse nome em português? Estou falando &lt;a href="https://en.wikipedia.org/wiki/Principle_of_least_astonishment"&gt;disso&lt;/a&gt;). Mas acho que hoje aprendi &lt;br&gt;
algo novo.&lt;/p&gt;

&lt;p&gt;Aprendi que o &lt;strong&gt;zsh&lt;/strong&gt; não diferencia &lt;code&gt;path&lt;/code&gt; e &lt;code&gt;PATH&lt;/code&gt;.&lt;br&gt;
Além disso, usem &lt;code&gt;local&lt;/code&gt; em suas funções!&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>zsh</category>
      <category>terminal</category>
      <category>bash</category>
    </item>
    <item>
      <title>TIL: Don't set a variable named path inside functions when using zsh</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 20 Mar 2024 21:22:05 +0000</pubDate>
      <link>https://dev.to/lucassperez/til-dont-set-a-variable-named-path-inside-functions-when-using-zsh-30k5</link>
      <guid>https://dev.to/lucassperez/til-dont-set-a-variable-named-path-inside-functions-when-using-zsh-30k5</guid>
      <description>&lt;p&gt;🇧🇷🇵🇹 Versão em português &lt;a href="https://dev.to/lucassperez/nao-use-uma-variavel-chamada-path-dentro-de-funcoes-quando-estiver-usando-o-zsh-1ob8"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past, I used to use aliases for common things, sometimes a sequence of commands or commands with specific flags and options. But when it got too complicated, I used to create shell scripts to handle more complex logic. Then I would create aliases that just call these shell scripts. I prefered this over putting the scripts in my path because then I could name then with more descriptive names and I wouldn't have to deal with the &lt;code&gt;PATH&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;But at some point I realized that I can just create functions and put then in my shell config file (like .bashrc, .zshrc etc) and then I would have these functions available to me. Also, using the script+alias aproach, running &lt;code&gt;which &amp;lt;command&amp;gt;&lt;/code&gt; wouldn't be all that useful, it would just show me something like &lt;code&gt;command=/path/to/script&lt;/code&gt;. But when I define functions, running &lt;code&gt;which &amp;lt;function&amp;gt;&lt;/code&gt; shows me the implementation of it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I think the behaviour of &lt;code&gt;which&lt;/code&gt; is not the same on every distro, but on Fedora it does that.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Of course that if the implementation is several lines long, it might not be helpful anyways, but anyways.&lt;/p&gt;

&lt;p&gt;You can pretty much copy paste your shell scripts into functions definitions, just have in mind that instead of using &lt;code&gt;exit&lt;/code&gt;, you should use &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Or can you?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Today I wanted to create a function that would call curl to get an authorization token, and then use this token to make another curl to a supplied route, so I wouldn't have to copy paste around a token the whole day and deal with yet another &lt;code&gt;--header&lt;/code&gt; flag in curl just to develop my API.&lt;/p&gt;

&lt;p&gt;So I did something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;my-api-curl&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;curl ... | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.token'&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;
  &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;shift
  &lt;/span&gt;curl &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"http://localhost:3000/&lt;/span&gt;&lt;span class="nv"&gt;$path&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What I wanted was to supply the path as the first argument to the function and append it to localhost:3000 (so I don't have to type so much all the time. We're lazy, right?). And then I would like to pass curl flags to my function so it would repass it to curl internaly. So I grab the first argument with &lt;code&gt;$1&lt;/code&gt;, I do a shift to remove it from the arg list, and pass the rest as is to curl.&lt;/p&gt;

&lt;p&gt;So I can do things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Do a GET to http://localhost:3000/posts&lt;/span&gt;
my-api-curl /posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I can also do things like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Do a POST to http://localhost:3000/posts with that body&lt;/span&gt;
my-api-curl /posts &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"title": "Nice Post"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes my function flexible, I just &lt;strong&gt;have to know&lt;/strong&gt; that the &lt;strong&gt;FIRST&lt;/strong&gt; argument is the url. I could iterate over the arguments, use getopts or something, but I was doing something dirt and quick.&lt;/p&gt;

&lt;p&gt;So when I was going to run this function, I got a weird error:&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="nv"&gt;$ &lt;/span&gt;my-api-curl /posts
curl: Command not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I thought, what? I do have curl. Lets edit the file where I define it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim ~/.zshrc
vim: Command not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty much every command I tried from here on would say Command not found, I could not use &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;What is going on? Why didn't my function work, and why did it bork my terminal session?&lt;/p&gt;

&lt;p&gt;The error message is not very clear. I wanted to run it as a script with the -x flag for debugging purposes, but when I copy pasted it into a file and ran it with &lt;code&gt;sh&lt;/code&gt;, it just worked! No problems with it!&lt;/p&gt;

&lt;p&gt;After some scratching my head, I had a hunch that the line &lt;code&gt;path=...&lt;/code&gt; was troublesome. I renamed the variable to simply &lt;code&gt;p&lt;/code&gt; and now the function works.&lt;/p&gt;

&lt;p&gt;And even weirder, I tried the same using our trusty old friend &lt;strong&gt;bash&lt;/strong&gt;, and I had no problem with using a variable named &lt;code&gt;path&lt;/code&gt;. So I guess there is some weird &lt;strong&gt;zsh&lt;/strong&gt; magic going on there.&lt;/p&gt;

&lt;p&gt;And by the way, I updated my function to use &lt;code&gt;local p=...&lt;/code&gt; when defining the variable. When doing so, it does not bork my terminal session if I use &lt;code&gt;local path=...&lt;/code&gt;, but the function itself does not work. Interesting. And then I thought, maybe &lt;strong&gt;zsh&lt;/strong&gt; can use both &lt;code&gt;path&lt;/code&gt; and &lt;code&gt;PATH&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Well, it is true! In &lt;strong&gt;zsh&lt;/strong&gt;, if you &lt;code&gt;echo $path&lt;/code&gt;, you'll get the same thing as &lt;code&gt;echo $PATH&lt;/code&gt;! So there you go, since I was using a variable named &lt;code&gt;path&lt;/code&gt;, it was overriding my &lt;strong&gt;PATH&lt;/strong&gt; env var! That's why using &lt;code&gt;local&lt;/code&gt; saved my terminal, because when not using it, this overwritten value would affect everything, not just the function.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;bash&lt;/strong&gt;, &lt;code&gt;echo $path&lt;/code&gt; just outputs nothing. I also tried in &lt;strong&gt;zsh&lt;/strong&gt; to &lt;code&gt;echo $home&lt;/code&gt;, but this outputs nothing as well. So weirdly, &lt;strong&gt;zsh&lt;/strong&gt; is case insensitive only for the path variable. It is not case insensitive for any other variable I tried, be it &lt;code&gt;x&lt;/code&gt;, &lt;code&gt;myvariable&lt;/code&gt; or &lt;code&gt;shell&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;All my scripts shebangs are &lt;code&gt;/sh&lt;/code&gt; though, so that's why I didn't have a problem when I copy pasted my function to a script, it worked well, because whatever &lt;code&gt;/sh&lt;/code&gt; is in my computer, it is not case insensitive for my PATH variable.&lt;/p&gt;

&lt;p&gt;And while writing this, I decided to try some googling (I didn't while I was solving the problem, because I like figuring things on my own. We're just lazy to type, not to debug, right?), it looks like this is also the behaviour of &lt;strong&gt;csh&lt;/strong&gt; and &lt;strong&gt;tcsh&lt;/strong&gt;. Also, &lt;strong&gt;zsh&lt;/strong&gt; is kind of based on &lt;strong&gt;tcsh&lt;/strong&gt; and &lt;strong&gt;ksh&lt;/strong&gt; I think (don't quote me on that), so maybe that's where it comes from.&lt;/p&gt;

&lt;p&gt;Also, zsh is not actually case insensitive, since pAth, PAtH etc does not work. It simply understands both path and PATH. I learned that with further experiments.&lt;/p&gt;

&lt;p&gt;To be honest, I thing this is weird and kind of hurts the principle of least surprises, but I guess &lt;strong&gt;today I learned&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;TIL &lt;strong&gt;zsh&lt;/strong&gt; is &lt;em&gt;somewhat&lt;/em&gt; case insensitive for the &lt;code&gt;PATH&lt;/code&gt;.&lt;br&gt;
Also, use &lt;code&gt;local&lt;/code&gt; in your functions!&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>zsh</category>
      <category>terminal</category>
      <category>bash</category>
    </item>
    <item>
      <title>Histórico do Bash dentro de Contêineres Docker</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 25 May 2022 13:10:13 +0000</pubDate>
      <link>https://dev.to/lucassperez/bash-history-inside-docker-container-4j2m</link>
      <guid>https://dev.to/lucassperez/bash-history-inside-docker-container-4j2m</guid>
      <description>&lt;p&gt;🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text &lt;a href="https://dev.to/lucassperez/bash-history-inside-docker-container-553g"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Não sei vocês, mas eu adoro ter um ambiente de desenvolvimento dockerizado. Não ter que me preocupar com versionamento e dependências quando for pulando de projeto em projeto é muito bom.&lt;/p&gt;

&lt;p&gt;Mas algo que eu não gosto tanto assim é quando eu saio do contêiner e mais tarde volto nele e descubro que perdi o histórico de todos os comandos anteriores, então não posso buscar mais nada nem com &lt;code&gt;ctrl+R&lt;/code&gt; nem com &lt;code&gt;seta pra cima&lt;/code&gt;/&lt;code&gt;ctrl+P&lt;/code&gt;. &lt;em&gt;Imagens de dor e sofrimento!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Decidi então tentar manter esse histórico, e para fazer isso, primeiro eu pensei, &lt;em&gt;como que o bash faz pra saber os comandos anteriores?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No fim parece que há uma variável de ambiente chamada &lt;code&gt;HISTFILE&lt;/code&gt; que contém o caminho para um arquivo de texto com o histórico de comandos do bash. Aparentemente, por padrão ela é configurada para &lt;code&gt;$HOME/.bash_history&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OBS: Se o teu contêiner rodar outro shell diferente do bash, teríamos que descobrir onde que esse outro shell guarda o seu histórico.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Então uma solução que encontrei foi de mudar essa variável de ambiente pra algum outro lugar, algum lugar dentro do diretório do projeto que estou trabalhando pra evitar perdê-lo depois de parar o contêiner.&lt;/p&gt;

&lt;p&gt;Vamos supor que a imagem do docker cria um diretório &lt;code&gt;/app&lt;/code&gt; com todo o conteúdo do projeto dentro, eu poderia definir &lt;code&gt;HISTFILE&lt;/code&gt; como sendo &lt;code&gt;/app/.bash_history&lt;/code&gt;, e daí se mapearmos tudo com um volume, vamos ter um histórico persistente entre sessões do docker. O nome do arquivo em si nem precisa ser &lt;code&gt;.bash_history&lt;/code&gt;, poderia ser algo como &lt;code&gt;/app/.docker_bash_history&lt;/code&gt;, por exemplo.&lt;/p&gt;

&lt;p&gt;Pra começar um contêiner com uma variável específica, podemos passar a opção &lt;code&gt;-e&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/.bash_history &lt;span class="nt"&gt;-v&lt;/span&gt; &amp;lt;volume&amp;gt; &amp;lt;...outras coisas...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se estivermos usando o &lt;strong&gt;Docker Compose&lt;/strong&gt;, podemos ou passar um "env file" (um arquivo com variáveis de ambiente) ou as variáveis diretamente no &lt;code&gt;docker-compose.yml&lt;/code&gt; (ou qualquer outro arquivo de configuração que estejas usando):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# arquivo de configuração de exemplo&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/app&lt;/span&gt; &lt;span class="c1"&gt;# mapeando este volume para persistir as modificações no nosso novo arquivo de histórico&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo Oi!&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# podemos definir as variáveis dentro deste arquivo .env&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# ou então podemos passá-las diretamente aqui&lt;/span&gt;
      &lt;span class="na"&gt;HISTFILE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/app/.bash_history&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um problema surge com essa solução, entretanto. Agora eu tenho um arquivo novo na raiz do meu projeto, um arquivo que o git vai ver, a menos que eu o coloque no nosso &lt;code&gt;.gitignore&lt;/code&gt;, coisa que eu realmente acho que devíamos. Eu não quero commitar meu histórico e nem quero puxar o histórico de outras pessoas, até porque isso acabaria com o propósito de ter um arquivo de histórico. Além disso, acabei de criar um novo arquivo na raiz, que pode ficar poluindo o diretório base do projeto. Talvez aches um outro lugar melhor para esses arquivos.&lt;/p&gt;

&lt;p&gt;E isso é praticamente tudo! Eu não sei o quão ruim ou boa é essa ideia, mas estou gostando até aqui. Eu criei um diretorio novo na raiz do projeto, &lt;code&gt;dotfiles/&lt;/code&gt;, que tem também outros arquivos parecidos, como &lt;code&gt;.irb_history&lt;/code&gt; e &lt;code&gt;.irbrc&lt;/code&gt; em um projeto &lt;strong&gt;ruby&lt;/strong&gt;. Pra conseguir ter isso tudo funcionando, eu tive que adicionar as seguintes linhas ao arquivo &lt;code&gt;dotfiles/.irbrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'irb/ext/save-history'&lt;/span&gt;
&lt;span class="no"&gt;IRB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:SAVE_HISTORY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;
&lt;span class="no"&gt;IRB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:HISTORY_FILE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'IRB_HISTFILE'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E agora definir não somente a variável &lt;code&gt;HISTFILE&lt;/code&gt; como também&lt;br&gt;
as variáveis &lt;code&gt;IRBRC&lt;/code&gt; e &lt;code&gt;IRB_HISTFILE&lt;/code&gt;, assim:&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="nv"&gt;HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.bash_history
&lt;span class="nv"&gt;IRBRC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.irbrc
&lt;span class="nv"&gt;IRB_HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.irb_history
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma nota importante sobre o &lt;strong&gt;IRB&lt;/strong&gt;, se você deixar o arquivo &lt;code&gt;.irbrc&lt;/code&gt; na raiz, toda vez que você abrir o IRB, ele vai usar o &lt;code&gt;.irbrc&lt;/code&gt; do projeto, visto que ele é encontrado primeiro. Isso pode não ser desejado, talvez você queira usar o seu próprio IRB normal. Nesse caso, colocar o arquivo &lt;code&gt;.irbrc&lt;/code&gt; dentro de outro diretório, como &lt;code&gt;dotfiles/&lt;/code&gt;, passa a ser essencial.&lt;/p&gt;

&lt;p&gt;Obrigado por lerem! (:&lt;/p&gt;

</description>
      <category>docker</category>
      <category>bash</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Bash history inside Docker Containers</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 25 May 2022 13:09:55 +0000</pubDate>
      <link>https://dev.to/lucassperez/bash-history-inside-docker-container-553g</link>
      <guid>https://dev.to/lucassperez/bash-history-inside-docker-container-553g</guid>
      <description>&lt;p&gt;🇵🇹 Versão em português deste texto &lt;a href="https://dev.to/lucassperez/bash-history-inside-docker-container-4j2m"&gt;&lt;em&gt;aqui&lt;/em&gt;&lt;/a&gt;! 🇧🇷&lt;/p&gt;

&lt;p&gt;I don't know about other people, but I love having a docker development environment. Being able to just run a docker container with all the dependencies taken care of for all projects, handling versions and etc is just too good.&lt;/p&gt;

&lt;p&gt;But what I don't love is when I exit the container and later start it again to realize I have lost all the previous commands, so I can neither &lt;code&gt;crtl+R&lt;/code&gt; nor &lt;code&gt;up&lt;/code&gt;/&lt;code&gt;ctrl+P&lt;/code&gt; to find them. Sad times!&lt;/p&gt;

&lt;p&gt;So I decided to try to keep this history, and in order to figure out how to do that, I first thought, &lt;em&gt;how does bash itself knows the previous commands?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It turns out there is an env var named &lt;code&gt;HISTFILE&lt;/code&gt;, which will contain a path to a text file with the bash history. Apparently, by default it is set to &lt;code&gt;$HOME/.bash_history&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;OBS: If your container does not run bash, but rather some other shell, we would have to find out where this other shell puts its history file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So a workaround I have found is to change this env var to somewhere else, somewhere inside the project's dir that I'm working on to avoid losing it after stopping the container.&lt;/p&gt;

&lt;p&gt;Lets say that the docker image builds a &lt;code&gt;/app&lt;/code&gt; folder with all the contents of the directory of the project I'm working on inside it, I could set &lt;code&gt;HISTFILE&lt;/code&gt; to &lt;code&gt;/app/.bash_history&lt;/code&gt;, and if we map with a volume with the project's dir contents, I would have a persistent history of commands between docker sessions. The file name itself doesn't even have to be &lt;code&gt;.bash_history&lt;/code&gt;, it could be something like &lt;code&gt;/app/.docker_bash_history&lt;/code&gt;, for example.&lt;/p&gt;

&lt;p&gt;To start a container with a specific variable, we can use the &lt;code&gt;-e&lt;/code&gt; option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/.bash_history &lt;span class="nt"&gt;-v&lt;/span&gt; &amp;lt;volume&amp;gt; &amp;lt;...other stuff...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we are using &lt;strong&gt;Docker Compose&lt;/strong&gt;, we could either pass an env file or the direct variables to it in the &lt;code&gt;docker-compose.yml&lt;/code&gt; (or other config file you may be using):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# example config file&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/app&lt;/span&gt; &lt;span class="c1"&gt;# mapping this volume to persist modifications to our new history file&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo Hi!&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# we can define the variables inside the .env file&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# or we can pass them directly here&lt;/span&gt;
      &lt;span class="na"&gt;HISTFILE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/app/.bash_history&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A problem with this approach arises, though. I now have a new file in my project's root, a file that git will see, unless we put it in our &lt;code&gt;.gitignore&lt;/code&gt;, and I really think we should. I don't want to commit my history nor do I want to pull other people's history, because this would defeat the purpose of having a history file. Other than that, I just created a new file in the root, which could cause some noise and litter the root folder. Maybe you can find a better place other than the app's highest level folder.&lt;/p&gt;

&lt;p&gt;And that's pretty much it. I don't know how bad or good of an idea this is, but I'm enjoying it so far. I created a &lt;code&gt;dotfiles/&lt;/code&gt; folder inside the root that also has other dot files, like &lt;code&gt;.irb_history&lt;/code&gt; and &lt;code&gt;.irbrc&lt;/code&gt; in a &lt;strong&gt;ruby&lt;/strong&gt; project. In order to get it working, I had to put this in &lt;code&gt;dotfiles/.irbrc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'irb/ext/save-history'&lt;/span&gt;
&lt;span class="no"&gt;IRB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:SAVE_HISTORY&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;
&lt;span class="no"&gt;IRB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:HISTORY_FILE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'IRB_HISTFILE'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then define not only &lt;code&gt;HISTFILE&lt;/code&gt;, but also &lt;code&gt;IRBRC&lt;/code&gt; and &lt;code&gt;IRB_HISTFILE&lt;/code&gt; environment variables, like this:&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="nv"&gt;HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.bash_history
&lt;span class="nv"&gt;IRBRC&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.irbrc
&lt;span class="nv"&gt;IRB_HISTFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/app/dotfiles/.irb_history
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An important note on &lt;strong&gt;IRB&lt;/strong&gt;, if you leave the &lt;code&gt;.irbrc&lt;/code&gt; file in the root folder, everytime you fire up IRB, it is going to use the project's &lt;code&gt;.irbrc&lt;/code&gt;, since it is the first found config file for IRB. This could be undesirable, though. In this case, putting the &lt;code&gt;.irbrc&lt;/code&gt; inside another directory, like &lt;code&gt;dotfiles/&lt;/code&gt;, becomes essential.&lt;/p&gt;

&lt;p&gt;Thanks for reading! (:&lt;/p&gt;

</description>
      <category>docker</category>
      <category>bash</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Funções recursivas e anônimas em Elixir</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Thu, 24 Feb 2022 17:53:59 +0000</pubDate>
      <link>https://dev.to/lucassperez/funcoes-recursivas-e-anonimas-em-elixir-347i</link>
      <guid>https://dev.to/lucassperez/funcoes-recursivas-e-anonimas-em-elixir-347i</guid>
      <description>&lt;p&gt;🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text &lt;a href="https://dev.to/lucassperez/recursive-anonymous-function-in-elixir-pn3"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Um tempo atrás, eu tentei criar uma função recursiva e anônima em Elixir porque eu estava dentro do &lt;strong&gt;iex&lt;/strong&gt; e estava com preguiça de criar um módulo dentro do &lt;em&gt;repl&lt;/em&gt;. Minha primeira tentativa foi algo 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="c1"&gt;# Fatorial ingênuo, anônimo e recursivo&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&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="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;OBS: Sim, é possível definir múltiplas cláusulas para funções anônimas!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;É claro que isso não funcionou, porque &lt;code&gt;fact/1&lt;/code&gt; ainda não está definida no momento em que é chamada dentro do corpo da função.&lt;/p&gt;

&lt;p&gt;Eu realmente não lembro &lt;em&gt;por que&lt;/em&gt; eu precisava de uma função anônima e recursiva, mas no começo dessa semana eu percebi o que que eu tinha que fazer para que funcionasse. Tudo o que temos que fazer é assegurar-nos que a função existe no momento em que é chamada, certo?&lt;/p&gt;

&lt;p&gt;E se a função anônima recebesse, então, outra função como argumento, e essa função recebida fosse a que faz a chamada recursiva?&lt;/p&gt;

&lt;p&gt;Agora o Elixir não poderia reclamar da função não estar definida, porque ela foi fornecida via um argumento, que poderia ser qualquer coisa:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bom, mas o que &lt;strong&gt;é&lt;/strong&gt; essa função &lt;code&gt;recur&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Ela poderia muito bem ser a própria &lt;code&gt;fact&lt;/code&gt;! Somente temos que passá-la quanto a estivermos chamando:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="c1"&gt;# Passe fact para si mesma, para que ela seja "recur" dentro do corpo da função&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É claro que isso vai lançar uma exceção, pois agora &lt;strong&gt;fact&lt;/strong&gt; tem uma aridade de &lt;strong&gt;2&lt;/strong&gt;, e &lt;strong&gt;recur&lt;/strong&gt; está sendo chamada com apenas um argumento. Lembre-se que &lt;strong&gt;recur&lt;/strong&gt; é de "facto" &lt;strong&gt;fact&lt;/strong&gt;! &lt;em&gt;Sim, tentei fazer um trocadilho.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Para resolver isso, tudo que temos que fazer é chamar &lt;strong&gt;recur&lt;/strong&gt; passando &lt;strong&gt;recur&lt;/strong&gt; para si mesmo, 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="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; 24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Também funciona com recursão de cauda, é claro. Tudo que teríamos que fazer é gerenciar os parâmetros e retornos corretamente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Legal, posso usar isso num Enum.map ou alguma outra função de ordem superior?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bom, somente se tomarmos cuidado.&lt;/p&gt;

&lt;p&gt;Se escrevermos isso:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então &lt;strong&gt;Enum.map/2&lt;/strong&gt; tentará invocar &lt;code&gt;fact&lt;/code&gt; com um argumento apenas, lançando uma exceção.&lt;/p&gt;

&lt;p&gt;Uma maneira de resolver isso seria encapsulando-a dentro de uma outra funçã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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outra maneira seria definir &lt;strong&gt;fact&lt;/strong&gt; com uma interface mais legal.&lt;/p&gt;

&lt;p&gt;A função &lt;strong&gt;fact&lt;/strong&gt; poderia simplesmente receber um argumento e daí definir a função anônima e recursiva dentro de si mesma, e daí chamar a função anônima recém definida passando a mesma como argumento.&lt;/p&gt;

&lt;p&gt;Seria algo 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="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_fact&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora nós temos uma função recursiva e anônima que funciona como o esperado. Se eu quiser saber o fatorial de um número, apenas tenho que passar o número para a função, que é exatamente o que &lt;strong&gt;Enum.map&lt;/strong&gt; tentará fazer.&lt;/p&gt;

&lt;p&gt;Até definir na mesma linha essa função anônima funcionará:&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="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_fact&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="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E recursiva de cauda:&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="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;_&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="n"&gt;n&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="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Lembre-se de definir corretamente o valor inicial do acumulador. Aqui ele é 1&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="n"&gt;do_fact&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="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ter uma interface mais legal não é bom somente para usá-la como argumentos de uma função de order superior, também é mais legal para nós invocarmos essa função, é claro:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;_&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="n"&gt;n&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="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="n"&gt;do_fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# Não há necessidade de passar nem o acumulador nem a própria função&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="c1"&gt;#=&amp;gt; 24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora se eu quiser saber o fatorial de 4, tenho que apenas chamar a função &lt;code&gt;fact/1&lt;/code&gt; com &lt;strong&gt;4&lt;/strong&gt; como argumento, sem ter essas coisas estranhas de passar a própria função por aí manualmente na chamada.&lt;/p&gt;

&lt;h2&gt;
  
  
  Legal, mas isso é útil?
&lt;/h2&gt;

&lt;p&gt;Para ser sincero, eu não sei.&lt;/p&gt;

&lt;p&gt;Para começo de conversa, não é ilegal definir um módulo dentro do repl, então o cenário de "Estou com preguiça dentro do iex" não é tão importante assim. Quero dizer, eu tive que escrever tanta coisa a mais só para criar essa função recursiva e anônima que talvez simplesmente escrever &lt;code&gt;defmodule M do ... end&lt;/code&gt; seja mais fácil e mais rápido.&lt;/p&gt;

&lt;p&gt;Outra situação em que poderíamos usar isso seria em arquivos elixir normais onde temos algums &lt;strong&gt;Enums&lt;/strong&gt; ou outras funções de ordem superior trabalhando, mas daí a gente provavelmente já vai estar dentro de um módulo, onde poderíamos definir uma função privada "com nome" (não anônima) para fazer esse trabalho e já dando um nome significativo a ela, aproveitando que vamos estar ali. Isso vai culminar num código melhor e mais legível do que a "solução" com as funções recursivas e anônimas malucas.&lt;/p&gt;

&lt;p&gt;Mas ei, mesmo que isso não seja assim tão útil, pelo menos é sempre legal pensar sobre funções e recursão, certo?&lt;/p&gt;

&lt;p&gt;E também foi bem divertido escrever esse post! 😁&lt;/p&gt;

&lt;p&gt;É isso por hoje. Obrigado por ler e tenha um bom dia! (:&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>functional</category>
    </item>
    <item>
      <title>Recursive anonymous functions in Elixir</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Thu, 24 Feb 2022 17:25:13 +0000</pubDate>
      <link>https://dev.to/lucassperez/recursive-anonymous-function-in-elixir-pn3</link>
      <guid>https://dev.to/lucassperez/recursive-anonymous-function-in-elixir-pn3</guid>
      <description>&lt;p&gt;🇵🇹 Versão em português desse texto &lt;a href="https://dev.to/lucassperez/funcoes-recursivas-e-anonimas-em-elixir-347i"&gt;&lt;em&gt;aqui&lt;/em&gt;&lt;/a&gt;! 🇧🇷&lt;/p&gt;

&lt;p&gt;Some time ago I tried to create a recursive anonymous function in Elixir because I was inside &lt;strong&gt;iex&lt;/strong&gt; and was feeling lazy about creating a module inside the repl. My first attempt was something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Anonymous recursive naive factorial&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&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="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Side note: Yes, you can define multiple clauses for anonymous functions!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This, of course, does not work, because &lt;code&gt;fact/1&lt;/code&gt; is not yet defined when it is called inside the function body.&lt;/p&gt;

&lt;p&gt;I really do not remember &lt;em&gt;why&lt;/em&gt; I needed a recursive anonymous function, but early this week I realized what I had to do in order to make it work. All we have to do is make sure the recursive function exists at the moment it is called, right?&lt;/p&gt;

&lt;p&gt;So what if the anonymous function receives another function as an argument, and this received function is what is going to make the recursive call?&lt;/p&gt;

&lt;p&gt;Now Elixir could not complain about the function not being defined, because I was supplied as an argument, which could be anything:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, but what &lt;strong&gt;is&lt;/strong&gt; this &lt;code&gt;recur&lt;/code&gt; function?&lt;/p&gt;

&lt;p&gt;It could very well be &lt;code&gt;fact&lt;/code&gt; itself! We just have to pass it when calling:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="c1"&gt;# Pass fact to itself, so it will be "recur" inside the function body&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course this will raise an exception, because now &lt;strong&gt;fact&lt;/strong&gt; has an arity of &lt;strong&gt;2&lt;/strong&gt;, and &lt;strong&gt;recur&lt;/strong&gt; is being called with only one argument. Remember that &lt;strong&gt;recur&lt;/strong&gt; is in fact &lt;strong&gt;fact&lt;/strong&gt;! No pun intended.&lt;/p&gt;

&lt;p&gt;To solve this, all we have to do is to call &lt;strong&gt;recur&lt;/strong&gt; passing &lt;strong&gt;recur&lt;/strong&gt; to itself, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; 24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works with tail recursion as well, of course. All you have to do is manage the parameters and returns correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nice, can I use it in an Enum.map or any other higher order function?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, only if we are careful.&lt;/p&gt;

&lt;p&gt;If we write this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then &lt;strong&gt;Enum.map/2&lt;/strong&gt; will try to invoke &lt;code&gt;fact&lt;/code&gt; with one argument only, raising an exception.&lt;/p&gt;

&lt;p&gt;One way to solve this would be to wrap it into another function:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
  &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
  &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way would be to define &lt;strong&gt;fact&lt;/strong&gt; with a nicer interface.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;fact&lt;/strong&gt; function could just receive an argument and then define the recursive anonymous function inside itself, and then call the just defined anonymous function passing it as the argument.&lt;/p&gt;

&lt;p&gt;Something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="n"&gt;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_fact&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;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="n"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a recursive anonymous function that works as expected. If I want to know the factorial of a number, I just have to pass the number to it, which is what &lt;strong&gt;Enum.map&lt;/strong&gt; will try to do.&lt;/p&gt;

&lt;p&gt;Even inline definition of this anonymous function will work:&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="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;do_fact&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="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And tail recursive:&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="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="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="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;_&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="n"&gt;n&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="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# Remember to correctly set the accumulator's initial value. Here it is 1&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="n"&gt;do_fact&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="c1"&gt;#=&amp;gt; [1, 2, 6, 24]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Having a nicer interface is not only good to use it as arguments of higher order functions, it is also nicer for us to invoke it normally, of course:&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;fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;do_fact&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;fn&lt;/span&gt;
    &lt;span class="mi"&gt;0&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;_&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="n"&gt;n&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="kn"&gt;recur&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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;n&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kn"&gt;recur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;do_fact&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&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="n"&gt;do_fact&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# No need to pass the accumulator nor the function itself&lt;/span&gt;
&lt;span class="n"&gt;fact&lt;/span&gt;&lt;span class="o"&gt;.&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="c1"&gt;#=&amp;gt; 24&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if I want to know the factorial of 4, I just have to call the function &lt;code&gt;fact/1&lt;/code&gt; with &lt;strong&gt;4&lt;/strong&gt; as an argument, no weird passing itself around manually on function calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nice, but is this useful?
&lt;/h2&gt;

&lt;p&gt;To be sincere, I do not know.&lt;/p&gt;

&lt;p&gt;For starters, it is not ilegal to define a module inside the repl, so the "I'm lazy in iex" scenario is not all that meaningful. I mean, I had to write so much extra content just to create this anonymous recursive function that simply writing &lt;code&gt;defmodule M do ... end&lt;/code&gt; might be easier and faster.&lt;/p&gt;

&lt;p&gt;Another situation where we could use this would be in normal elixir files where we have some &lt;strong&gt;Enum&lt;/strong&gt; functions or other higher order functions work, but then we would probably already be inside a module, where we could define a named private function to do this work and give it a meaningful name while we're at this, culminating in a better, more readable code than the "solution" with the crazy recursive anonymous functions.&lt;/p&gt;

&lt;p&gt;But hey, even if it is not all that useful, at least it is always nice to think about functions and recursion, right?&lt;/p&gt;

&lt;p&gt;And it was also very fun to write this post! 😁&lt;/p&gt;

&lt;p&gt;That's it for today. Thanks for reading, and have a nice day! (:&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>functional</category>
    </item>
    <item>
      <title>Como mostrar apenas os commits da branch atual</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Mon, 04 Oct 2021 18:35:45 +0000</pubDate>
      <link>https://dev.to/lucassperez/shell-script-para-mostrar-um-range-de-commits-13ah</link>
      <guid>https://dev.to/lucassperez/shell-script-para-mostrar-um-range-de-commits-13ah</guid>
      <description>&lt;p&gt;🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text &lt;a href="https://dev.to/lucassperez/shell-script-to-show-a-range-of-git-commits-44ne"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Volta e meia eu crio aliases que executam comandos com algumas opções que eu uso com frequência. Um deles é o meu alias para &lt;code&gt;git log --oneline&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O problema é que quando eu executo esse comando, vários commits aparecem na minha tela até que ela fique completamente cheia, enquanto que a última linha indica que existem ainda mais commits. Se eu apertar &lt;code&gt;q&lt;/code&gt;, eu volto para a minha linha de comando, mas o commit mais recente de todos será empurrado para fora da tela (isso acontece comigo porque o meu prompt ocupa duas linhas).&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%2Fs1q5dgtf6qsxiinqefsh.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%2Fs1q5dgtf6qsxiinqefsh.png" alt="imagem de commits do git preenchendo completamente a tela de um terminal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Além desse problema específico do meu prompt grande, eu normalmente também quero apenas os commits na branch em que estou agora. Uma maneira simples que passou pela minha cabeça seria &lt;code&gt;git log --oneline main..HEAD&lt;/code&gt; (ou talvez usando &lt;code&gt;main^&lt;/code&gt;). Isso parecia apenas que seria mais um alias pra minha coleção, mas daí eu lembrei que tenho projetos com branch a &lt;code&gt;main&lt;/code&gt; e projetos com branch a &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Decidi, então, praticar minhas habilidades de shell script e fazer um programinha que decidiria automaticamente entre usar main ou master.&lt;/p&gt;

&lt;h2&gt;
  
  
  Primeiramente
&lt;/h2&gt;

&lt;p&gt;Antes de começar, deixe-me planejar tudo que será feito de antemão.&lt;/p&gt;

&lt;p&gt;Se eu fosse escrever pseudo código desse script ou resumí-lo em passos, como seria?&lt;br&gt;
Além disso, o que deveria acontecer se eu não estiver em um repositório git?&lt;br&gt;
Vamos pensar sobre essas coisas enquanto escrevemos um plano:&lt;/p&gt;

&lt;h3&gt;
  
  
  Temos que:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Imprimir alguma mesangem de erro e sair com código não zero caso não estejamos em um repo git&lt;/li&gt;
&lt;li&gt;Descobrir se ou main ou master estão disponíveis&lt;/li&gt;
&lt;li&gt;Executar &lt;code&gt;git log main^/master^..HEAD&lt;/code&gt; se possível&lt;/li&gt;
&lt;li&gt;Imprimir alguma mensagem de erro e sair com código não zero caso contrário&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1 - Verificar se estamos em um repositório git
&lt;/h3&gt;

&lt;p&gt;Uma maneira simples, e não muito boa, seria de apenas executar &lt;code&gt;ls .git&lt;/code&gt;. Se sair 0, estamos num repositório git. Se não, não estamos.&lt;/p&gt;

&lt;p&gt;Essa não é uma solução muito boa porque não vai funcionar se estivermos dentro de um subdiretório de um repositório git. Temos que pensar em outra forma. Torcemos para que o git já tenha uma maneira simples e fácil de verificar isso.&lt;/p&gt;

&lt;p&gt;E certamente tem, já que o git é tão legal.&lt;/p&gt;

&lt;p&gt;Uma pesquisa rápida no google me mostrou que o comando &lt;code&gt;git rev-parse --git-dir&lt;/code&gt; pode ser usado para isso. &lt;code&gt;man git rev-parse&lt;/code&gt; mostra mais detalhes, e a opção &lt;code&gt;--git-dir&lt;/code&gt; realmente parece uma boa opção. Quando não estamos em um repositório git, um erro será impresso na tela e um código não zero será retornado, segundo o manual.&lt;/p&gt;

&lt;p&gt;Eu não estou realmente interessado na mensagem de erro, apenas no código de saída (zero ou não zero).&lt;/p&gt;

&lt;p&gt;Portanto, para verificar se estamos ou não em um repositório git ao mesmo tempo que escondemos mensagens de erro, eu fiz assim:&lt;/p&gt;

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

&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--git-dir&lt;/span&gt; 2&amp;gt; /dev/null&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;Not &lt;span class="k"&gt;in &lt;/span&gt;a git repository
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;A sintaxe &lt;code&gt;[ ... ]&lt;/code&gt; é uma forma reduzida do comando &lt;code&gt;test&lt;/code&gt;.&lt;br&gt;
O &lt;code&gt;!&lt;/code&gt; vai inverter a verificação, isto é, se o comando (nesse caso &lt;code&gt;git rev-parse --git-dir&lt;/code&gt;) retornar 0, então ele será considerado "falso" ou que resultou em uma "falha".&lt;br&gt;
O &lt;code&gt;2&amp;gt; /dev/null&lt;/code&gt; está redirecionando a mensagem de erro para &lt;code&gt;/dev/null&lt;/code&gt;. Isso é uma maneira simples de apenas não mostrar mensagens de erro na tela.&lt;/p&gt;

&lt;p&gt;Então basicamente o que isso está fazendo é verificando se o comando falhou. Se sim, significa que não estamos num repositório git, então uma mensagem de erro é impressa e o script retorna 1. Do contrário, nada acontece e podemos seguir para os nossos próximos passos.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 - Descobrir se main ou master existem
&lt;/h3&gt;

&lt;p&gt;Podemos fazer isso usando o comando &lt;code&gt;git branch&lt;/code&gt; e o comando &lt;code&gt;grep&lt;/code&gt;, mas &lt;code&gt;git rev-parse&lt;/code&gt; também pode fazê-lo.&lt;/p&gt;

&lt;p&gt;A segunda opção é bastante simples, &lt;code&gt;git rev-parse --verify &amp;lt;nome-da-branch&amp;gt;&lt;/code&gt; é o suficiente (passe &lt;code&gt;-q&lt;/code&gt; para suprimir mensagens de erro):&lt;/p&gt;

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

git rev-parse -q --verify main


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

&lt;/div&gt;

&lt;p&gt;Pra mudar um pouco, porém, vou fazer com o grep. Dessa forma, podemos aprender um pouquinho mais sobre regexes!&lt;/p&gt;

&lt;p&gt;O comando &lt;code&gt;git branch&lt;/code&gt; mostra todas as branches disponíveis na sua máquina local, com a branch atual sendo precedida por um &lt;code&gt;*&lt;/code&gt;.&lt;br&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%2Fygliwcc1z74ec054iug2.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%2Fygliwcc1z74ec054iug2.png" alt="imagem do comando git branch mostrando mostrando as banches main e another-branch"&gt;&lt;/a&gt;&lt;br&gt;
Basicamente podemos usar o &lt;code&gt;grep&lt;/code&gt; passando &lt;code&gt;main&lt;/code&gt; ou &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Existe um perigo, porém. Simplesmente executar:&lt;/p&gt;

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

git branch | grep main


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

&lt;/div&gt;

&lt;p&gt;vai retornar com sucesso se alguma branch contendo a palavra main existir.&lt;br&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%2F0aaeyfx44vbnpa8pg61u.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%2F0aaeyfx44vbnpa8pg61u.png" alt="imagem do comando git branch com grep mostrando a branch main, mas também a branch not-main"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para resolver esse problema, podemos usar uma expressão regular melhor do que apenas &lt;code&gt;main&lt;/code&gt;. O padrão que buscamos é:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Começo da linha&lt;/li&gt;
&lt;li&gt;Possivelmente um &lt;code&gt;*&lt;/code&gt;, mas poderia não ter também&lt;/li&gt;
&lt;li&gt;Espaços em branco (a quantidade depende se um * estava lá ou não)&lt;/li&gt;
&lt;li&gt;A palavra main (ou master) exatamente&lt;/li&gt;
&lt;li&gt;Final da linha&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Vamos fazer por partes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;O regex para o começo da linha é &lt;code&gt;^&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Nos regexes, um &lt;code&gt;*&lt;/code&gt; é um quantificador, que significa &lt;em&gt;"a coisa antes de mim entre 0 e infinitas vezes"&lt;/em&gt;. Portanto, para encontrar literalmente um &lt;code&gt;*&lt;/code&gt;, temos que escapá-lo: &lt;code&gt;\*&lt;/code&gt;. Além disso, para tornálo opcional, podemos usar o quantificador &lt;code&gt;?&lt;/code&gt;, que significa &lt;em&gt;"a coisa antes de mim entre 0 e 1 vezes"&lt;/em&gt;. Portanto, o regex pra isso tudo seria &lt;code&gt;\*?&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Espaços em branco poderiam simplesmente ser um espaço ou &lt;code&gt;\s&lt;/code&gt;. Este último também encontra coisas como tabulações e quebra de linhas. Como a quantidade de espaços pode variar, podemos usar o quantificador &lt;code&gt;*&lt;/code&gt;, resultando em &lt;code&gt;\s*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;As palavras &lt;code&gt;main&lt;/code&gt; ou &lt;code&gt;master&lt;/code&gt; podem ser encontradas pelas palavras literais&lt;/li&gt;
&lt;li&gt;O regex para o final de uma linha é &lt;code&gt;$&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Portanto, nosso regex para a branch main seria &lt;code&gt;^\*?\s*main$&lt;/code&gt;. Para a master, é claro, é extremamente similar.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Um ponto importante, apra usar alguns caracteres especiais no regex, o comando grep deve ser invocado com a flag &lt;code&gt;-E&lt;/code&gt; (a opção de &lt;strong&gt;regex extendido&lt;/strong&gt;)!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;O comando final para a branch main, então, poderia ser:&lt;/p&gt;

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

git branch | grep -E '^\*?\s*main$'


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

&lt;/div&gt;

&lt;p&gt;Isso deve funcionar para nós.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 - Executar git log para a branch correta
&lt;/h3&gt;

&lt;p&gt;Podemos fazer isso com uma sequência de comandos &lt;code&gt;if/elif&lt;/code&gt;. Se main existir, usamos main. Se não, porém master existir, usamos master.&lt;/p&gt;

&lt;p&gt;Até poderíamos guardar o resultado do comando acima (git branch com grep) em uma variável e verificá-la. Dessa forma não teremos que executar &lt;code&gt;git branch&lt;/code&gt; duas vezes. Porém, também podemos passar diretamente o comando inteiro para o if, assim:&lt;/p&gt;

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

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Esse trecho é razoavelmente simples. É verificado se main existe usando aquele regex que definimos. Se existir, usamos o git log no range saindo de main (incluída, pois adicionamos o &lt;code&gt;^&lt;/code&gt;) até HEAD. Daí saímos 0 para finalizar o script (essa saída 0 provavelmente não é necessária e nem muito boa, pois se existir algum bug em nossa lógica/regex, o programa pode falhar silenciosamente, retornando 0 apesar de um erro!)&lt;/p&gt;

&lt;h3&gt;
  
  
  4 - Imprimir mensagem de erro e sair não zero caso main/master não sejam encontradas
&lt;/h3&gt;

&lt;p&gt;Podemos simplesmente adicionar um comando &lt;code&gt;else&lt;/code&gt; para o trecho acima:&lt;/p&gt;

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

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Mas funciona?
&lt;/h2&gt;

&lt;p&gt;Podemos testar nosso script agora! (:&lt;/p&gt;

&lt;p&gt;Eu salvei um arquivo chamado &lt;code&gt;git-log-main-master&lt;/code&gt; com nosso script e dei a ele permissão de execução. Vamos testá-lo:&lt;br&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%2Ff0hbkd3pwdhhck40a5pi.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%2Ff0hbkd3pwdhhck40a5pi.png" alt="imagem mostrando apenas commits de main até HEAD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso foi legal. Mas será que não conseguimos fazê-lo &lt;strong&gt;melhor&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;E se pudéssemos passar flags do git log para nosso script?&lt;/p&gt;
&lt;h3&gt;
  
  
  Flags!
&lt;/h3&gt;

&lt;p&gt;Isso é bastante simples de se fazer. Em um shell script, a variável especial &lt;code&gt;$@&lt;/code&gt; contém todos os argumentos passados ao script, então podemos simplesmente adicioná-lo às nossas linhas com "git log": &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Agora se passarmos um monte de flags, será executado o git log com essas opções:&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%2Fwpdp0w752ndb5ddfpgsi.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%2Fwpdp0w752ndb5ddfpgsi.png" alt="iamgem mostrando o script sendo executado com as flags --oneline e --graph corretamente"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas será que não podemos tornar esse script ainda mais legal de usar? E se passássemos um nome de uma branch pra usar ao invés de &lt;code&gt;main&lt;/code&gt; ou &lt;code&gt;master&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Isso com certeza pode ser feito. Quem sabe pudéssemos assumir que o primeiro argumento é ou um nome de branch ou uma flag, e usar as variáveis posicionais especiais &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;Talvez o comando pudesse ser &lt;code&gt;git log $1^..HEAD $FLAGS&lt;/code&gt;, onde &lt;code&gt;$FLAGS&lt;/code&gt; seriam todos os argumentos passados menos o primeiro.&lt;/p&gt;

&lt;p&gt;Isso envolveria um tratamento melhor e verificações pra ver se todos os argumentos passados são somente flags (daí poderíamos manter main/master e &lt;code&gt;$@&lt;/code&gt;) ou se um nome de branch foi passado. É certamente factível, mas vou deixar a possibilidade pra outro post por enquanto... 😅&lt;/p&gt;

&lt;h4&gt;
  
  
  Aliases...?
&lt;/h4&gt;

&lt;p&gt;Como eu disse, costumo fazer aliases para comandos simples com flags que uso comumente.  &lt;code&gt;--oneline&lt;/code&gt; é definitivamente uma das minhas opções mais usadas com git log, e é claro, eu fiz um alias:&lt;/p&gt;


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

&lt;p&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'~/scripts/git-log-main-master --oneline'&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Script no final das contas&lt;br&gt;
&lt;/h4&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;##############################&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# Non zero exit codes:&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;#   1 - If not in a git repository&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;#   2 - If neither git branch main nor master is found&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;##############################&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--git-dir&lt;/span&gt; 2&amp;gt; /dev/null&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;Not &lt;span class="k"&gt;in &lt;/span&gt;a git repository&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;br&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;if &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--verify&lt;/span&gt; main&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;git log main^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;br&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--verify&lt;/span&gt; master&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;git log master^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;br&gt;
&lt;span class="k"&gt;else&lt;br&gt;
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;2&lt;br&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Isso é tudo por hoje&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Ainda estou aprendendo o básico de shell script, e deve haver maneiras melhores de se fazer isso. Qualquer comentário e sugestão é mais do que bem vindo! 😊&lt;/p&gt;

</description>
      <category>git</category>
      <category>shell</category>
      <category>cli</category>
    </item>
    <item>
      <title>How to only show commits of current branch</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Mon, 04 Oct 2021 18:33:14 +0000</pubDate>
      <link>https://dev.to/lucassperez/shell-script-to-show-a-range-of-git-commits-44ne</link>
      <guid>https://dev.to/lucassperez/shell-script-to-show-a-range-of-git-commits-44ne</guid>
      <description>&lt;p&gt;🇵🇹 Versão em português desse texto &lt;a href="https://dev.to/lucassperez/shell-script-para-mostrar-um-range-de-commits-13ah"&gt;&lt;em&gt;aqui&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Every now and then I make aliases that execute a command with a few flags that I use often. One of them being an alias for &lt;code&gt;git log --oneline&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The problem is that when I executed this command, it would show all the commits untill my screen is filled, and the last line shows that it has more to come. If I press &lt;code&gt;q&lt;/code&gt;, I will return to my prompt, but the most recent commit will be pushed out of my screen (because my prompt has two lines).&lt;br&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%2Fs1q5dgtf6qsxiinqefsh.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%2Fs1q5dgtf6qsxiinqefsh.png" alt="image of git commits filling up entirely a terminal screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Other than this specific problem to my big prompt, I usually just want the commits on the branch I am right now. A simple way that crossed my mind was &lt;code&gt;git log --oneline main..HEAD&lt;/code&gt; (or maybe use &lt;code&gt;main^&lt;/code&gt;). This looked like a simple new alias for my collection, but then I remembered that I have projects with a &lt;code&gt;main&lt;/code&gt; branch and also other projects with a &lt;code&gt;master&lt;/code&gt; branch.&lt;/p&gt;

&lt;p&gt;I decided, then, to practice my shell scripting and make a script that would decide between main or master automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  First things first
&lt;/h2&gt;

&lt;p&gt;Before starting, let me plan what will be done beforehand.&lt;/p&gt;

&lt;p&gt;If I would write some pseudo code of this script or summarize it in steps, how would that be?&lt;br&gt;
Also, what should happen if I am not in a git repository?&lt;br&gt;
Let's think about these things while writing down a plan:&lt;/p&gt;

&lt;h3&gt;
  
  
  We have to:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Print some error message and exit non zero code if not in a git repository&lt;/li&gt;
&lt;li&gt;Find out if either main or master branch is available&lt;/li&gt;
&lt;li&gt;Execute &lt;code&gt;git log main^/master^..HEAD&lt;/code&gt; if possible&lt;/li&gt;
&lt;li&gt;Print some error message and exit non zero code otherwise&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1 - Check if in a git repository
&lt;/h3&gt;

&lt;p&gt;A simple, and not very good, way would be to just execute &lt;code&gt;ls .git&lt;/code&gt;. If it exits 0, we are in a git repo. If not, then we are not.&lt;/p&gt;

&lt;p&gt;This is not a very good solution because it will not work if we are inside a subdirectory of a git repository. We have to think about something else, but hopefully git itself already has some quick way to check this.&lt;/p&gt;

&lt;p&gt;And surely it has, since git is so nice.&lt;/p&gt;

&lt;p&gt;A quick google search showed me that the command &lt;code&gt;git rev-parse --git-dir&lt;/code&gt; can be used for this task. &lt;code&gt;man git rev-parse&lt;/code&gt; shows more details, and the &lt;code&gt;--git-dir&lt;/code&gt; option indeed looks like a good option. When we are not in a git repo, it prints an error message and exits "non zero", according to the manual.&lt;/p&gt;

&lt;p&gt;I'm not really interested in the error message, just the exit code (zero or non zero).&lt;/p&gt;

&lt;p&gt;So to check if we are in a git repository while also hiding possible error messages, I did this:&lt;/p&gt;

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

&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;

&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--git-dir&lt;/span&gt; 2&amp;gt; /dev/null&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;Not &lt;span class="k"&gt;in &lt;/span&gt;a git repository
  &lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;[ ... ]&lt;/code&gt; syntax is a shorthand for the &lt;code&gt;test&lt;/code&gt; command.&lt;br&gt;
The &lt;code&gt;!&lt;/code&gt; will invert the check, if the command (in this case, &lt;code&gt;git rev-parse --git-dir&lt;/code&gt;) returns 0, then this will be considered "false", or a "failure".&lt;br&gt;
The &lt;code&gt;2&amp;gt; /dev/null&lt;/code&gt; is redirecting the error message to &lt;code&gt;/dev/null&lt;/code&gt;. This is a simple way of not showing error messages.&lt;/p&gt;

&lt;p&gt;So basically what this is doing is checking if the command failed. If it did fail, it means we are not in a git repo, so an error message is printed and the script returns 1. If the command succeeds, nothing happens, and we can proceed to our next steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 - Find out if main or master exists
&lt;/h3&gt;

&lt;p&gt;We can do this using the &lt;code&gt;git branch&lt;/code&gt; command and some grepping, but &lt;code&gt;git rev-parse&lt;/code&gt; can also do it.&lt;/p&gt;

&lt;p&gt;The second option is very simple, &lt;code&gt;git rev-parse --verify &amp;lt;branch-name&amp;gt;&lt;/code&gt; will do the trick (pass &lt;code&gt;-q&lt;/code&gt; to hide error messages):&lt;/p&gt;

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

git rev-parse -q --verify main


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

&lt;/div&gt;

&lt;p&gt;Just for a change, though, I'll use the simple (maybe naive) grep way. By doing so, we can learn more about regexes!&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;git branch&lt;/code&gt; shows all the branches you have avaiable in your local machine, with the current branch being preceded by a &lt;code&gt;*&lt;/code&gt;.&lt;br&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%2Fygliwcc1z74ec054iug2.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%2Fygliwcc1z74ec054iug2.png" alt="image of git branch showing a main branch and another-branch"&gt;&lt;/a&gt;&lt;br&gt;
Basically we can grep for &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;There is a danger, though. Simply executing:&lt;/p&gt;

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

git branch | grep main


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

&lt;/div&gt;

&lt;p&gt;will return successfully if any branch containing the word main exists.&lt;br&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%2F0aaeyfx44vbnpa8pg61u.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%2F0aaeyfx44vbnpa8pg61u.png" alt="image of git branch showing main branch but also not-main branch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To solve this problem, we can use a better regular expression than just &lt;code&gt;main&lt;/code&gt;. The pattern we are looking for is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start of the line&lt;/li&gt;
&lt;li&gt;Possibly a &lt;code&gt;*&lt;/code&gt;, but could not have it&lt;/li&gt;
&lt;li&gt;Whitespaces (the amount depends if a * was there or not)&lt;/li&gt;
&lt;li&gt;The word main (or master) exactly&lt;/li&gt;
&lt;li&gt;End of the line&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's break down how to do each part:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The regex start of the line token is &lt;code&gt;^&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In regex, a &lt;code&gt;*&lt;/code&gt; is a quantifier, meaning &lt;em&gt;"the thing before me between 0 and unlimited times"&lt;/em&gt;, so to match the &lt;code&gt;*&lt;/code&gt; literal, we have to escape it: &lt;code&gt;\*&lt;/code&gt;, and to make it optional, we use the &lt;code&gt;?&lt;/code&gt; quantifier (it means &lt;em&gt;"the thing before me between 0 and 1 times"&lt;/em&gt;). So to match a possible &lt;code&gt;*&lt;/code&gt;, the regex would be &lt;code&gt;\*?&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Whitespaces can be simply a space or &lt;code&gt;\s&lt;/code&gt;, the latter matching things like tabs and new lines also. The amount of whitespaces can vary, so we can use the &lt;code&gt;*&lt;/code&gt; quantifier, leaving us with &lt;code&gt;\s*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The words &lt;code&gt;main&lt;/code&gt; or &lt;code&gt;master&lt;/code&gt; can be matched with the literal words&lt;/li&gt;
&lt;li&gt;The end of the line is the token &lt;code&gt;$&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So our regex would be &lt;code&gt;^\*?\s*main$&lt;/code&gt; for the main branch. For the master, of course, is extremely similar.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An important note, to use some special regex characters, grep have to be invoked with the &lt;code&gt;-E&lt;/code&gt; flag (the &lt;strong&gt;extended regex&lt;/strong&gt; flag)!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The command for the main branch could then be:&lt;/p&gt;

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

git branch | grep -E '^\*?\s*main$'


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

&lt;/div&gt;

&lt;p&gt;This should work for us right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 - Execute git log for the correct branch
&lt;/h3&gt;

&lt;p&gt;We can do this with a sequence of &lt;code&gt;if/elif&lt;/code&gt; commands. If the main exists, use it. If not, but the master exists, use master instead.&lt;/p&gt;

&lt;p&gt;We could store the result of the last step in a variable and check it, or we could just check it directly:&lt;/p&gt;

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

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This snippet is fairly simple. It checks if main exists using the regex we defined. If it does, it git logs the range from the main (inclusive, since we added &lt;code&gt;^&lt;/code&gt;) to HEAD. It then exits 0 to finish the script (this exit is probably not needed and also not very good, because if there is some bug in our logic/regex, it can fail silently, exiting 0!).&lt;/p&gt;

&lt;h3&gt;
  
  
  4 - Print error message and exit non zero if main/master not found
&lt;/h3&gt;

&lt;p&gt;We can simply add an &lt;code&gt;else&lt;/code&gt; statement to the snippet above:&lt;/p&gt;

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

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Does it work?
&lt;/h2&gt;

&lt;p&gt;We can test our script now! (:&lt;/p&gt;

&lt;p&gt;I saved a file named &lt;code&gt;git-log-main-master&lt;/code&gt; with our script and gave it execution permission. Let's try it out:&lt;br&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%2Ff0hbkd3pwdhhck40a5pi.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%2Ff0hbkd3pwdhhck40a5pi.png" alt="image showing only commits from main to HEAD"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that's nice. But can we make it &lt;strong&gt;better&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;What if we could pass the standard git log flags to it?&lt;/p&gt;
&lt;h3&gt;
  
  
  Flags!
&lt;/h3&gt;

&lt;p&gt;This is fairly simple to do. In a shell script, the special variable &lt;code&gt;$@&lt;/code&gt; contains all the arguments passed to the script, so we can simply append it to our "git log" lines:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*main$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log main^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git branch | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'^\*?\s*master$'&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;git log master^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;else
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;
  &lt;span class="nb"&gt;exit &lt;/span&gt;2
&lt;span class="k"&gt;fi&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Now if we pass a bunch of flags, it is going to execute git log with those options:&lt;br&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%2Fwpdp0w752ndb5ddfpgsi.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%2Fwpdp0w752ndb5ddfpgsi.png" alt="image showing the script being run with --oneline and --graph flags correctly"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Is there a way to make it even nicer to use? What if we passed a branch name to use instead of either main or master?&lt;/p&gt;

&lt;p&gt;We could definitely do that. Maybe we could assume the first argument is either a branch name or a flag and use the positional special arguments &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt; etc.&lt;/p&gt;

&lt;p&gt;Maybe the command could be &lt;code&gt;git log $1^..HEAD $FLAGS&lt;/code&gt;, where &lt;code&gt;$FLAGS&lt;/code&gt; would be all the arguments passed but the first.&lt;/p&gt;

&lt;p&gt;This would involve some better treatment and checks to see if all the arguments are just flags (in this case we could keep main/master and &lt;code&gt;$@&lt;/code&gt;) or if a branch name was passed, and is definitely doable, but I'll leave for possibly another post for now... 😅&lt;/p&gt;

&lt;h4&gt;
  
  
  Aliases...?
&lt;/h4&gt;

&lt;p&gt;Like I said, I usually make aliases for simple commands with common flags. &lt;code&gt;--oneline&lt;/code&gt; is definitely one of my most used options for git log, and sure enough, I made an alias:&lt;/p&gt;


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

&lt;p&gt;&lt;span class="nb"&gt;alias &lt;/span&gt;&lt;span class="nv"&gt;gl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'~/scripts/git-log-main-master --oneline'&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h4&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Summed up script&lt;br&gt;
&lt;/h4&gt;
&lt;br&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="c"&gt;##############################&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;# Non zero exit codes:&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;#   1 - If not in a git repository&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;#   2 - If neither git branch main nor master is found&lt;/span&gt;&lt;br&gt;
&lt;span class="c"&gt;##############################&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&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="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;--git-dir&lt;/span&gt; 2&amp;gt; /dev/null&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;&lt;span class="nb"&gt;echo &lt;/span&gt;Not &lt;span class="k"&gt;in &lt;/span&gt;a git repository&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;1&lt;br&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;if &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--verify&lt;/span&gt; main&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;git log main^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;br&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;git rev-parse &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="nt"&gt;--verify&lt;/span&gt; master&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="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;br&gt;
  &lt;/span&gt;git log master^..HEAD &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;br&gt;
&lt;span class="k"&gt;else&lt;br&gt;
  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'Neither main nor master branch found'&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;2&lt;br&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  That's it for today&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;I'm still learning the very basics of shell scripting, and there are probably better ways of doing this. Any comment and advice is more than welcome! 😊&lt;/p&gt;

</description>
      <category>git</category>
      <category>shell</category>
      <category>cli</category>
    </item>
    <item>
      <title>Open all conflicted files from Command Line</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 28 Apr 2021 00:07:39 +0000</pubDate>
      <link>https://dev.to/lucassperez/open-all-files-with-a-conflict-from-command-line-184p</link>
      <guid>https://dev.to/lucassperez/open-all-files-with-a-conflict-from-command-line-184p</guid>
      <description>&lt;p&gt;A few days ago I learned more about the &lt;code&gt;xargs&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;For a brief explanation, &lt;code&gt;xargs&lt;/code&gt; will receive a chunk of text and transform it in a list of arguments and pass it to a command that you can specify.&lt;/p&gt;

&lt;p&gt;For instance, if you write in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e "file1\nfile2"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will see this result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;file1
file2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now could pipe this into &lt;code&gt;xargs&lt;/code&gt; and do something with it, say, create files with those names:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo -e "file1\nfile2" | xargs touch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just created two files whose names are file1 and file2.&lt;/p&gt;

&lt;p&gt;There are many things you could do with xargs, write &lt;code&gt;xargs -h&lt;/code&gt; to see more (the &lt;code&gt;-I&lt;/code&gt; flag is specially interesting).&lt;/p&gt;

&lt;p&gt;But what happened today was that I decided I wanted to open all files that had a conflict after an attempted &lt;code&gt;git rebase -i&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;To do that, we first have to find a way to list all the files with a conflict. I'm pretty sure there is nothing git &lt;strong&gt;can't&lt;/strong&gt; do, and of course what we want is very possible.&lt;/p&gt;

&lt;p&gt;The command &lt;code&gt;git diff&lt;/code&gt; can receive the flag &lt;code&gt;--name-only&lt;/code&gt;, which will give you just the names of the files that &lt;code&gt;git diff&lt;/code&gt; would have looked at.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user@pc:~$ git diff --name-only
app/this-guy
config/this-other-guy
user@pc:~$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is just what we wanted! We can now easily pipe it into &lt;code&gt;xargs&lt;/code&gt; and call a code editor, for example vim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git diff --name-only | xargs vim
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Xargs can be very useful, this is just one use case. Maybe you want to append a specific extension to a bunch of files? You could use find, ls and grep, just to pass them to xargs with a mv command, for instance.&lt;/p&gt;

&lt;p&gt;I hope someone else also learns a little with my little "playing around in terminal" thing.&lt;/p&gt;

&lt;p&gt;Thanks for reading and have a nice day (:&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>git</category>
    </item>
    <item>
      <title>Verificando parênteses, colchetes e chaves correspondentes com Elixir</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Thu, 08 Apr 2021 00:28:33 +0000</pubDate>
      <link>https://dev.to/lucassperez/verificando-parenteses-colchetes-e-chaves-correspondentes-com-elixir-jn0</link>
      <guid>https://dev.to/lucassperez/verificando-parenteses-colchetes-e-chaves-correspondentes-com-elixir-jn0</guid>
      <description>&lt;p&gt;🏴󠁧󠁢󠁥󠁮󠁧󠁿 English version of this text &lt;a href="https://dev.to/lucassperez/verify-matching-parens-brackets-and-braces-with-elixir-dh5"&gt;&lt;em&gt;here&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Eu comecei a estudar a linguagem Elixir e decidi resolver alguns exercícios de programação pra conseguir entender melhor alguns conceitos.&lt;br&gt;
Como eu acabei gostando da minha solução, decidi fazer esse post explicando o pensamento por trás dela. Sugestões pra melhorar ainda mais o código ou pra melhor seguir os padrões e convenções do Elixir são mais do que bem-vindos! (:&lt;/p&gt;
&lt;h2&gt;
  
  
  O Problema
&lt;/h2&gt;

&lt;p&gt;Quero fazer uma função que recebe uma string de entrada, supostamente uma expressão matemática ou um trecho de código, e que me diga se todos os seus abre parênteses/colcehetes/chaves são corretamente fechados.&lt;br&gt;
Algumas expressões 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="mi"&gt;1&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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="c1"&gt;# deveria retornar true&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# deveria retornar false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Faça um plano
&lt;/h2&gt;

&lt;p&gt;Antes de começar a escrever código, eu acho que é uma boa ideia resolver o problema de maneira teórica, para aí sim tentar implementá-lo.&lt;/p&gt;

&lt;p&gt;Pra esse exercício, eu acredito que usar o conceito de &lt;a href="https://pt.wikipedia.org/wiki/Pilha_(inform%C3%A1tica)"&gt;pilha&lt;/a&gt; seja uma boa ideia.&lt;br&gt;
Basicamente, uma pilha é um conjunto de itens que tem duas operações: &lt;strong&gt;push&lt;/strong&gt; e &lt;strong&gt;pop&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O push vai colocar um novo item no conjunto&lt;/li&gt;
&lt;li&gt;O pop vai remover o último item adicionado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ou seja, a pilha segue o princípio do "Last In, First Out" (LIFO), ou seja, "o último a entrar será o primeiro a sair".&lt;/p&gt;

&lt;p&gt;Mas como podemos usar uma pilha aqui? Bom, minha solução teórica seria de iterar sobre todos os caracteres na string de entrada e:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Se for uma "abertura" (&lt;code&gt;(&lt;/code&gt;, &lt;code&gt;[&lt;/code&gt; ou &lt;code&gt;{&lt;/code&gt;), colocamos na pilha&lt;/li&gt;
&lt;li&gt;Se for um "fechamento" (&lt;code&gt;)&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt; ou &lt;code&gt;}&lt;/code&gt;), temos que verificar o último item adicionado na pilha. Se forem correspondentes (&lt;code&gt;(&lt;/code&gt; com &lt;code&gt;)&lt;/code&gt;, por exemplo), nós removemos ele da pilha (&lt;em&gt;pop&lt;/em&gt;) e seguimos a iteração. Do contrário, a string de entrada era inválida&lt;/li&gt;
&lt;li&gt;Se for outra coisa, ignoramos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Se iterarmos sobre a expressão inteira e nunca acharmos um erro, isso significa que todos os fechamentos tiveram uma abertura apropriada, mas isso não significa necessariamente que a string era válida. Veja esse 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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aqui, todos os fechamentos tiveram uma abertura correta, mas nem todas as aberturas foram fechadas.&lt;br&gt;
Isso significa que, caso sobrevivamos à iteração, temos que verificar também se no final a nossa pilha está &lt;em&gt;vazia&lt;/em&gt;. Se sim, então todas as aberturas foram corretamente fechadas. Se não, o valor de entrada era inválido.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Implementação
&lt;/h2&gt;

&lt;p&gt;Boa, temos um plano. Agora, temos que traduzir isso para Elixir.&lt;br&gt;
Pra começar, vou criar um módulo chamado &lt;code&gt;Parens&lt;/code&gt; com a função &lt;code&gt;check&lt;/code&gt;, que vai receber uma string.&lt;br&gt;
Essa função &lt;code&gt;check&lt;/code&gt; terá que iterar sobre todos os caracteres desse valor de entrada, então podemos separar essa string usando a função &lt;code&gt;split/2&lt;/code&gt;, do módulo &lt;code&gt;String&lt;/code&gt;. Nosso primeiro trecho de código então é algo 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;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usei aqui o operador pipe &lt;code&gt;|&amp;gt;&lt;/code&gt;. O que ele faz é que ele usa o que vem antes como o primeiro argumento do que vier depois. Nesse caso, &lt;code&gt;expression&lt;/code&gt; será o primeiro argumento para &lt;code&gt;String.split&lt;/code&gt;.&lt;br&gt;
O segundo argumento nesse caso é uma string vazia, o que significa que vamos separar &lt;code&gt;expression&lt;/code&gt; em todos os caracteres.&lt;br&gt;
O resultado final será uma lista, tipo 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="s2"&gt;"a + b * (c / d)"&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;split&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="c1"&gt;# ["", "a", " ", "+", " ", "b", " ", "*", " ", "(", "c", " ", "/", " ", "d", ")", ""]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na nossa solução teórica, todos os caracteres diferentes de aberturas/fechamentos deveriam ser ignorados. Podemos removê-los da nossa lista agora usando um &lt;strong&gt;filter&lt;/strong&gt; (filtro). Pra fazer isso, podemos chamar &lt;code&gt;Enum.filter/2&lt;/code&gt;, que recebe dois argumentos.&lt;br&gt;
O primeiro deve ser algo "enumerável", que significa que deve ser algo que implementa o "protocolo" Enum.&lt;br&gt;
Felizmente, listas fazem isso, então podemos usar nosso resultado como primeiro argumento do filtro.&lt;br&gt;
O segundo argumento é uma &lt;em&gt;função&lt;/em&gt; que recebe um elemento da nossa lista e decide se ele deveria ou não estar no resultado filtrado. Mais especificamente, essa função vai retornar um valor, e se ele for &lt;em&gt;falsy&lt;/em&gt; (&lt;code&gt;false&lt;/code&gt; ou &lt;code&gt;nil&lt;/code&gt;), o filtro vai remover esse item do resultado final. Do contrário, ele vai estar na lista resultante.&lt;/p&gt;

&lt;p&gt;No nosso caso, essa função vai ter que verificar cada elemento e dizer se ele é ou uma abertura ou um fechamento, que são os únicos caracteres que nos importam. Uma maneira de se fazer isso é 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;fn&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&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;p&gt;Essa função anônima vai receber algo (&lt;em&gt;x&lt;/em&gt;) e ver se essa coisa pertence ou não àquela lista especificada, que contém somente os caracteres importantes (aberturas e fechamentos).&lt;br&gt;
Também poderíamos usar a notação de captura, 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="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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="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;Essa notação é parecida, mas ao invés de declarar o &lt;em&gt;x&lt;/em&gt;, a gente usa &amp;amp;1, &amp;amp;2, &amp;amp;3... para todos os argumentos que podem chegar.&lt;/p&gt;

&lt;p&gt;Beleza, então nosso código até aqui está 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;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="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;O próximo passo é iterar sobre nossa listra resultante (depois do filtro) e usar a nossa estratégia da pilha.&lt;br&gt;
Pra fazer isso, decidi criar uma &lt;strong&gt;função privada&lt;/strong&gt; chamada &lt;code&gt;iterate&lt;/code&gt;, onde vou recursivamente andar sobre nossos elementos, levando a pilha de um lado para o outro, até termos verificado todos os nossos elementos.&lt;br&gt;
Já que eu vou precisar da pilha, essa função terá uma aridade de 2, ou seja, ela terá 2 argumentos.&lt;br&gt;
A primeira coisa que eu faço quando estou pensando sobre recursão é de escrever a condição de parada. Nesse caso, a função deveria parar assim que a nossa lista de caracteres estiver vazia.&lt;br&gt;
Vou usar a funcionalidade maravilhosa de &lt;strong&gt;pattern matching&lt;/strong&gt; aqui pra fazer isso:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;stack&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;stack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso significa que essa função só vai ser executada quando o primeiro elemento for uma lista vazia, e o segundo elemento pode ser qualquer coisa aqui (que será colocado numa variável chamada &lt;code&gt;stack&lt;/code&gt;, que significa pilha em inglês).&lt;br&gt;
Nesse caso, a função não está fazendo nada, apenas retornando a pilha. Mais tarde podemos verificar se ela está vazia ou não.&lt;/p&gt;

&lt;p&gt;Um ponto muito importante pra perceber aqui é que também temos que passar a pilha quando chamamdos a função &lt;code&gt;iterate&lt;/code&gt; pela primeira vez. Nossa pilha começa vazia, então nossa pipeline ficou 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;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;&lt;em&gt;Obs: Também podemos usar um valor padrão aqui, mas deixarei assim.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Agora, a parte difícil. Depois de escrever a condição de parada da nossa recursão, temos que escrever o passo recursivo (ou passos).&lt;/p&gt;

&lt;p&gt;Vamos relembrar nosso plano outra vez. Temos que olhar pra cada elemento, e se for uma abertura, colocamos na pilha e seguimos em frente. Vamos fazer essa parte primeiro.&lt;/p&gt;

&lt;p&gt;Eu amo pattern matching, então vou estar usando aqui de novo. E pra ajudar-nos ainda mais, também usarei algumas &lt;strong&gt;guardas&lt;/strong&gt; (ou guard, em inglês), pra decidir se a função será executada ou nã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="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa função somente será executada se a variável &lt;code&gt;head&lt;/code&gt; estiver naquela lista de aberturas. Mas de onde essa variável está vindo?&lt;br&gt;
Estamos fazendo o pattern matching do primeiro argumento com &lt;code&gt;[head | tail]&lt;/code&gt;, então essa função vai precisar que o primeiro argumento seja uma lista que tenha um primeiro elemento. Esse elemento então vai ser vinculado/ligado (bind) a &lt;code&gt;head&lt;/code&gt;. O resto da lista será vinculado a &lt;code&gt;tail&lt;/code&gt;. Sempre que estiver em dúvida, podemos abrir o shell interativo do Elixir e fazer alguns testes.&lt;br&gt;
Escreva &lt;code&gt;iex&lt;/code&gt; no terminal e aperte enter, e tente alguns códigos como esses:&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="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&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="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="n"&gt;head&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;tail&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [2,3,4]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail2&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;head2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 0&lt;/span&gt;
&lt;span class="n"&gt;tail2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; []&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail3&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="c1"&gt;# Vai levantar um "matching error"!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os conceitos de "cabeça" e "cauda" de uma lista são bastante importantes (head e tail, respectivamente). O primeiro elemento de uma lista é sua cabeça, e a cauda será o resto da lista. Perceba que a cauda &lt;strong&gt;é também uma lista&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Okay, de volta pra nossa função. O que ela deveria fazer se o elemento sendo verificado for uma abertura?&lt;br&gt;
Ela deveria colocar na pilha (push) e seguir iterando. Podemos fazer isso simplesmente chamando &lt;code&gt;iterate&lt;/code&gt; com os argumentos certos.&lt;br&gt;
Como já verificamos o primeiro elemento, temos que passar a lista sem o primeiro elemento, certo? E isso é exatamente o que &lt;code&gt;tail&lt;/code&gt; é! Ótimo, mas como podemos adicionar (fazer o &lt;strong&gt;push&lt;/strong&gt;) esse elemento na pilha?&lt;br&gt;
O Elixir oferece uma maneira muito fácil de colocar um item no começo de uma lista, e é simplesmente 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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;elemento_novo&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;pilha&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é uma lista cuja cabeça é &lt;code&gt;elemento_novo&lt;/code&gt;, e a cauda é &lt;code&gt;pilha&lt;/code&gt;. Sempre podemos ir no iex e fazer alguns experimentos:&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [1,9,8,7]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Então, nossa função pode ficar meio 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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando &lt;code&gt;head&lt;/code&gt; for uma abertura, a gente chama &lt;code&gt;iterate&lt;/code&gt; passando &lt;code&gt;tail&lt;/code&gt; como primeiro argumento e a pilha com um novo elemento adicionado como segundo elemento.&lt;/p&gt;

&lt;p&gt;Legal! Agora que temos essa parte feita, vamos recapitular:&lt;/p&gt;

&lt;p&gt;Já sabemos parar a recursão;&lt;br&gt;
Já lidamos com os casos dos caracteres que não são nem aberturas, nem fechamentos;&lt;br&gt;
Já sabemos adicionar um item na pilha e seguir adiante;&lt;/p&gt;

&lt;p&gt;Agora temos que fazer alguma coisa quando o elemento é um fechamento. Quando isso acontece, a ideia era olhar o último item adicionado na nossa pilha, que por construção, vem a ser exatamente a cabeça da nossa pilha!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A próxima parte do código foi fortemente refatorada, mas eu vou mostrar como eu fiz inicialmente.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pra cada fechamento possível, eu fiz uma declaração específica, fazendo o pattern match na cabeça dos elementos que vão ser iterados, 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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"]"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;")"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E daí pra cada uma delas, eu fiz um if/else simples:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;false&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;Primeiro de tudo, aqui eu usei as funções &lt;code&gt;hd&lt;/code&gt; e &lt;code&gt;tl&lt;/code&gt;, que retornam a cabeça e a cauda de uma lista, respectivamente. Seria a mesma coisa que escrever isso:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;if&lt;/span&gt; &lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;false&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;Essa função, então, só vai executar se o primeiro elemento da lista for exatamente &lt;code&gt;}&lt;/code&gt;. Daí a gente verifica se o último elemento adicionado na pilha, sua cabeça (estamos adicionando as coisas "pela cabeça" na lista!) é &lt;code&gt;{&lt;/code&gt;, que seria a correspondência correta.&lt;br&gt;
Se for, temos que fazer o &lt;em&gt;pop&lt;/em&gt; desse elemento, era o nosso plano. Perceba que a versão "popada" da pilha é simplesmente sua cauda, então é por isso que não passamos a pilha pra próxima iteração, e sim sua cauda (representada por &lt;code&gt;stack_tail&lt;/code&gt;, veja o pattern matching nos argumentos da função).&lt;br&gt;
Se não for a correspondência correta, a gente sabe que a string de entrada não era válida, então estou retornando &lt;code&gt;false&lt;/code&gt; aqui.&lt;/p&gt;

&lt;p&gt;Note que a parte do &lt;code&gt;else&lt;/code&gt; não é realmente necessária, pois se não entrássemos na parte do &lt;code&gt;if&lt;/code&gt;, o valor retornado seria &lt;code&gt;nil&lt;/code&gt;, mas vou deixar assim por enquanto. Depois podemos refatorar (:&lt;/p&gt;

&lt;p&gt;Isso parece uma boa "versão alpha" da nossa função &lt;code&gt;iterate&lt;/code&gt;. O que está faltando é verificar no final se a nossa pilha está vazia ou não após a condição de parada.&lt;br&gt;
Poderíamos usar aqui &lt;code&gt;Enum.empty?&lt;/code&gt;, que receberia a pilha e verificaria se está vazia ou não (&lt;code&gt;true&lt;/code&gt; se estiver vazia, &lt;code&gt;false&lt;/code&gt; caso contrário).&lt;br&gt;
Uma outra maneira de fazer isso seria adicionar uma comparação com &lt;code&gt;[]&lt;/code&gt; ou na condição de parada, ou na pipeline da nossa função &lt;code&gt;check&lt;/code&gt;. Vou fazer a segunda opção primeiro pra poder falar rapidinho do módulo &lt;code&gt;Kernel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O módulo &lt;code&gt;Kernel&lt;/code&gt; tem todas as funções "nativas", que podemos chamar sem escrever um módulo. Ou seja, se você quiser somar dois inteiros, podes fazer dos dois jeitos:&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="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;span class="no"&gt;Kernel&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="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A comparação &lt;code&gt;==&lt;/code&gt; também faz parte do módulo &lt;code&gt;Kernel&lt;/code&gt;, então podemos fazer 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;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;Kernel&lt;/span&gt;&lt;span class="o"&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;p&gt;Isso vai pegar o que quer que seja que tenha retornado de &lt;code&gt;iterate&lt;/code&gt; e passar como primeiro argumento de &lt;code&gt;Kernel.==&lt;/code&gt;. O segundo argumento é &lt;code&gt;[]&lt;/code&gt;, então vamos retornar a comparação entre o resultado de &lt;code&gt;iterate&lt;/code&gt; com &lt;code&gt;[]&lt;/code&gt;.&lt;br&gt;
Se a entrada for uma expressão inválida, &lt;code&gt;iterate&lt;/code&gt; pode retornar &lt;code&gt;false&lt;/code&gt;, e daí a comparação com &lt;code&gt;[]&lt;/code&gt; também será falsa.&lt;br&gt;
Outra possibilidade é que &lt;code&gt;iterate&lt;/code&gt; vai retornar uma pilha não vazia, ou seja, uma lista com algum elemento. Neste caso, a comparação com &lt;code&gt;[]&lt;/code&gt; também será falsa.&lt;/p&gt;

&lt;p&gt;Isso até resolve o problema, mas pra mim é bastante feio.&lt;/p&gt;

&lt;p&gt;Pra começo de conversa, às vezes &lt;code&gt;iterate&lt;/code&gt; retorna um booleano, mas às vezes retorna uma lista, seja vazia ou não.&lt;br&gt;
Agora que eu já escrevi um pouquinho sobre o módulo &lt;code&gt;Kernel&lt;/code&gt;, acho que podemos não utilizá-lo aqui (:&lt;br&gt;
Pra evitá-lo, podemos simplesmente colocar a comparação na nossa condição de parada:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;stack&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;stack&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outro jeito é de usar o pattern matching no segundo argumento, 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="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se o primeiro argumento for uma lista vazia e o segundo, também, retornamos &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
Se o primeiro argumento for uma lista vazia e o segundo for qualquer coisa, retornamos &lt;code&gt;false&lt;/code&gt;.&lt;br&gt;
&lt;em&gt;O underline(_) em &lt;code&gt;_stack&lt;/code&gt; denota que que essa variável não será usada. Poderíamos escrever simplesmente &lt;code&gt;_&lt;/code&gt;, sem a palavra "stack" junto, mas acho que quando não é óbvio o que pode ser esse segundo parâmetro, é uma boa ideia dar um nome melhor para a variável, em nome da legibilidade.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Okay, então isso aparentemente funciona, certo?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Se tentarmos rodar nosso código agora, de vez em quanto tomaremos um erro!&lt;br&gt;
Pra testá-lo, podemos usar nosso módulo dentro do iex. Pra fazer isso, salve o código em um arquivo, por exemplo, &lt;code&gt;parens.ex&lt;/code&gt;. Agora, execute &lt;code&gt;iex parens.ex&lt;/code&gt;. Conseguimos agora usar o módulo &lt;code&gt;Parens&lt;/code&gt;, que criamos, dentro do iex!&lt;br&gt;
Se tentarmos verificar uma string onde um fechamento foi encontrado num momento em que não há nenhuma abertura na nossa pilha, estaríamos tentando pegar a cabeça de uma &lt;em&gt;lista vazia&lt;/em&gt;, o que levanta um erro para nós. Podes verificar com esses 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="no"&gt;Parens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#&amp;gt; Levanta um erro!&lt;/span&gt;

&lt;span class="no"&gt;Parens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"(a}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Podemos arrumar isso se verificarmos se a pilha está vazia antes de tentarmos pegar a cabeça.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ou...&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Poderíamos simplesmente declarar uma função fazendo pattern matching no segundo argumento para uma lista vazia quando o elemento a ser analisado é um fechamento, assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight viml"&gt;&lt;code&gt;defp iterate&lt;span class="p"&gt;([&lt;/span&gt;head &lt;span class="p"&gt;|&lt;/span&gt; _&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt; when head &lt;span class="k"&gt;in&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="s2"&gt;"]"&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; false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A guarda vai garantir que o elemento em questão é um fechamento, e quando a pilha está vazia, retornamos direto &lt;code&gt;false&lt;/code&gt; antes de tentar pegar a cabeça de uma lista vazia (que jogaria um erro em nós).&lt;/p&gt;

&lt;p&gt;A primeira versão da nossa solução, portanto, poderia ser isso:&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;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"]"&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="no"&gt;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"]"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"["&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;")"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;&lt;strong&gt;Show!&lt;/strong&gt; Então agora nosso código realmente funciona!&lt;br&gt;
Mas ele não me passa uma vibe muito boa...&lt;/p&gt;
&lt;h2&gt;
  
  
  Refatoração!
&lt;/h2&gt;

&lt;p&gt;Primeiro, estamos usando listas como &lt;code&gt;["{", "[", "("]&lt;/code&gt;, &lt;code&gt;["{", "[", "("]&lt;/code&gt; e &lt;code&gt;["{", "[", "(", "}", "]", ")"]&lt;/code&gt; algumas vezes, que poderiam ser extraídas para &lt;strong&gt;atributos de módulo&lt;/strong&gt;.&lt;br&gt;
Um atributo de módulo é um valor que pode ser usado por qualquer método dentro de um módulo. Pra definí-los, podemos escrever algo como &lt;code&gt;@nome_do_atributo&lt;/code&gt; logo em seguida o seu valor.&lt;br&gt;
No nosso caso, podemos fazer algo 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;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@opener&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="s2"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;@closer&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="s2"&gt;"]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com essa pequena adição, podemos reescrever nossas guardas e nosso filtro, desta maneira:&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="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"]"&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="no"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é legal, mas ainda temos 3 grandes funções que são basicamente a mesma coisa, que são as que decidem o que fazer quando o elemento checado é um fechamento.&lt;/p&gt;

&lt;p&gt;Vou escrever aqui a maneira como podemos melhorá-las, usando apenas um outro atributo de módulo e uma única função, e vou explicar depois o que ela faz:&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;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@pairs&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="s2"&gt;"}"&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="s2"&gt;"]"&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="s2"&gt;")"&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;Primeiro, eu criei o atributo &lt;code&gt;@pairs&lt;/code&gt;, que é um &lt;strong&gt;mapa&lt;/strong&gt;. Cada chave desse mapa é um caracter de abertura que é mapeado para o seu caracter de fechamento correspondente (mapas são como hashes e dicionários, se você está vindo do Ruby ou Python).&lt;br&gt;
Então, eu fiz uma outra definição para &lt;code&gt;iterate/2&lt;/code&gt; que tem uma guarda. Essa guarda vai nos assegurar que a variável &lt;code&gt;head&lt;/code&gt; (elemento a ser verificado) é um caracter de fechamento (então é ou &lt;code&gt;)&lt;/code&gt;, ou &lt;code&gt;]&lt;/code&gt;, ou &lt;code&gt;}&lt;/code&gt;).&lt;br&gt;
Eu também usei uma operação booleana &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; aqui:&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se o lado esquerdo dessa operação for &lt;strong&gt;falsy&lt;/strong&gt;, então este valor é retornado e o lado direito não é executado (o que para a nossa recursão).&lt;br&gt;
Se o lado esquerdo for &lt;strong&gt;truthy&lt;/strong&gt;, então seja lá o que for que está do lado direito é retornado. Nesse caso, o lado direito é uma chamada recursiva da nossa própria função &lt;code&gt;iterate&lt;/code&gt;, continuando o ciclo.&lt;/p&gt;

&lt;p&gt;Agora olhemos para &lt;code&gt;@pairs[stack_head]&lt;/code&gt;. Lembra que &lt;code&gt;@pairs&lt;/code&gt; é um mapa? Ou seja, se tivéssemos, por exemplo, &lt;code&gt;@pairs["{"]&lt;/code&gt;, isso retornaria &lt;code&gt;"}"&lt;/code&gt;.&lt;br&gt;
Se seja lá o que for que estiver na cabeça da nossa pilha for um caracter de abertura, então estamos mapeando-o para o seu respectivo fechador quando consultamos o valor de &lt;code&gt;@pairs[stack_head]&lt;/code&gt;. Se esse fechador for o mesmo que está na variável &lt;code&gt;head&lt;/code&gt;, então essa comparação retorna &lt;code&gt;true&lt;/code&gt;, que fará com que aquela operação booleana retorne o lado direito, isto é, a chamada recursiva da função, passando o resto da lista (&lt;code&gt;tail&lt;/code&gt;) e a versão "popada" da pilha (&lt;code&gt;stack_tail&lt;/code&gt;).&lt;br&gt;
Se o que estiver na cabeça da pilha não for uma abertura, &lt;code&gt;@pairs[stack_head]&lt;/code&gt; vai retornar &lt;code&gt;nil&lt;/code&gt;, e &lt;code&gt;nil == head&lt;/code&gt; vai ser falso, logo, a recursão morre aí.&lt;br&gt;
Também pode acontecer que o que está na cabeça da pilha é uma abertura, mas &lt;code&gt;@pairs[stack_head]&lt;/code&gt; não é igual a &lt;code&gt;head&lt;/code&gt;. Logo, a comparação vai ser falsa também. Esse é o caso em que estamos tentando fechar algo que ainda não foi aberto, e como deu falso naquela comparação, a recursão para por aí.&lt;/p&gt;

&lt;p&gt;Portanto, isso basta para verificar se os caracteres correspondem e parar a recursão caso contrário.&lt;/p&gt;

&lt;p&gt;Então, a nossa segunda versão do programa seria:&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;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@pairs&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="s2"&gt;"}"&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="s2"&gt;"]"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;@opener&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="s2"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;@closer&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="s2"&gt;"]"&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;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;iterate&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;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&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;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;
  
  
  Isso é tudo por hoje
&lt;/h3&gt;

&lt;p&gt;Obrigado por lerem isso. Estou gostando bastante de Elixir! Pattern matching é bastante poderoso e divertido, também.&lt;br&gt;
Por favor, corrijam erros que eu possa ter feito (:&lt;br&gt;
Espero que vocês tenham aprendido algo hoje, e que tenham um bom dia.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>algorithms</category>
      <category>functional</category>
    </item>
    <item>
      <title>Verify matching parens, brackets and braces with Elixir</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Wed, 07 Apr 2021 19:44:56 +0000</pubDate>
      <link>https://dev.to/lucassperez/verify-matching-parens-brackets-and-braces-with-elixir-dh5</link>
      <guid>https://dev.to/lucassperez/verify-matching-parens-brackets-and-braces-with-elixir-dh5</guid>
      <description>&lt;p&gt;🇵🇹 Versão em português desse texto &lt;a href="https://dev.to/lucassperez/verificando-parenteses-colchetes-e-chaves-correspondentes-com-elixir-jn0"&gt;&lt;em&gt;aqui&lt;/em&gt;&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;So I've started to study the Elixir language and decided to solve some coding exercise with it in order to better understand some concepts.&lt;br&gt;
Since I liked my solution, I decided to make a post explaining the thought process behind it. Suggestions to further improve the code or to better follow Elixir's conventions are more than appreciated! (:&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;I want to make a function that receives a string as input, supposedly a mathematical expression or some code snippet, and tells me whether all of it's opening parenthesis/brackets/braces have a correct closing match.&lt;br&gt;
Some expressions as examples:&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="mi"&gt;1&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&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="c1"&gt;# should return true&lt;/span&gt;
&lt;span class="mi"&gt;9&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# should return false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make a plan
&lt;/h2&gt;

&lt;p&gt;Before coding, I think it is a good ideia do solve the problem theoretically, and then try to implement it.&lt;br&gt;
For this exercise, I believe using the &lt;a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)"&gt;stack&lt;/a&gt; idea is a very good approach. Basically, a stack is a set of items that have two operations: &lt;strong&gt;push&lt;/strong&gt; and &lt;strong&gt;pop&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The push operation will put a new item in the set&lt;/li&gt;
&lt;li&gt;The pop operation will remove the last pushed item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the stack follows the "Last In, First Out" dynamic. When I put an item in the stack, this item will be the first one to get out when I start removing them.&lt;/p&gt;

&lt;p&gt;How can we use a stack here? Well, my theoretical solution would be to iterate over all the characters in the input string, and if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is an opening char (parens/brackets/braces), put it in a stack&lt;/li&gt;
&lt;li&gt;It is a closing char, check the last item in the stack: If it matches, we &lt;em&gt;pop&lt;/em&gt; it and continue the recursion. If it doesn't, the input string is not valid&lt;/li&gt;
&lt;li&gt;If it is something else, ignore&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the whole input string is iterated and I never found an error, this means that all closers had a matching opener, but it doesn't necessarily means the string is valid. This input is an example:&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All the closers had a matching opener, but not all the openers were closed. This means that if we survive the iteration, we also have to check if our final stack is &lt;em&gt;empty&lt;/em&gt;. If it is, all openers were closed, and the input was valid. If it is not, the input was not valid.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;

&lt;p&gt;Good, we have a plan, so now we have to translate it into Elixir.&lt;br&gt;
For starters, I'm creating a module &lt;code&gt;Parens&lt;/code&gt; with a function &lt;code&gt;check&lt;/code&gt; that will receive as input a string.&lt;br&gt;
This function &lt;code&gt;check&lt;/code&gt; will have to iterate over the string, so we can use the &lt;code&gt;String&lt;/code&gt; module's &lt;code&gt;split/2&lt;/code&gt; function. So we have our first piece of code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using the pipe operator &lt;code&gt;|&amp;gt;&lt;/code&gt; here, meaning that whatever comes before it, is going to be the first argument of whatever comes after it. In this case, &lt;code&gt;expression&lt;/code&gt; is going to be the first argument of &lt;code&gt;String.split&lt;/code&gt;.&lt;br&gt;
The second argument is an empty string so we can split the expression at every character. The result of this is a list, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="s2"&gt;"a + b * (c / d)"&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;split&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="c1"&gt;# ["", "a", " ", "+", " ", "b", " ", "*", " ", "(", "c", " ", "/", " ", "d", ")", ""]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On our theoretical solution, every character but openers/closers were to be ignored, so we can apply a &lt;strong&gt;filter&lt;/strong&gt; in this resulting list. To do that, we can use &lt;code&gt;Enum.filter/2&lt;/code&gt;, which receives two arguments.&lt;br&gt;
The first one is something that "is enumerable", which means that this something must implement the Enum protocol.&lt;br&gt;
Luckly, lists do that, so we can pass our resulting list as the first argument to our filter.&lt;br&gt;
The second argument is a &lt;em&gt;function&lt;/em&gt; that receives an element of our list and then decide if it should or shouldn't be in the filtered result. More precisely, if this &lt;em&gt;function&lt;/em&gt; returns a falsy value (&lt;code&gt;false&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt;), then the element will not be in the resulting filtered list. If it returns a truthy value (anything else), it is going to be in the filtered result.&lt;br&gt;
In our case, this function will verify if each element of our list is a parens/brackets/braces and keep it if it is, removing it otherwise. One way to do that is like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&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;p&gt;This anonymous function will receive something (&lt;em&gt;x&lt;/em&gt;) and see if it belongs to that list, which happens to be a list with only our parens/brackets/braces.&lt;br&gt;
We could also use the capture notation, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="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;The capture notation is similar, but instead of declaring &lt;em&gt;x&lt;/em&gt;, we just use &amp;amp;1, &amp;amp;2, &amp;amp;3... for all of our arguments.&lt;/p&gt;

&lt;p&gt;Good, so our code right now looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="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;The next step is to iterate over our resulting list and use our "stack strategy". To do that, I decided to create a &lt;strong&gt;private function&lt;/strong&gt; called &lt;code&gt;iterate&lt;/code&gt;, where I'll recursively walk over our elements, passing the stack around, until we checked all of our elements. Since I'll need the stack, this function will have an arity of 2, which means it will have 2 arguments.&lt;br&gt;
The first thing I do when I'm thinking about recursion it to write the stop condition. In this case, it should stop once our list of characters is empty. I'll make use of the wonderful &lt;strong&gt;pattern matching&lt;/strong&gt; functionality to do that:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;stack&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;stack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that this function will only execute when the first element is an empty list and the second element is whatever it arrives here.&lt;br&gt;
In this case, this function will do nothing and just return the stack, so we can later verify if it is empty or not.&lt;/p&gt;

&lt;p&gt;A very important thing to note here is that we also have to pass a &lt;code&gt;stack&lt;/code&gt; when we first call the iterate function. Our stack will start empty, so our pipeline will be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
  &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;&lt;em&gt;Note: We could also use a default value, but I'll keep it like this.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now the hard part. After writing a stop condition to our recursion, we have to write the recursive step (or steps).&lt;/p&gt;

&lt;p&gt;Let's check our plan again. We have to look at each element, and if it is an opener, we put it in the stack and go on. Let's do this part first.&lt;/p&gt;

&lt;p&gt;I love pattern matching, so I'll be using it here again. And to further help us, I'll also use &lt;strong&gt;guards&lt;/strong&gt; to decide if the function will be executed or not:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will only be executed if the variable &lt;code&gt;head&lt;/code&gt; belongs to that list of openers. But where is this variable coming from?&lt;br&gt;
We are pattern matching the first argument with &lt;code&gt;[head | tail]&lt;/code&gt;, so this function will need for the first argument to be a list with a first element. This first element will be bound to &lt;code&gt;head&lt;/code&gt;. The rest of the list will be bound to &lt;code&gt;tail&lt;/code&gt;. If you are in doubt, open the interactive elixir shell in your terminal (write iex and press enter) and try this code:&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="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&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="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="n"&gt;head&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 1&lt;/span&gt;
&lt;span class="n"&gt;tail&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [2,3,4]&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head2&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail2&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;head2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 0&lt;/span&gt;
&lt;span class="n"&gt;tail2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; []&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head3&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail3&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="c1"&gt;# Will raise a matching error!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The head and tail are important concepts. The head is the first element of a list, and the tail &lt;strong&gt;is the list itself&lt;/strong&gt;, but &lt;strong&gt;without the first element&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;Okay, back to our function. What will it do if the character is an opener? It should push it to the stack and continue iterating. We can do that simply by calling &lt;code&gt;iterate&lt;/code&gt; again with the right arguments.&lt;br&gt;
Since we already checked the first element, we can pass the list without the first element. That is precisely what &lt;code&gt;tail&lt;/code&gt; is! Good, but how can we &lt;strong&gt;push&lt;/strong&gt; the element to the stack?&lt;br&gt;
Elixir offers a good way to put an item in a list, and it is simply like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;new_element&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a list which its head is &lt;code&gt;new_element&lt;/code&gt;, and its tail is the &lt;code&gt;stack&lt;/code&gt;. You can always go to iex and make some experiments:&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; [1,9,8,7]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our function looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it is an opener, we simply call iterate with &lt;code&gt;tail&lt;/code&gt; and pass the stack with a newly pushed &lt;code&gt;head&lt;/code&gt; item.&lt;/p&gt;

&lt;p&gt;Good! Now that we have this part done, let's check the plan again.&lt;/p&gt;

&lt;p&gt;We already know how to stop the recursion;&lt;br&gt;
We already took care of the "ignore if not opener/closer" issue;&lt;br&gt;
We already know how to push an opener to the stack and continue;&lt;/p&gt;

&lt;p&gt;We now have to do something when the element is a "closer". When that happens, the idea was to look at the last added item of our stack, which happens to be the head of &lt;code&gt;stack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This part of the code was heavily refactored, but I'll tell how I did it first time. For each possible closer, which are &lt;code&gt;}&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt; and &lt;code&gt;)&lt;/code&gt;, I made its single pattern matched function:&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"]"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;")"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for each one of those, I made a simple if/else statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;false&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;First of all, I used the functions &lt;code&gt;hd&lt;/code&gt; and &lt;code&gt;tl&lt;/code&gt;, which returns the &lt;strong&gt;head&lt;/strong&gt; and the &lt;strong&gt;tail&lt;/strong&gt; of a list, respectively. It would be the same as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;if&lt;/span&gt; &lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="no"&gt;false&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;Then, since this function will only execute if the element is exactly &lt;code&gt;}&lt;/code&gt;, I'm verifying if the last added item in the stack (its head) is &lt;code&gt;{&lt;/code&gt;, which would be a match.&lt;br&gt;
If it is, we have to pop it. The "popped" version of the stack is simply its tail, so that's why we don't pass the stack to the next iteration, but rather the &lt;code&gt;stack_tail&lt;/code&gt;.&lt;br&gt;
If it doesn't match, we know that the input string is not valid, so I'm returning a &lt;code&gt;false&lt;/code&gt; here.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;else&lt;/code&gt; part is not really needed, because in order to go inside it, the comparison should be &lt;strong&gt;falsy&lt;/strong&gt;. When that happens, an &lt;code&gt;if&lt;/code&gt; statement alone would return &lt;code&gt;nil&lt;/code&gt;, but I'll keep it with this &lt;code&gt;else&lt;/code&gt; for now. We can refactor later.&lt;/p&gt;

&lt;p&gt;This looks like a valid "alpha version" of our &lt;code&gt;iterate&lt;/code&gt; function. What is missing is verifying if the stack is empty or not after the stop condition. A way to do that is to add a comparison with &lt;code&gt;[]&lt;/code&gt; in the stop condition or in the pipeline  of our &lt;code&gt;check&lt;/code&gt; function. &lt;code&gt;Enum.empty?&lt;/code&gt; would also work, as it does exactly what its name suggests. I'll show the "comparison with &lt;code&gt;[]&lt;/code&gt;" first because I can talk briefly about the &lt;code&gt;Kernel&lt;/code&gt; module.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Kernel&lt;/code&gt; module has all the functions we can use "natively", without calling a module. So if you want so sum two integers, you can do both:&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="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;span class="no"&gt;Kernel&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="c1"&gt;#=&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;==&lt;/code&gt; comparison is also part of the &lt;code&gt;Kernel&lt;/code&gt; module, so we can do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;Kernel&lt;/span&gt;&lt;span class="o"&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;p&gt;This will take whatever returns from the &lt;code&gt;iterate&lt;/code&gt; call and use it as the first argument of &lt;code&gt;Kernel.==&lt;/code&gt;. The second argument is &lt;code&gt;[]&lt;/code&gt;, so we are going to return the comparison of the result of &lt;code&gt;iterate&lt;/code&gt; with &lt;code&gt;[]&lt;/code&gt;.&lt;br&gt;
If the input is invalid, the &lt;code&gt;iterate&lt;/code&gt; may return &lt;code&gt;false&lt;/code&gt;, and then the comparison with &lt;code&gt;[]&lt;/code&gt; will also be false.&lt;br&gt;
Another possibility is that the &lt;code&gt;iterate&lt;/code&gt; will return a not empty stack. Then, the comparison with &lt;code&gt;[]&lt;/code&gt; will be false as well.&lt;br&gt;
This actually solves it, but for me it is really ugly.&lt;/p&gt;

&lt;p&gt;For starters, sometimes &lt;code&gt;iterate&lt;/code&gt; returns a boolean, and sometimes it returns a list, which could be empty or not.&lt;br&gt;
Now that I wrote about &lt;code&gt;Kernel&lt;/code&gt; a little bit, I think we should not use it in this case (:&lt;br&gt;
To avoid it, we can put this comparison in our stop condition, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;stack&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;stack&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another way is to pattern match the second argument as well!&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the first argument is an empty list and the second argument is also an empty list, we return &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
If the first argument is an empty list and the second argument is anything (the _ denotes that this variable will not be used), we return false.&lt;br&gt;
&lt;em&gt;Note: We could simply use _ instead of _stack, but I think it is nice to put some name to it in the name of readability, since it is not obvious what the second argument could be&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Okay, so this apparently works, right?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If we try to run our code now, we are going to sometimes get an error!&lt;br&gt;
To test it, we can use our module inside iex. To do that, save the code in a file, for example, &lt;code&gt;parens.ex&lt;/code&gt;. Now, run &lt;code&gt;iex parens.ex&lt;/code&gt;. You'll be able to use the &lt;code&gt;Parens&lt;/code&gt; module we just created inside iex!&lt;br&gt;
If you try to check a string where a closer would be found before any opener, the code would try to get the head of an empty stack, which raises an error. You can verify it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Parens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"a}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#&amp;gt; Raises error!&lt;/span&gt;

&lt;span class="no"&gt;Parens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"(a}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can fix this by checking if the stack is empty before trying to get its head.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Or...&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;We could simply pattern match the second argument to empty list when we have a closer, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"]"&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="no"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The guard will ensure that &lt;code&gt;head&lt;/code&gt; is a closer, and when the stack is an empty list, we just return &lt;code&gt;false&lt;/code&gt; before trying to get the head of an empty list (which raises an error).&lt;/p&gt;

&lt;p&gt;The first version of our solution could then be this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Parens&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;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;iterate&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;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"]"&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="no"&gt;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"{"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;"]"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"["&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s2"&gt;")"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;if&lt;/span&gt; &lt;span class="n"&gt;hd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
     &lt;span class="no"&gt;false&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;&lt;strong&gt;Nice!&lt;/strong&gt; So now our code actually works!&lt;br&gt;
But it doesn't really give me good vibes...&lt;/p&gt;
&lt;h2&gt;
  
  
  Refactor!
&lt;/h2&gt;

&lt;p&gt;First, we are using lists like &lt;code&gt;["{", "[", "("]&lt;/code&gt;, &lt;code&gt;["{", "[", "("]&lt;/code&gt; and &lt;code&gt;["{", "[", "(", "}", "]", ")"]&lt;/code&gt;, which could be extracted to &lt;strong&gt;module attributes&lt;/strong&gt;.&lt;br&gt;
Module attributes are values that can be used by any method in a module. To define them, we can write &lt;code&gt;@attribute_name&lt;/code&gt; and then its value. We can do it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@opener&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="s2"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;@closer&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="s2"&gt;"]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a nice little addition, so now we can rewrite our guards and filter like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&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="s2"&gt;"["&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="s2"&gt;"}"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"["&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;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&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="s2"&gt;"]"&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="no"&gt;false&lt;/span&gt;
&lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we still have 3 big functions that are basically the same, which are the ones that decide what to do when the element we are checking is a closer character.&lt;br&gt;
I'll write what I did and then explain it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight elixir"&gt;&lt;code&gt;&lt;span class="k"&gt;defmodule&lt;/span&gt; &lt;span class="no"&gt;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@pairs&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="s2"&gt;"}"&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="s2"&gt;"]"&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="s2"&gt;")"&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;So first, I created a &lt;code&gt;@pairs&lt;/code&gt; module attribute which is a &lt;strong&gt;map&lt;/strong&gt;. Each key of the map is an opener character and it maps to a closer character (maps are like hashes and dictionaries, if you are coming from ruby or python).&lt;br&gt;
Then, I made an &lt;code&gt;iterate/2&lt;/code&gt; function that has a guard. This guard will ensure that &lt;code&gt;head&lt;/code&gt; variable (the first element of our list) is a closer (so it is one of &lt;code&gt;)&lt;/code&gt;, &lt;code&gt;]&lt;/code&gt; or &lt;code&gt;}&lt;/code&gt;).&lt;br&gt;
I also used a &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; boolean operation here:&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the left side is a &lt;strong&gt;falsy&lt;/strong&gt; value, then this value is returned and the right side is not executed (which stops our recursion).&lt;br&gt;
If the left side is &lt;strong&gt;truthy&lt;/strong&gt;, then whatever is at the right side is returned. In this case, the right side is a function call, continuing the recursion.&lt;/p&gt;

&lt;p&gt;Now I'll look at &lt;code&gt;@pairs[stack_head]&lt;/code&gt;. Remember that &lt;code&gt;@pairs&lt;/code&gt; is a map, so &lt;code&gt;@pairs["{"]&lt;/code&gt;, for example, returns &lt;code&gt;"}"&lt;/code&gt;.&lt;br&gt;
If whatever is the head of our stack is an opener, then it maps to some closer (&lt;code&gt;@pairs[stack_head]&lt;/code&gt;, then, is some closer). If this closer equals to &lt;code&gt;head&lt;/code&gt; (the element we are checking itself), then the comparison returns &lt;code&gt;true&lt;/code&gt;, which will then return the right side of the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, continuing our recursion!&lt;br&gt;
If not, then the comparison will return &lt;code&gt;false&lt;/code&gt;, and not execute the right side of the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;.&lt;br&gt;
So this is enough to check if the parens are matching and stop the recursion otherwise.&lt;/p&gt;

&lt;p&gt;So our second version of the program is:&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;Parens&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="nv"&gt;@pairs&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="s2"&gt;"}"&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="s2"&gt;"]"&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="s2"&gt;")"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nv"&gt;@opener&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="s2"&gt;"["&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"("&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nv"&gt;@closer&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="s2"&gt;"]"&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;def&lt;/span&gt; &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expression&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;expression&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;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;|&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Enum&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filter&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="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nv"&gt;&amp;amp;1&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;iterate&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;iterate&lt;/span&gt;&lt;span class="p"&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="no"&gt;true&lt;/span&gt;
  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([],&lt;/span&gt; &lt;span class="n"&gt;_stack&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;stack&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@opener&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;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack&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;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;],&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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;false&lt;/span&gt;

  &lt;span class="k"&gt;defp&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;head&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;@closer&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="nv"&gt;@pairs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack_head&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;iterate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tail&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stack_tail&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;
  
  
  That's it for today
&lt;/h3&gt;

&lt;p&gt;Thanks for reading this. I'm enjoying Elixir very much. Pattern matching is quite powerful and fun.&lt;br&gt;
Please correct any mistakes I might have made (:&lt;br&gt;
I hope you learned something today, and have a good day.&lt;/p&gt;

</description>
      <category>elixir</category>
      <category>algorithms</category>
      <category>functional</category>
    </item>
    <item>
      <title>Write Your Own Snippets in VSCode</title>
      <dc:creator>Lucas Perez</dc:creator>
      <pubDate>Mon, 11 Jan 2021 02:49:02 +0000</pubDate>
      <link>https://dev.to/lucassperez/write-your-own-snippets-in-vscode-3b7b</link>
      <guid>https://dev.to/lucassperez/write-your-own-snippets-in-vscode-3b7b</guid>
      <description>&lt;p&gt;Everyone has its own way of learning things. What I know about myself is that little shortcuts often get in the way at the beginning. One example are snippets and VSCode extensions that add those snippets.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Snippets?
&lt;/h2&gt;

&lt;p&gt;Snippets are just a piece of text (or code, in our case), a little extract from something bigger. They are very helpful to avoid repetition. If you constantly have to write a piece of code, you surely thought about copying and pasting a big chunk of boilerplate code (I know I have). Well, those are basically snippets.&lt;br&gt;
Now, wouldn't it be great if we could automate the process of pasting those chunks of code? Like this:&lt;br&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%2Fi%2Fsp4x7x14ith5zy0uglz4.gif" 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%2Fi%2Fsp4x7x14ith5zy0uglz4.gif" alt="Nice snippet example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here I just typed some kind of shortcut and pressed tab, pretty much like auto completion, but for something bigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  No Need For VSCode Extensions!
&lt;/h2&gt;

&lt;p&gt;I recently started studying &lt;em&gt;React&lt;/em&gt; and decided that to be productive I should add some kind of extension full of snippets, just like in the videos I was watching.&lt;/p&gt;

&lt;p&gt;The problem is that now my coding environment got full of autocomplete suggestions that would just return a bunch of text. Many shortcuts that I did not know about would sometimes randomly make me pop huge code extracts when I was trying to write something completely unrelated. Snippets that I didn't know their uses. And then I realized that I was overwhelmed with many useful shortcuts that were not meaningful for me at the moment. I did now know why a particular Snippet existed in the first place.&lt;br&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%2Fi%2Fe96fdxhk2qb50bix46x2.gif" 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%2Fi%2Fe96fdxhk2qb50bix46x2.gif" alt="Too many snippets!"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;List of all the snippets of a particular extension&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If I don't know why a shortcut is useful, it is not useful for me and I shouldn't use it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sometimes I think of it like a game. I have to code a certain amount to unlock a particular snippet. I can only use it when I got tired of writing it by hand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create Your Own Snippets
&lt;/h2&gt;

&lt;p&gt;VSCode already has by default some snippets, and that is really nice.&lt;br&gt;
But, you can create your own custom Snippets, and it is actually &lt;strong&gt;pretty easy&lt;/strong&gt;!&lt;br&gt;
This has the immediate benefit of only populating your environment with snippets that you know that exist, you know what is it's purpose and how to use them.&lt;br&gt;
Also, it ensures that you really learn the hard way before actually gifting yourself an easy alternative, meaning that you can code anywhere, and not just in your particular computer.&lt;br&gt;
Finally, you can customize them according to specific needs if necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, How Do We Do It?
&lt;/h2&gt;

&lt;p&gt;Start your VSCode and open the Command Palette (&lt;code&gt;CTRL&lt;/code&gt; + &lt;code&gt;SHIFT&lt;/code&gt; + &lt;code&gt;P&lt;/code&gt; by default) and write &lt;code&gt;snippet&lt;/code&gt; to see the options that appears:&lt;br&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%2Fi%2Fehz7y6m41i2wg700el3j.gif" 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%2Fi%2Fehz7y6m41i2wg700el3j.gif" alt="Search command palette"&gt;&lt;/a&gt;&lt;br&gt;
Alternatively, you could go to &lt;strong&gt;File &amp;gt; Preferences &amp;gt; User Snippets&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can now create a &lt;code&gt;.json&lt;/code&gt; file full of snippets.&lt;br&gt;
You can either create a &lt;em&gt;language specific&lt;/em&gt; file, for example:&lt;br&gt;
&lt;code&gt;javascript.json&lt;/code&gt;&lt;br&gt;
Snippets defined here will only apply on a javascript document.&lt;br&gt;
Or you can define a &lt;em&gt;global&lt;/em&gt; snippet file. The global ones should end with the &lt;code&gt;.code-snippets&lt;/code&gt; extension, for example:&lt;br&gt;
&lt;code&gt;my-global-snippets.json.code-snippets&lt;/code&gt;.&lt;br&gt;
Since I am learning react, I created a file named&lt;br&gt;
&lt;code&gt;javascriptreact.json&lt;/code&gt;&lt;br&gt;
Snippets here will be available in all &lt;code&gt;.jsx&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing the Snippet
&lt;/h2&gt;

&lt;p&gt;To write the snippet you have to give it a name and associate it with an "object" (it is a JSON, after all), like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Snippet Name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keys&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;values&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;here&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;The more important keys are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;prefix&lt;/code&gt;: The shortcut that will invoke it (could have many)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt;: The code created when invoked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scope&lt;/code&gt;: If you created a global snippets file, you can pass languages here, so that it will only be available for those languages. You can ignore this if you created a language specific file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;description&lt;/code&gt;: You can pass some text that will show up on autocomplete with information about the snippet here. If no description is passed, it will use the snippet's name.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is an example that I'm using:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"React Function Component Export"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"body"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"import React from 'react';"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"function ${0:$TM_FILENAME_BASE} () {"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;return ("&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t\t&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t\t&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;/div&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s2"&gt;);"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"export default ${0:$TM_FILENAME_BASE};"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;


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

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Note that &lt;code&gt;\t&lt;/code&gt; is a single tabulation. Also, &lt;code&gt;\n&lt;/code&gt; would have worked for new lines and so on&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The prefix here is set to &lt;code&gt;fc&lt;/code&gt;, so every time I'm inside a &lt;code&gt;.jsx&lt;/code&gt; file, writing &lt;em&gt;"fc"&lt;/em&gt; and hitting &lt;code&gt;TAB&lt;/code&gt; will generate this code. Now that's useful!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;It is also worth noting that &lt;code&gt;CTRL&lt;/code&gt; + &lt;code&gt;SPACE&lt;/code&gt; will also show the "suggestions" of a particular word, including the snippets&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You could also pass many prefixes, like this:&lt;br&gt;
&lt;code&gt;"prefix": ["fc", "rfc", "funcomp", "hello"]&lt;/code&gt;&lt;br&gt;
Also, the body supports many special characters. In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;$0&lt;/code&gt;: This is a "tab-stop" and will put the cursor in this position when the snippet is invoked. Passing repeated tab-stops will give you multiple cursors right from start! You could also have more than one tab-stop without using multi-cursors, just use different indexes for them: &lt;code&gt;$0&lt;/code&gt;, &lt;code&gt;$1&lt;/code&gt; etc. It is possible to cicle through those different indexed tab-stops after the snippet was invoked with the &lt;code&gt;TAB&lt;/code&gt; key&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;${0:text}&lt;/code&gt;: This is a tab-stop that has a initial value of "text"&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$TM_FILE_NAME_BASE&lt;/code&gt;: This is a variable that will have the name of the file where the snippet was invoked but without it's extension. There are multiple available variables that you can use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can look for all the available variables and everything else about writing our own snippets at the documentations:&lt;br&gt;
&lt;a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/editor/userdefinedsnippets&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Specific Snippets
&lt;/h2&gt;

&lt;p&gt;Upon creation, you could also specify a snippet to a project, so that it will not be available anywhere else.&lt;br&gt;
Imagine that for a specific project you have to write some particular text/code very often. Maybe some import, or have some kind of class template, who knows.&lt;br&gt;
In those cases it is probably a good ideia to create a &lt;em&gt;project specific&lt;/em&gt; snippet.&lt;/p&gt;

&lt;p&gt;To do that, you can either open the Command Pallet, search for snippets and choose the &lt;strong&gt;New snippet file for &lt;em&gt;[PROJECT NAME]&lt;/em&gt;&lt;/strong&gt; option. It will create a &lt;code&gt;/.vscode&lt;/code&gt; folder at the root of the project's directory and put the json there.&lt;br&gt;
You can now determine the:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scope (languages)&lt;/li&gt;
&lt;li&gt;prefix (shortcut to invoke) and&lt;/li&gt;
&lt;li&gt;body (actual code)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;of all the necessary snippets in that file.&lt;/p&gt;

&lt;h2&gt;
  
  
  VSCode Extensions, again...
&lt;/h2&gt;

&lt;p&gt;Now, don't get me wrong. I know that people work hard and put a lot of love and effort in creating extensions that come with a number of very nice snippets, and I'm not against this. I'm just saying that, specifically when learning a new technology, it is probably a bad idea. You can use one of those extensions to fill the more generic and everyday snippets and customize just a few particular ones, if you want.&lt;/p&gt;

&lt;p&gt;And finally...&lt;/p&gt;

&lt;h2&gt;
  
  
  Have fun!
&lt;/h2&gt;

&lt;p&gt;Customizing your workspace is fun and helps not only at being productive but also at learning better how things work. I hope I helped someone out there with customizing it's own snippets, because that is something that I'm finding particularly useful.&lt;br&gt;
Thanks for reading, and don't forget to check the docs!&lt;br&gt;
&lt;a href="https://code.visualstudio.com/docs/editor/userdefinedsnippets" rel="noopener noreferrer"&gt;https://code.visualstudio.com/docs/editor/userdefinedsnippets&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stay safe 😊&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
