Use canos (pipes) sempre que possível em Elixir!

Oi, pessoal!

Recentemente fiz um vídeo sobre Pipes em Elixir. Como sei que nem todos gostam de ver vídeos (eu estou entre estas pessoas), vou escrever um pouco sobre o que falei lá.

Em primeiro lugar, preciso falar da Falácia do Espantalho. Um site muito bom sobre falácias lógicas é https://yourlogicalfallacyis.com/. Lá você encontra um texto sobre a falácia do espantalho que diz:

Por que eu disse isso? Porque quando você entra na página da Elixir School (que eu adoro) sobre o Operador Pipe está escrito "chamadas em funções podem ficar tão incorporadas a outras chamadas de função, tornando-se muito difícil de seguir" e aí eles dão o seguinte exemplo:

foo(bar(baz(new_function(other_function()))))

Bem, mesmo sem pipe dá pra deixar o código acima bem mais legível. Como? Assim:

valor = other_function()
nome_significativo_1 = new_function(valor)
nome_significativo_2 = baz(nome_significativo_1)
nome_significativo_3 = bar(nome_significativo_2)
foo(nome_significativo_3)

Ou seja, o código acima talvez fique, dependendo da escolha dos "nomes significativos" das variáveis, até mais legível do que o exemplo com pipe utilizado na Elixir School:

other_function() |> new_function() |> baz() |> bar() |> foo()

Ou seja, eu acho que o pessoal da Elixir School usou um pouco da falácia do espantalho para justificar o pipe.

Eu já sou meio chato em usar os pipes tudo numa mesma linha. OK, sei que no iex não tem muita escolha exceto fazer isto (colocar o pipe no fim da linha e pular para a próxima linha):

iex> "Elixir rocks" |> 
String.upcase() |> 
String.split()

Mas não vou escrever sobre o que não gosto e sim sobre o que gosto.
A tradução literal de pipe é cano e usando o operador pipe.

Na figura abaixo você pode ver como os dados fluem de uma função a outra através dos canos (pipes).

Neste exemplo eu mostrei como você pode usar IO.inspect para ver o que acontece após cada ação do pipe.

Enum.take(1..100, 10)
|> IO.inspect(label: "inicial")
|> Enum.map(fn x -> x * 2 end)
|> IO.inspect(label: "Após map")
|> Enum.filter(fn x -> x > 4 end)
|> IO.inspect(label: "Após filter")
|> Enum.sum()
|> IO.inspect(label: "Após sum")

Portanto, minha sugestão é: use o pipe sempre que possível em Elixir. Na minha opinião (é somente uma opinião, claro), o pipe deixa o código mais legível!

Cover Photo by Kyle Glenn on Unsplash.

26