Ruby 2.7.0-preview3 Released

We are pleased to announce the release of Ruby 2.7.0-preview3.

A preview version is released to gather feedback for the final release planned for December. This preview3 is mainly released to confirm the compatibility of keyword arguments.

It also introduces a number of new features and performance improvements, most notably:

  • Compaction GC
  • Pattern Matching
  • REPL improvement
  • Separation of positional and keyword arguments

Compaction GC

This release introduces Compaction GC which can defragment a fragmented memory space.

Some multi-threaded Ruby programs may cause memory fragmentation, leading to high memory usage and degraded speed.

The GC.compact method is introduced for compacting the heap. This function compacts live objects in the heap so that fewer pages may be used, and the heap may be more CoW friendly. [Feature #15626]

Pattern Matching [Experimental]

Pattern matching, a widely used feature in functional programming languages, is introduced as an experimental feature. [Feature #14912]

It can traverse a given object and assign its value if it matches a pattern.

require "json"

json = <<END
  "name": "Alice",
  "age": 30,
  "children": [{ "name": "Bob", "age": 2 }]

case JSON.parse(json, symbolize_names: true)
in {name: "Alice", children: [{name: "Bob", age: age}]}
  p age #=> 2

For more details, please see Pattern matching - New feature in Ruby 2.7.

REPL improvement

irb, the bundled interactive environment (REPL; Read-Eval-Print-Loop), now supports multi-line editing. It is powered by reline, a readline-compatible pure Ruby implementation. It also provides rdoc integration. In irb you can display the reference for a given class, module, or method. [Feature #14683], [Feature #14787], [Feature #14918]

Besides, source lines shown at binding.irb and inspect results for core-class objects are now colorized.

Separation of positional and keyword arguments

Automatic conversion of keyword arguments and positional arguments is deprecated, and conversion will be removed in Ruby 3. [Feature #14183]

  • When a method call passes a Hash at the last argument, and when it passes no keywords, and when the called method accepts keywords, a warning is emitted. To continue treating the hash as keywords, add a double splat operator to avoid the warning and ensure correct behavior in Ruby 3.

    def foo(key: 42); end; foo({key: 42})   # warned
    def foo(**kw);    end; foo({key: 42})   # warned
    def foo(key: 42); end; foo(**{key: 42}) # OK
    def foo(**kw);    end; foo(**{key: 42}) # OK
  • When a method call passes keywords to a method that accepts keywords, but it does not pass enough required positional arguments, the keywords are treated as a final required positional argument, and a warning is emitted. Pass the argument as a hash instead of keywords to avoid the warning and ensure correct behavior in 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
  • When a method accepts specific keywords but not a keyword splat, and a hash or keywords splat is passed to the method that includes both Symbol and non-Symbol keys, the hash will continue to be split, and a warning will be emitted. You will need to update the calling code to pass separate hashes to ensure correct behavior in 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
  • If a method does not accept keywords, and is called with keywords, the keywords are still treated as a positional hash, with no warning. This behavior will continue to work in Ruby 3.

    def foo(opt={});  end; foo( key: 42 )   # OK
  • Non-symbols are allowed as keyword argument keys if the method accepts arbitrary keywords. [Feature #14183]

    def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1}
  • **nil is allowed in method definitions to explicitly mark that the method accepts no keywords. Calling such a method with keywords will result in an ArgumentError. [Feature #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
  • Passing an empty keyword splat to a method that does not accept keywords no longer passes an empty hash, unless the empty hash is necessary for a required parameter, in which case a warning will be emitted. Remove the double splat to continue passing a positional hash. [Feature #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)    # {}

NOTE: Too many deprecation warnings about keyword argument incompatibility have been pointed out to be too verbose. Currently, two possible solutions are discussed; disabling deprecation warnings by default (#16345) or suppressing duplicated warnings (#16289). The final decision is not made, but will be fixed by the official release.

Other Notable New Features

  • A method reference operator, .:, was introduced as an experimental feature in earlier previews, but was reverted. [Feature #12125], [Feature #13581], [Feature #16275]

  • Numbered parameter as the default block parameter is introduced as an experimental feature. [Feature #4475]

  • A beginless range is experimentally introduced. It might not be as useful as an endless range, but would be good for DSL purposes. [Feature #14799]

    ary[..3]  # identical to ary[0..3]
    rel.where(sales: ..100)
  • Enumerable#tally is added. It counts the occurrence of each element.

    ["a", "b", "c", "b"].tally
    #=> {"a"=>1, "b"=>2, "c"=>1}
  • Calling a private method on self is now allowed. [Feature #11297], [Feature #16123]

    def foo
    private :foo
  • Enumerator::Lazy#eager is added. It generates a non-lazy enumerator from a lazy enumerator. [Feature #15901]

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

Performance improvements

  • JIT [Experimental]

    • JIT-ed code is recompiled to less-optimized code when an optimization assumption is invalidated.

    • Method inlining is performed when a method is considered as pure. This optimization is still experimental and many methods are NOT considered as pure yet.

    • The default value of --jit-min-calls is changed from 5 to 10,000.

    • The default value of --jit-max-cache is changed from 1,000 to 100.

  • Symbol#to_s (reverted), Module#name, true.to_s, false.to_s, and nil.to_s now always return a frozen String. The returned String is always the same for a given object. [Experimental] [Feature #16150]

  • The performance of CGI.escapeHTML is improved. GH-2226

  • The performance of Monitor and MonitorMixin is improved. [Feature #16255]

Other notable changes since 2.6

  • Some standard libraries are updated.
    • Bundler 2.1.0.pre.3 (History)
    • RubyGems 3.1.0.pre.3 (History)
    • CSV 3.1.2 (NEWS)
    • Racc 1.4.15
    • REXML 3.2.3 (NEWS)
    • RSS 0.2.8 (NEWS)
    • StringScanner 1.0.3
    • Some other libraries that have no original version are also updated.
  • Promote stdlib to default gems
    • The following default gems were published on
      • benchmark
      • cgi
      • delegate
      • getoptlong
      • net-pop
      • net-smtp
      • open3
      • pstore
      • singleton
    • The following default gems were only promoted at ruby-core, but not yet published on
      • monitor
      • observer
      • timeout
      • tracer
      • uri
      • yaml
  • and proc with no block in a method called with a block is warned now.

  • lambda with no block in a method called with a block errs.

  • Update Unicode version and Emoji version from 11.0.0 to 12.0.0. [Feature #15321]

  • Update Unicode version to 12.1.0, adding support for U+32FF SQUARE ERA NAME REIWA. [Feature #15195]

  • Date.jisx0301, Date#jisx0301, and Date.parse support the new Japanese era. [Feature #15742]

  • Require compilers to support C99 [Misc #15347]
  • Regexp#match{?} with nil raises TypeError as String, Symbol. [Feature #13083] reverted

3895 files changed, 213426 insertions(+), 96934 deletions(-)

See NEWS or commit logs for more details.

With those changes, stat since Ruby 2.6.0!

Enjoy programming with Ruby 2.7!



    SIZE: 14630824
    SHA1: 1fa35d8a26dfc814e92fa259095f4cf70f386f87
    SHA256: df2ddee659873e6fc30a8590ecffa49cf3a4ef81fa922b0d09f821b69ee88bc3
    SHA512: 5d8e99e3fd984c7d05c0bc483e1504e81ccdb920cbb2d78cad3c314e197b30316b692fd0199f836acac41246e3a713cb81dc6dd64c27cba56f807df4c193db1a

    SIZE: 16723536
    SHA1: 7554926ee29a344da4b53d67fc296d70fdbe60ca
    SHA256: 9baa1f5096ebc2a0923df628d7dc7105da3789c1bf8b873469d9010249736b00
    SHA512: 8fad3e761fd54036fee974a9f33e4db31d9a8a878b1181a08724388f5a1da548ab249136356f675797e9c43b565777bf22e6a419db1364336f134b31f4e75b33

    SIZE: 11923988
    SHA1: f3c54538915483e5ddc714ac23414e7c47048b12
    SHA256: ad9d61e55ac224e3447a762e001965839846f9658f87a0e792840887cfe61b8c
    SHA512: 2b6844f34d32f1013dc3110043e6ece33a083b20f1343dea9a14311bda0017e8f56fc7d73be1616999b22ce430d7ba59a77bb0892d27c6d1ec243c3860086133

    SIZE: 20691541
    SHA1: d18b494cda4db751d8b3f5026404e348f3f682e3
    SHA256: 2bc95f67f271b6a41fc3dd40536705b4a7974df8a2fa33ff0758a60822291781
    SHA512: af9f728aebc53693cbd9f78a632c82e851e9f83dfc0c53979fdc37c627b11482c8435ce12dbb1d5a7253e998ea989759be699e6a00aae18384d2d765650cb0d7

What is Ruby

Ruby was first developed by Matz (Yukihiro Matsumoto) in 1993, and is now developed as Open Source. It runs on multiple platforms and is used all over the world especially for web development.