Ruby 2.7.0-rc1 Publicado

Nos complace anunciar la publicación de Ruby 2.7.0-rc1.

Una versión candidata se publica para recibir retroalimentación sobre la versión final planeada para Diciembre. Esta rc1 se publica principalmente para confirmar la compatibilidad de los argumentos de palabra clave.

También introduce una serie de características nuevas y mejoras de desempeño, las más notorias son:

  • Compactar en el Recolector de Basura (GC)
  • Reconocimiento de patrones
  • Mejoras en REPL
  • Separación de argumentos posicionales y con palabra clave

Compactar en el recolector de basura (GC)

Esta versión introduce compactar en el recolector de basura, que defragmenta un espacio de memoria fragmentado.

Algunos programas Ruby de múltiples hilos pueden causar fragmentación en la memoria, que conlleva a un alto uso de la memoria y a que se degrade la velocidad.

El método GC.compact se introduce para compactar el montón (heap). Esta función compacta los objetos vivos en el montón de forma que usen menos páginas y que el montón sea más amigable con la técnica de administración de recursos compartidos “Copiar ante Escritura” (Copy on Write o CoW). [Característica #15626]

Reconocimiento de patrones [Experimental]

El reconocimiento de patrones, es una característica ampliamente usada en lenguajes de programación funcional, se introduce como característica experimental. [Característica #14912]

Puede recorrer un objeto dado y asignar su valor si concuerda con un patrón.

json ='{
  "nombre": "Alice",
  "edad": 30,
  "hijos": [
    {
      "nombre": "Bob",
      "edad": 2
    }
  ]
}'
case JSON.parse(json, symbolize_names: true)
in {nombre: "Alice", hijos: [{nombre: "Bob", edad: edad}]}
  p edad
  ...
end

Puede ver más detalles en Pattern matching - New feature in Ruby 2.7.

Mejoras a REPL

irb, el ambiente interactivo incluido con Ruby (REPL; Read-Eval-Print-Loop; Bucle-Leer-Evaluar-Presentar), ahora soporta edición de múltiples líneas. Es potenciado por reline, la implementación en puro Ruby de readline. También provee integración con rdoc. En irb puede presentar el manual de referencia para una clase dada, para un modulo o para un método. [Característica #14683], [Característica #14787], [Característica #14918]

Además, ahora se presentan con colores tanto el código fuente de su programa al iniciar una sesión IRB con binding.irb como los resultados de inspeccionar los objetos de las clases del núcleo de ruby.

Separación de argumentos posicionales y con palabra clave

Se desecha la conversión automática de argumentos con palabra clave a argumentos posicionales, y tal conversión se eliminará en Ruby 3. [Característica #14183]

  • Si la llamada a un método pasa un diccionario (Hash) cómo último argumento y si no pasa palabras clave, y si el método llamado acepta palabras clave, se emitirá una advertencia. Para seguir tratando el diccionario como palabras clave, agregue un operador doble splat al llamar para evitar la advertencia y asegurar el comportamiento correcto en Ruby 3.

    def foo(key: 42); end; foo({key: 42})   # advertencia
    def foo(**kw);    end; foo({key: 42})   # advertencia
    def foo(key: 42); end; foo(**{key: 42}) # OK
    def foo(**kw);    end; foo(**{key: 42}) # OK
    
  • Si la llamada a un método pasa palabras clave a un método que acepta palabras clave, pero no pasa suficientes argumentos posicionales requeridos, las palabras clave se tratarán como los argumentos posicionales finales que requiera el método pero se emitirá una advertencia. Pase el argumento como un diccionario en lugar de palabras clave para evitar la advertencia y asegurar el comportamiento correcto en Ruby 3.

    def foo(h, **kw); end; foo(key: 42)      # warned
    def foo(h, key: 42); end; foo(key: 42)   # warned
    def foo(h, **kw); end; foo({key: 42})    # OK
    def foo(h, key: 42); end; foo({key: 42}) # OK
    
  • Si un método acepta palabras clave especificas, pero no una palabra clave splat, y si en la llamada al método se pasa un diccionario o palabra clave con unas llaves que sean símbolos y otras que no sean símbolos, el diccionario será dividido y se emitirá una advertencia. Tendrá que actualizar el código que hace la llamada para pasar diccionarios separados y asegurar el comportamiento correcto en Ruby 3.

    def foo(h={}, key: 42); end; foo("key" => 43, key: 42)   # warned
    def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned
    def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK
    
  • Si un método no acepta palabras clave, y se llama con palabras clave, las palabras clave se tratarán como un diccionario posicional, sin advetencias. Este comportamiento seguirá operando en Ruby 3.

    def foo(opt={});  end; foo( key: 42 )   # OK
    
  • Las cadenas que no sean símbolos se aceptarán como llaves en argumentos con palabras clave si el método acepta palabras clave arbitrarias. [Característica #14183]

    def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
    
  • **nil se permite en la definición de métodos para marcar explicitamente que el método no acepta palabras clave. Llamar a un método así con palabras clave resultará en un ArgumentError. [Característica #14183]

    def foo(h, **nil); end; foo(key: 1)       # ArgumentError
    def foo(h, **nil); end; foo(**{key: 1})   # ArgumentError
    def foo(h, **nil); end; foo("str" => 1)   # ArgumentError
    def foo(h, **nil); end; foo({key: 1})     # OK
    def foo(h, **nil); end; foo({"str" => 1}) # OK
    
  • Si se pasa una palabra clave splat vacía a un método que no acepta palabras clave, ya no pasará un diccionario vacío, a menos que el diccionario vacío sea necesario para una parámetro requerido, en cuyo caso se emite una advertencia. Elimine el doble splat para continuar pasando un diccionario posicional. [Característica #14183]

    h = {}; def foo(*a) a end; foo(**h) # []
    h = {}; def foo(a) a end; foo(**h)  # {} and warning
    h = {}; def foo(*a) a end; foo(h)   # [{}]
    h = {}; def foo(a) a end; foo(h)    # {}
    

NOTA: Muchos mensajes de obsolecencia por incompatibilidad de argumentos de palabra clave han sido señalados de ser muy extensos. En el momento, se discuten dos soluciones posibles; deshabilitar los mensajes de obsolecencia por omisión (#16345) o suprimir las advertencias duplicadas (#16289). La decisión final no se ha tomado, pero se adoptará una con la versión oficial.

Otras caracerísticas nuevas y notables

  • Un operador para referenciar un método, .:, se introdujo como característica experimental en versiones preview anteriores, pero se ha revertido. [Característica #12125], [Característica #13581] [Característica #16275]

  • Como característica experimental se introducen paramétros numerados como parámetros por omisión en bloques. [Característica #4475]

  • Un rango sin inicio se introduce de forma experimental. Podría no ser tan útil como un rango sin terminación, pero es bueno para lenguajes específicos para un domino (DSL). [Característica #14799]

    ary[..3]  # identico a ary[0..3]
    rel.where(ventas: ..100)
    
  • Se añade Enumerable#tally. Que cuenta las ocurrencias de cada elemento.

    ["a", "b", "c", "b"].tally
    #=> {"a"=>1, "b"=>2, "c"=>1}
    
  • Ahora se permite llamar un método privado conself. [Característica #11297], [Característica #16123]

    def foo
    end
    private :foo
    self.foo
    
  • Se añade Enumerator::Lazy#eager que genera un enumerador no-perezoso a partir de un enumerador perezoso. [Característica #15901]

    a = %w(foo bar baz)
    e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager
    p e.class               #=> Enumerator
    p e.map {|x| x + "?" }  #=> ["FOO!?", "BAR!?", "BAZ!?"]
    

Mejoras en desempeño

  • JIT [Experimental]

    • El código compilado con JIT es recompilado a uno menos optimizado cuando los supuestos de la optimización dejan de ser válidos.

    • Un método se puede ejecutar en línea (method inlining o inserción en lugar de llamado) cuando un método se considera puro. Esta optimización aún es experimental y muchos métodos aún NO se consideran puros.

    • El valor por omisión de --jit-min-calls cambió de 5 a 10,000

    • El valor por omisión de --jit-max-cache cambió de 1,000 a 100

  • Symbol#to_s, Module#name, true.to_s, false.to_s y nil.to_s ahora siempre retornan una cadena congelada. La cadena retornada es siempre la misma para un objeto dado. [Experimental] [Característica#16150]

  • Se mejora el desempeño de CGI.escapeHTML. GH-2226

  • Se mejora el desempeño de `Monitor y MonitorMixin [Característica #16255]

Otros cambios notables desde la versión 2.6

  • Se actualizaron algunas librerías estándar
    • Bundler 2.1.0.pre.3 (Historia)
    • RubyGems 3.1.0.pre.3 (Historia)
    • CSV 3.1.2 (NOVEDADES)
    • Racc 1.4.15
    • REXML 3.2.3 (NOVEDADES)
    • RSS 0.2.8 (NOVEDADES)
    • StringScanner 1.0.3
    • Algunas de las otras librerías que no tienen versión original también se actualizaron.
  • Se promovieron de stdlib a gemas por omisión
    • Las siguientes gemas por omisión se publicaron en rubygems.org
      • benchmark
      • cgi
      • delegate
      • getoptlong
      • net-pop
      • net-smtp
      • open3
      • pstore
      • singleton
    • Las siguientes gemas por omisión se promovieron en ruby-core pero aún no se han publicado en rubygems.org
      • monitor
      • observer
      • timeout
      • tracer
      • uri
      • yaml
  • Proc.new y proc sin bloque en un método llamado con un bloque ahora produce una advertencia.

  • lambda sin un bloque en un método llamado con un bloque produce un error.

  • Actualizada la versión de Unicode y de Emoji de 11.0.0 a 12.0.0. [Característica #15321]

  • Actualizada la versión de Unicode a 12.1.0, añadiendo soporte para U+32FF SQUARE ERA NAME REIWA. [Característica #15195]

  • Date.jisx0301, Date#jisx0301, y Date.parse soportan la nueva era japonesa. [Característica#15742]

  • Requiere compiladores que soporten C99 [Misc #15347]
  • ~~ Regexp#match{?} con nil` lanza TypeError con String y Symbol. [Característica #13083]~~ revertido

Vea más detalles en el archivo NEWS o en la bitácora de cambios.

Con estos cambios, 4163 archivos modificados, 226280 inserciones(+), 99449 eliminaciones (-) desde Ruby 2.6.0!

¡Disfrute programando con Ruby 2.7!

Descargas

  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0-rc1.tar.bz2

    SIZE: 14691356
    SHA1: f501841276c4a922104b4afb19ff385a6de6b2e0
    SHA256: 1c5a02b63fa9fca37c41681bbbf20c55818a32315958c0a6c8f505943bfcb2d2
    SHA512: b5f96227775f8bdf19f944a555d0a83d7e84b37bd31fe4b8ac008a3272b1a28a4d94abbb1b5570ee32ec0690ba9d476b837a020a5194bee14bebf6f0e768bc79
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0-rc1.tar.gz

    SIZE: 16772802
    SHA1: c45cb603ed845d1e0d458d3fdc1afc910b6945b4
    SHA256: 59bd97b82e167453b5c76bc0fbb50ebda15ccee56b9ef1e94d5530b095b8a392
    SHA512: 6710266d221e9fd0ac9d6c40d48ce502badbc8b87ef500bb428b63e1744497903be267860dbc93a78235ef959ae3326f7e3c597b5567df87648fccb216d56f7d
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0-rc1.tar.xz

    SIZE: 11987512
    SHA1: 7d57c78a1c05e4d03d9f6726512f2c31d74413d8
    SHA256: 7528db87df7a8cbfdcbd053073839f5a00b2a38f807771e3e45000e72fc86732
    SHA512: 202b1a5bf01e6c398b8745cf968027db507ef39df521b3b24e06c6894d507ffcef9e904fa0d3a47f8be98fe750ca15a9829eb75627dacb4679538a61dabbe368
    
  • https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0-rc1.zip

    SIZE: 20645360
    SHA1: 3f0c415b8c2c674c9d4a86cce48347b15f822de8
    SHA256: f0c73add73c84a0390dca858c8c24e0cab107ada7dea7193e1ae207f78b79193
    SHA512: 23db300274f8a60aa89b3ab4a1685fba527b62c66b6944f03fdb4c32418e65aae3adc909c7c7c8dae743def230dadbf19ec3be6de50a9e955a0049b5c26e4020
    

¿Qué es Ruby?

Ruby fue desarrollado primero por Matz (Yukihiro Matsumoto) en 1993, y ahora es desarrollado como Código Abierto. Corre en múltiples plataformas y se usa en todo el mundo especialmente para desarrollo web.