Skip to content

Instantly share code, notes, and snippets.

@kelvinst
Last active August 29, 2015 14:10
Show Gist options
  • Select an option

  • Save kelvinst/826c4deb51d27422e7f9 to your computer and use it in GitHub Desktop.

Select an option

Save kelvinst/826c4deb51d27422e7f9 to your computer and use it in GitHub Desktop.

Revisions

  1. kelvinst revised this gist Nov 24, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Ruby magics: método `Enumerable#inject`
    # 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.

  2. kelvinst revised this gist Nov 24, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # Ruby magics: método `#inject` do module `Enumerable`
    # Ruby magics: método `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.

  3. kelvinst revised this gist Nov 24, 2014. No changes.
  4. kelvinst revised this gist Nov 24, 2014. No changes.
  5. kelvinst revised this gist Nov 24, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,7 @@ Este método acima, soma todos os elementos do range `1..3`. Esse mesmo código

    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: 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`.
    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.

  6. kelvinst revised this gist Nov 24, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,9 @@ Este método acima, soma todos os elementos do range `1..3`. Esse mesmo código

    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: 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`. Na terceira o result é `3` (1 + 2) e na quarta e última fica `6` (3 + 3).
    Então, esse é mais complicado de explicar: 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.

  7. kelvinst revised this gist Nov 24, 2014. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -12,7 +12,7 @@ O conceito em si é muito simples, é apenas uma maneira de combinar todos os el

    ## Mas como isso?

    E para implementar ele é assim:
    E para implementar ele fazemos assim:

    ```ruby
    (1..3).inject(0) do |result, i|
  8. kelvinst revised this gist Nov 24, 2014. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -2,12 +2,12 @@

    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 que ele faz?

    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?
  9. kelvinst revised this gist Nov 24, 2014. 1 changed file with 39 additions and 6 deletions.
    45 changes: 39 additions & 6 deletions enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -2,14 +2,47 @@

    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.

    Bem, o método `#inject` (ou `#reduce`, que é só um alias para `#inject`) está primariamente implementado no module `Enumerable`, que por sua vez é incluído em várias das classes da API padrão do ruby.
    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.

    Pra ficar bem claro o que é um `Enumerable`, podemos basicamente chamar ele de **collection do ruby**. E como em várias outras linguagens, as collections têm vários métodos úteis para coleções de objetos, como o `#contains?` e o `#empty?` por exemplo, logo no ruby não poderia ser diferente. Se você não conhece muito dos métodos da `Enumerable`, sugiro [dar uma olhada neles](http://ruby-doc.org/core-2.1.5/Enumerable.html), têm muitos métodos que podem te ajudar ali.
    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.

    Mas vamos ao que interessa: a ideia do método `#inject` é retornar um outro objeto a partir da iteração nos valores do seu `Enumerable`. Bem simples né? Parece, mas não é...
    ## O que ele faz?

    Pra ilustrar melhor: você deve conhecer já o método `#map` (que por acaso também é da `Enumerable`), ele te retorna um `Array` com o retorno de cada iteração. Por exemplo, o código `[1, 2, 3].map { |i| i + 1 }` nos retorna `[2, 3, 4]`.
    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.

    Bem, e o que você fez nisso? Não transformou um `Enumerable` em outro objeto (nesse caso um outro `Enumerable`)? Pois é, o inject faz exatamente isso certo? Mas então porque usar o inject? Bem, é que com o map, o resultado sempre é um array, mas com o `#inject`, você define o resultado, pode ser o que você quiser! Até um inteiro!
    ## Mas como isso?

    Mas como implemento? Olha só um exemplo: o código `[1, 2, 3].inject(0) { |result, i| result + i }` retorna `6`. Isso mesmo, com esse código você somou todos os itens do array. Interessante né?
    E para implementar ele é 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: 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`. Na terceira o result é `3` (1 + 2) e na quarta e última fica `6` (3 + 3).

    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:
  10. kelvinst created this gist Nov 24, 2014.
    15 changes: 15 additions & 0 deletions enumerable-inject.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,15 @@
    # Ruby magics: método `#inject` do module `Enumerable`

    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.

    Bem, o método `#inject` (ou `#reduce`, que é só um alias para `#inject`) está primariamente implementado no module `Enumerable`, que por sua vez é incluído em várias das classes da API padrão do ruby.

    Pra ficar bem claro o que é um `Enumerable`, podemos basicamente chamar ele de **collection do ruby**. E como em várias outras linguagens, as collections têm vários métodos úteis para coleções de objetos, como o `#contains?` e o `#empty?` por exemplo, logo no ruby não poderia ser diferente. Se você não conhece muito dos métodos da `Enumerable`, sugiro [dar uma olhada neles](http://ruby-doc.org/core-2.1.5/Enumerable.html), têm muitos métodos que podem te ajudar ali.

    Mas vamos ao que interessa: a ideia do método `#inject` é retornar um outro objeto a partir da iteração nos valores do seu `Enumerable`. Bem simples né? Parece, mas não é...

    Pra ilustrar melhor: você deve conhecer já o método `#map` (que por acaso também é da `Enumerable`), ele te retorna um `Array` com o retorno de cada iteração. Por exemplo, o código `[1, 2, 3].map { |i| i + 1 }` nos retorna `[2, 3, 4]`.

    Bem, e o que você fez nisso? Não transformou um `Enumerable` em outro objeto (nesse caso um outro `Enumerable`)? Pois é, o inject faz exatamente isso certo? Mas então porque usar o inject? Bem, é que com o map, o resultado sempre é um array, mas com o `#inject`, você define o resultado, pode ser o que você quiser! Até um inteiro!

    Mas como implemento? Olha só um exemplo: o código `[1, 2, 3].inject(0) { |result, i| result + i }` retorna `6`. Isso mesmo, com esse código você somou todos os itens do array. Interessante né?