Stream
Falamos sobre enumeráveis (ou enumerables), onde é uma caracterÃstica do que é enumerável ou qualidade daquilo que se consegue enumerar. Em nosso contexto, algo que podemos iterar, passando um por um. Fizemos exemplos de iteração no capÃtulo sobre Enum.
Stream está nessa mesma categoria, com uma diferença importante. Streams são composições de enumeração preguiçosa.
Isso quer dizer, diferente de listas que ao criamos são executadas, Streams
não são. Eles contém tudo que precisamos para executar, mas só irão ser executados quando for necessário. Logo, preguiçoso.
Vamos a um exemplo simples:
Precisamos agendar 5 eventos, porém, não queremos ter o resultado agora, porque só será processado semana que vem.
Vamos ao teste:
O teste parece complexo por nao ser tão comum utilizarmos Stream desa forma, mas, vamos tentar entende-lo.
Na linha 8 utilizamos o Stream.map/2
passando no primeiro argumento um enumerable (no nosso caso foi um range, mas poderia ser uma lista também). No segundo paramentro, passamos a função que queremos que execute para cada elemento de nosso enumerable. Isso quer dizer que esse função será executada para cada item dentro do campo enum.
Na linha 9 garantimos que criamos nosso enum
com o valor de range (1 até 5) e em funs
, que temos uma função para ser executada para cada interação. No teste de mesa seria:
Porém, estamos usando Stream
e esse código ainda não foi executado. Vamos rodar o teste para ver o que temos:
Estranho não? O teste passou, mesmo acusando em um warning
que não possuimos Event.schedule/1
. Isso quer dizer que a função não foi executada, como já esperavamos. Lembrando que Stream
é um carregamento preguiçoso, ele só será executado quando realmente precisar. Vamos seguir até falhar. Precisamos agora fazer ele executar. Vamos atualizar nosso teste.
A linha 12 roda o streaming para mim e nessa hora ele tenta executar a função passada. Vamos rodar o teste:
Agora temos nosso primeiro erro. Ele esta avisando que não possuÃmos a função Event.schedule/1
. O mais interessante é que agora ele falou que na linha 8 também não foi encontrado a função. Esse é um dos diferenciais de utilizar Stream
. Ele deixa tudo pronto para ser executado e quando realmente precisar, ele vai realizar a computação e dar o resultado.
Imagina um cenário onde temos milhoes de dados. Esses dados precisam ser computados na hora, podemos fazer isso aos poucos e com Stream
podemos criar uma lógica onde isso seja possÃvel. Deixando o processamento mais rápido e não gastando recursos de máquina a toa.
Vamos resolver o problema do teste e criar nossa implementação. Você vai perceber que agora se tornou uma função comum, como fizemos no capÃtulo sobre Enum. Vamos criar a função apenas para passar os testes até então:
Perfeito, estamos conseguindo executar Event.schedule/1
, porém, ele não faz nada. Vamos alterar nosso teste para que ele diga que o evento x foi agendado.
Vamos rodar esse teste:
Algo estranho aconteceu. A resposta para Stream.run/1
foi :ok
. Isso causou o problema que não estavamos esperando. Queriamos a lista de eventos agendados. Vamos entender isso.
A função Stream.run/1
mesmo executando nosso Stream
não retorna o valor processado. Ele é normalmente utilizado para iniciar um processo que não precisamos de uma resposta. Logo, essa função não serve para nós obtermos uma resposta do processamento. Para isso precisamos usar uma outra.
Para resolver isso, utilizaremos uma função simples do módulo Enum
chamada to_list
. Quando utilizamos ela, a própria função entende quando estamos utilizando Stream
e faz a conversão, executando o Stream
e pegando a resposta, convertendo para uma lista e devolvendo para nos como uma lista simples. Vamos a implementação:
Apenas alteramos a linha 11 para faze a conversão do Stream
para uma lista
. Isso faz todo o processamento e nos devolve a lista que queremos. vamos rodar o teste e ver o que acontece:
Perfeito! Fizemos nosso primeiro processamento de Stream
e tudo ocorreu bem.
Conclusão
Stream é uma lista de carregamento preguiçoso que só será executado quando realmente precisar. ele serve para evitar processamente sem necessidades, como quando não precisamos executar todos os dados de uma vez em uma lista de milhares de dados. Isso nós ajuda a salvar processamento.
Esse foi um exemlpo simples para entendermos o conceito de Stream. Fiz um vÃdeo mais avançado sobre processamento de grande quantidade de dados. Você pode dar uma olhada nele nesse link.
Last updated