Ir para conteúdo principal
Lucas Caton

Ruby 2.6 acaba de ser lançado!

Com mais performance, JIT, ranges infinitos, método "then" e muito mais!

Lucas Caton

Lucas Caton

@lucascaton
Desde 2013, os desenvolvedores do Ruby mantém uma tradição de lançar uma nova versão da linguagem na época do Natal e nesse ano não foi diferente.
Ruby 2.6

Como instalar/atualizar?

Antes de mais nada: sim, já é possível instalar e usar a nova versão!
Para instalar usando os gerenciadores mais populares:

RVM:

bash
# Atualize o RVM:
$ rvm get stable

# Instale o Ruby 2.6:
$ rvm install 2.6.0

rbenv:

bash
# Atualize a lista de versões do Ruby:
$ cd "$(rbenv root)"/plugins/ruby-build && git pull

# Instale o Ruby 2.6:
$ rbenv install 2.6.0
* * *
Vamos então dar uma olhada no que há de novo nessa nova versão!

Melhorias de performance

Essa versão tem algumas melhorias de performance, como:
  • O método Proc#call está aproximadamente 1.4x mais rápido.
  • Hashes de vida-útil curta consomem 7% menos memória.
Na RubyConf de 2015, Matz (criador do Ruby) anunciou o Ruby 3x3, que são os planos para fazer o Ruby 3.0 ficar 3x mais rápido. Essa versão provavelmente será lançada em 2020.
Uma das estratégias que viabilizará essa grande melhoria de performance é o JIT/MJIT, que está sendo incluída (como recurso experimental) na versão 2.6, conforme você confere na sessão abaixo:

JIT (Just-in-time)

Uma das funcionalidades mais notáveis da versão 2.6 do Ruby é que ela vem com uma implementação (experimental) de um compilador JIT (Just-in-time).
Segundo esse artigo do Guy Maliar (em uma tradução livre):
A idéia por trás de um compilador JIT é "inspencionar" o código em tempo de execução e tentar otimizar de forma mais inteligente o código atualmente em execução, que é o oposto do que acontece em um compilador AOT (Ahead Of Time compiler).
Essa é apenas a implementação inicial e ainda está um pouco instável.
Entretando, benchmarks iniciais mostram resultados muito bons. O emulador de NES "Optcarrot" rodou ~ 77% mais rápido, se comparado com o Ruby 2.5.3:
Ruby (versão)FPS (frames por segundo)
2.5.348.3
2.6.054.5
2.6.0 + JIT85.7
(Fonte) {: .text-right}
Outros benchmarks mostram resultados ainda mais significativos:
BenchmarkQuanto mais rápido?Código
Mandlebrot1.27xVer código
Fibonacci3.19xVer código
const/const2Quase 4xVer código
Leia mais sobre JIT (e MJIT) neste artigo.

Bundler agora vem com o Ruby

Bundler
Já faz um tempo que essa discussão começou e agora é oficial: a gem bundler vem por padrão com o Ruby!
Quem tiver curiosidade, esse é o Pull Request com tudo que foi alterado.
Essa mudança é especialmente bem-vinda pelo fato de ajudar iniciantes, já que elimina um passo na instalação do Ruby (e é com prazer que eu vou ter que regravar já regravei essa aula do meu curso 🙂).
Você pode ler mais sobre essa integração no blog de engenharia da Appfolio.

O método #then

O método yield_self foi adicionado no Ruby 2.5. A novidade agora é que ele ganhou um alias: then.
Considere o seguinte exemplo de código de controller do Rails:
ruby
events = Event.upcoming
events = events.limit(params[:limit])          if params[:limit]
events = events.where(status: params[:status]) if params[:status]
events
Podemos reescrever o código acima usando yield_self ou then (já que o segundo é apenas um alias do primeiro):
ruby
Event.upcoming
  .yield_self { |events| params[:limit]  ? events.limit(params[:limit])          : events }
  .yield_self { |events| params[:status] ? events.where(status: params[:status]) : events }
Agora com then, que faz o código ficar um pouco mais legível:
ruby
Event.upcoming
  .then { |events| params[:limit]  ? events.limit(params[:limit])          : events }
  .then { |events| params[:status] ? events.where(status: params[:status]) : events }

Ranges infinitos

Agora podemos criar ranges sem especificar um valor final. Isso significa que podemos escrever códigos como:
ruby
array[1..]
# O código acima é identico à `array[1..-1]`
ruby
# Loop infinito que começa com índice 1
(1..).each { |index| ... }
ruby
array.zip(1..) { |elem, index| ... }
# O código acima é identico à `array.each.with_index(1) { }`

Novo método #filter para arrays (alias para o método #select)

Nós conhecemos bem o método select, mas em outras linguagens (como JavaScript, Java e PHP), ele é mais conhecido como filter. Se você, assim como eu, sempre quis que um alias fosse criado, esse momento chegou:
ruby
[:foo, :bar].filter { |x| x == :foo }
# => [:foo]

Métodos #union e #difference para arrays

Para quem lembra das aulas de matemática da escola ou para quem precisa trabalhar com união e diferença entre arrays, tenho uma boa notícia:
Dois métodos (#union e #difference) foram adicionados aos arrays.
Eis um exemplo:
ruby
[1, 1, 2, 2, 3, 3, 4, 5].difference([1, 2, 4])
# => [3, 3, 5]
ruby
['a', 'b', 'c'].union(['c', 'd', 'a'])
# => ['a', 'b', 'c', 'd']
ruby
['a'].union([['e', 'b'], ['a', 'c', 'b']])
# => ['a', 'e', 'b', 'c']

Veja também post oficial sobre o lançamento da versão 2.6.