# Ruby magics: `Enumerable#inject` Como muitos já sabem, sou apaixonado pro ruby e já [compartilhei vários motivos do por quê](https://gist.github.com/kelvinst/fccfe340b9a9eea2befe). Mas dentre os motivos que dei, não entrei muito em detalhes de códigos no ruby que me deixam sem ar de tão legais e fáceis de implementar. E um exemplo desse tipo de código é o método `#inject` que vou explicar pra vocês agora. Espero que se empolguem e que usem ele sabiamente. ## O que ele faz? Bom, pra quem caiu de paraquedas aqui: o module `Enumerable` é o modules que representa uma collection no ruby. Se você tem uma classe que é uma collection, apenas inclua esse module e implemente o método `#each` e você terá vários métodos úteis na sua collection. E um desses métodos é o `#inject`, ou `#reduce` que é apenas um alias para `#inject`. Agora vamos aos detalhes desse método tão maravilhoso. O conceito em si é muito simples, é apenas uma maneira de combinar todos os elementos da collection em um novo objeto. Ou seja, o método retorna um novo objeto a partir da iteração em todos os elementos. ## Mas como isso? E para implementar ele fazemos assim: ```ruby (1..3).inject(0) do |result, i| result + i end # => 6 ``` Este método acima, soma todos os elementos do range `1..3`. Esse mesmo código pode ser escrito assim: `(1..3).inject(0, :+)`. Mas para explicar como o método funciona, vamos ficar com o primeiro exemplo. Como podem ver, só batendo o olho não é muito claro como ele funciona. Então vou explicar como funciona: o método `#inject` itera no `Enumerable` e executa o bloco de código para cada iteração, igual ao `#each`. Mas o que é esse primeiro parêmtro `result` do bloco? Então, esse é mais complicado de explicar :grin:: no primeiro parâmetro do bloco o `#inject` passa para você o retorno da execução da iteração anterior, e na primeira iteração, ele é igual ao valor passado por parâmetro para o `#inject`, no nosso caso o `0`. Sacou? No nosso código por exemplo, na primeira iteração o `result` é `0`, pois foi o que passamos por parâmetro. Na segunda iteração é `1`, pois somamos o `result` que era `0`, com o item da iteração `i`, que era `1`, e assim por diante. O resultado retornado pelo `#inject` é o retorno da última iteração. Meio complicado só pra somar um array né? Mas lembre-se que você pode fazer isso em uma linha de código, e ainda deixar o código bem legível! Olha outra utilidade para essa "belezura": ```ruby (1..3).inject(Hash.new) do |result, i| result[i.to_s] = i result end # => {'1' => 1, ... } ``` Viu? Facilmente convertemos um range para um hash! Consegue perceber o poder que isso te dá? Então vá e use ele! ## Conclusão Lembre-se, com grandes poderes vêm grandes responsabilidades. Use o inject com conciência, por mais magnífico que ele seja, muitas vezes ele pode ficar bem ilegível, e bem difícil de dar manutenção. Pra finalizar, uma dica: explore mais os [métodos do module `Enumerable`](http://ruby-doc.org/core-2.1.5/Enumerable.html), tem outros métodos muito úteis. :wink: