Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
August 23, 2021 09:54 pm GMT

Mas e os loops em Elixir?

Se voc est vindo de uma linguagem de paradigma imperativo, orientada a objetos, muito provavelmente voc vai esbarrar nessa pergunta do ttulo.

Pois bem, Elixir no possui esse termo em seu vocabulrio. Apesar de ser possvel iterar sobre uma lista de elementos utilizando o for:

iex> for n <- [1, 2, 3, 4], do: n * n[1, 4, 9, 16]

Isso no significa que o Elixir possui loops, esse for nada mais do que uma chamada nativa ao List Comprehensions do Erlang.

Curioso n? Como fazer para lidar com uma coleo de itens ento?

H 2 maneiras de trabalhar com este tipo de problema, sendo elas:

  1. High Order Functions (map, reduce, filter, find, etc...)
  2. Recursividade

High Order Functions

muito comum se deparar com uma situao onde voc tem uma lista de elementos e precisa manipular os dados dela.

E para isso podemos utilizar funes como map, reduce, filter, etc.

Digamos que voc precise multiplicar todos os elementos da sua lista por 2, isso deveria ser um problema trivial, certo?

A implementao desse problema em js utilizando uma estrutura de repetio (loop) seria mais ou menos assim:

const list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];for (let i = 0; i < list.length; i++) {  list[i] = list[i] * 2;}> list> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Em Elixir possvel resolver isso com map/2:

iex> list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]iex> sum = fn x -> x * 2 endiex> Enum.map(list, sum)[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Comparando os exemplos acima, diferente da estrutura de repetio, com o map/2 no necessrio definir nada alm da frmula para mapear os dados da minha lista, onde a frmula x -> x * 2.

O prprio map/2 faz o resto do trabalho aplicando a frmula pra cada elemento da nossa lista, e gerando uma nova lista ao final da execuo.

Segue o mesmo conceito para as demais funes, como:

  • map/2 manipula os elementos e gera uma nova lista
  • filter/2 filtra os elementos e gera uma nova lista
  • reduce/2 manipula os elementos acumulando seus resultados anteriores

Existem diversos tipos de High Order Functions disponveis no Elixir, feitas para facilitar a sua vida na hora de resolver problemas sejam eles triviais ou no.

Recursividade

Mesmo que voc seja uma pessoa de linguagens imperativas, o termo recursividade ainda algo familiar!

E o que recursividade? uma forma de iterar sob listas (ou no), onde a funo chama ela prpria at atingir uma condio de parada.

Um exemplo muito conhecido sobre recursividade, o clculo fatorial de um nmero, onde 4! = 4 x 3 x 2 x 1 = 24

Destrinchando esse clculo, teramos algo semelhante a:

4! = 3! * 4   = 2! * 3   = 1! * 2   = 1

Considerando o exemplo acima, a condio de parada para essa execuo o valor 1. Quando a funo fatorial receber como argumento o valor 1, ela dever retornar 1 e as outras execues devem se basear neste valor, exemplo:

4! = (6) * 4 = 24   = (2) * 3   = (1) * 2   = 1

Em parnteses: resultado da chamada fatorial anterior.

A implementao em JS:

fact = (val) => {  if (val == 1) return 1;  return fact(val - 1) * val;};

Essa mesma funo em Elixir fica assim:

def fact(1), do: 1def fact(a), do: fact(a - 1) * a

Nota-se que na chamada recursiva, a funo fact/1 chama a si mesma passando o argumento - 1, e quando essa funo chamada com o valor 1, ela retorna somente o valor 1 e encerra sua execuo em cadeia.

Vamos analisar mais de perto essa chamada do fact/1:

# Considere que estamos chamando fatorial com o argumento 4 (4!)fact(4) -> fact(4 - 1) * 4 # Esse ser o retorno# Ele estar chamando fact(3) e multiplicando por 4.# E assim sucessivamente...fact(3) -> fact(3 - 1) * 3fact(2) -> fact(2 - 1) * 2fact(1) -> 1# Essa abordagem gera uma cadeia de chamadas que precisam ser resolvidas.# Quando a chamada em cadeia chega na nossa condio de parada (1)# O processador comea a desencadear essas chamadas que empilhamos.# Seguindo assim:fact(1) -> 1fact(2) -> (1) * 2 -> 2fact(3) -> (2) * 3 -> 6fact(4) -> (6) * 4 -> 24

Implementar uma funo fatorial utilizando recursividade bem simples, n? Mas se formos considerar a explicao que acabamos de ver, isso pode se tornar um problema?

Imagine que temos uma funo que precisar iterar milhares de vezes para resolver um determinado problema, precisaremos empilhar vrias chamadas no-resolvidas na nossa pilha de chamadas, e isso poder estourar o limite da pilha.

Para esse problema em especfico, h uma soluo chamada Tail Call Optimization (ou TCO). Com TCO possvel eliminar essas chamadas no-resolvidas que uma funo recursiva costuma criar.

O pulo do gato quando aplicamos Tail Call Optimization em uma funo recursiva que essa funo saiba o valor processado em todas as suas chamadas, sendo assim, ela no depende do desencadeamento para encontrar o valor final de sua execuo.

E como podemos fazer isso? Segue o exemplo de uma chamada sem TCO:

# nossa condio de paradadef fact(1), do: 1# funo fatorial recursivadef fact(val), do: fact(val - 1) * val

com TCO:

def fact(val), do: fact(val - 1, val)# nossa condio de paradadefp fact(1, res), do: res# funo fatorial recursivadefp fact(val, res), do: fact(val - 1, res * val)

A grande diferena, que na funo fatorial com TCO, ela sabe exatamente o valor da sua execuo.

fact(4) -> fact(4 - 1, 4)fact(3, 4) -> fact(3 - 1, (4 * 3)) -> fact(2, 12)fact(2, 12) -> fact(2 - 1, (12 * 2)) -> fact(1, 24)fact(1, 24) -> 24

Portanto, quando a nossa funo chega na sua condio de parada, no necessrio desencadear todas as chamadas anteriores e seus respectivos clculos. Ela s precisa retornar seu valor final (24) para a funo que originou a sua chamada fact(4).

Fato curioso: Por padro, Elixir/Erlang implementam Tail Call Optimization, por isso a utilizao de recursividade algo muito comum e encorajada! Inclusive as High Order Functions so implementadas atravs de recursividade, no final das contas.

Concluso

Elixir amor, Erlang vida.

thats all


Original Link: https://dev.to/wlsf/mas-e-os-loops-em-elixir-3d0k

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To