|
| 1 | +--- |
| 2 | +layout: news_post |
| 3 | +title: "Ruby 2.7.0-preview3 Released" |
| 4 | +author: "naruse" |
| 5 | +translator: |
| 6 | +date: 2019-11-23 12:00:00 +0000 |
| 7 | +lang: en |
| 8 | +--- |
| 9 | + |
| 10 | +We are pleased to announce the release of Ruby 2.7.0-preview3. |
| 11 | + |
| 12 | +A preview version is released to gather feedback for the final release |
| 13 | +planned for December. |
| 14 | +This preview3 is mainly released to confirm the compatibility of |
| 15 | +keyword arguments. |
| 16 | + |
| 17 | +It also introduces a number of new features and performance improvements, |
| 18 | +most notably: |
| 19 | + |
| 20 | +* Compaction GC |
| 21 | +* Pattern Matching |
| 22 | +* REPL improvement |
| 23 | +* Separation of positional and keyword arguments |
| 24 | + |
| 25 | +## Compaction GC |
| 26 | + |
| 27 | +This release introduces Compaction GC which can defragment |
| 28 | +a fragmented memory space. |
| 29 | + |
| 30 | +Some multi-threaded Ruby programs may cause memory fragmentation, |
| 31 | +leading to high memory usage and degraded speed. |
| 32 | + |
| 33 | +The `GC.compact` method is introduced for compacting the heap. |
| 34 | +This function compacts live objects in the heap so that fewer pages |
| 35 | +may be used, and the heap may be more CoW friendly. |
| 36 | +[[Feature #15626]](https://bugs.ruby-lang.org/issues/15626) |
| 37 | + |
| 38 | +## Pattern Matching [Experimental] |
| 39 | + |
| 40 | +Pattern matching, a widely used feature in functional programming languages, |
| 41 | +is introduced as an experimental feature. |
| 42 | +[[Feature #14912]](https://bugs.ruby-lang.org/issues/14912) |
| 43 | + |
| 44 | +It can traverse a given object and assign its value if it matches a pattern. |
| 45 | + |
| 46 | +{% highlight ruby %} |
| 47 | +require "json" |
| 48 | + |
| 49 | +json = <<END |
| 50 | +{ |
| 51 | + "name": "Alice", |
| 52 | + "age": 30, |
| 53 | + "children": [{ "name": "Bob", "age": 2 }] |
| 54 | +} |
| 55 | +END |
| 56 | + |
| 57 | +case JSON.parse(json, symbolize_names: true) |
| 58 | +in {name: "Alice", children: [{name: "Bob", age: age}]} |
| 59 | + p age #=> 2 |
| 60 | +end |
| 61 | +{% endhighlight %} |
| 62 | + |
| 63 | +For more details, please see |
| 64 | +[Pattern matching - New feature in Ruby 2.7](https://speakerdeck.com/k_tsj/pattern-matching-new-feature-in-ruby-2-dot-7). |
| 65 | + |
| 66 | +## REPL improvement |
| 67 | + |
| 68 | +`irb`, the bundled interactive environment (REPL; Read-Eval-Print-Loop), |
| 69 | +now supports multi-line editing. It is powered by `reline`, |
| 70 | +a `readline`-compatible pure Ruby implementation. |
| 71 | +It also provides rdoc integration. In `irb` you can display the reference |
| 72 | +for a given class, module, or method. |
| 73 | +[[Feature #14683]](https://bugs.ruby-lang.org/issues/14683), |
| 74 | +[[Feature #14787]](https://bugs.ruby-lang.org/issues/14787), |
| 75 | +[[Feature #14918]](https://bugs.ruby-lang.org/issues/14918) |
| 76 | + |
| 77 | +Besides, source lines shown at `binding.irb` and inspect results |
| 78 | +for core-class objects are now colorized. |
| 79 | + |
| 80 | +<video autoplay="autoplay" controls="controls" muted="muted" width="576" height="259"> |
| 81 | + <source src="https://cache.ruby-lang.org/pub/media/irb_improved_with_key_take2.mp4" type="video/mp4"> |
| 82 | +</video> |
| 83 | + |
| 84 | +## Separation of positional and keyword arguments |
| 85 | + |
| 86 | +Automatic conversion of keyword arguments and positional arguments |
| 87 | +is deprecated, and conversion will be removed in Ruby 3. |
| 88 | +[[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 89 | + |
| 90 | +* When a method call passes a Hash at the last argument, and when it |
| 91 | + passes no keywords, and when the called method accepts keywords, |
| 92 | + a warning is emitted. To continue treating the hash as keywords, |
| 93 | + add a double splat operator to avoid the warning and ensure |
| 94 | + correct behavior in Ruby 3. |
| 95 | + |
| 96 | + {% highlight ruby %} |
| 97 | + def foo(key: 42); end; foo({key: 42}) # warned |
| 98 | + def foo(**kw); end; foo({key: 42}) # warned |
| 99 | + def foo(key: 42); end; foo(**{key: 42}) # OK |
| 100 | + def foo(**kw); end; foo(**{key: 42}) # OK |
| 101 | + {% endhighlight %} |
| 102 | + |
| 103 | +* When a method call passes keywords to a method that accepts keywords, |
| 104 | + but it does not pass enough required positional arguments, the |
| 105 | + keywords are treated as a final required positional argument, and |
| 106 | + a warning is emitted. Pass the argument as a hash instead of keywords |
| 107 | + to avoid the warning and ensure correct behavior in Ruby 3. |
| 108 | + |
| 109 | + {% highlight ruby %} |
| 110 | + def foo(h, **kw); end; foo(key: 42) # warned |
| 111 | + def foo(h, key: 42); end; foo(key: 42) # warned |
| 112 | + def foo(h, **kw); end; foo({key: 42}) # OK |
| 113 | + def foo(h, key: 42); end; foo({key: 42}) # OK |
| 114 | + {% endhighlight %} |
| 115 | + |
| 116 | +* When a method accepts specific keywords but not a keyword splat, and |
| 117 | + a hash or keywords splat is passed to the method that includes both |
| 118 | + Symbol and non-Symbol keys, the hash will continue to be split, and |
| 119 | + a warning will be emitted. You will need to update the calling code |
| 120 | + to pass separate hashes to ensure correct behavior in Ruby 3. |
| 121 | + |
| 122 | + {% highlight ruby %} |
| 123 | + def foo(h={}, key: 42); end; foo("key" => 43, key: 42) # warned |
| 124 | + def foo(h={}, key: 42); end; foo({"key" => 43, key: 42}) # warned |
| 125 | + def foo(h={}, key: 42); end; foo({"key" => 43}, key: 42) # OK |
| 126 | + {% endhighlight %} |
| 127 | + |
| 128 | +* If a method does not accept keywords, and is called with keywords, |
| 129 | + the keywords are still treated as a positional hash, with no warning. |
| 130 | + This behavior will continue to work in Ruby 3. |
| 131 | + |
| 132 | + {% highlight ruby %} |
| 133 | + def foo(opt={}); end; foo( key: 42 ) # OK |
| 134 | + {% endhighlight %} |
| 135 | + |
| 136 | +* Non-symbols are allowed as keyword argument keys if the method accepts |
| 137 | + arbitrary keywords. |
| 138 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 139 | + |
| 140 | + {% highlight ruby %} |
| 141 | + def foo(**kw); p kw; end; foo("str" => 1) #=> {"str"=>1} |
| 142 | + {% endhighlight %} |
| 143 | + |
| 144 | +* `**nil` is allowed in method definitions to explicitly mark |
| 145 | + that the method accepts no keywords. Calling such a method with keywords |
| 146 | + will result in an ArgumentError. |
| 147 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 148 | + |
| 149 | + {% highlight ruby %} |
| 150 | + def foo(h, **nil); end; foo(key: 1) # ArgumentError |
| 151 | + def foo(h, **nil); end; foo(**{key: 1}) # ArgumentError |
| 152 | + def foo(h, **nil); end; foo("str" => 1) # ArgumentError |
| 153 | + def foo(h, **nil); end; foo({key: 1}) # OK |
| 154 | + def foo(h, **nil); end; foo({"str" => 1}) # OK |
| 155 | + {% endhighlight %} |
| 156 | + |
| 157 | +* Passing an empty keyword splat to a method that does not accept keywords |
| 158 | + no longer passes an empty hash, unless the empty hash is necessary for |
| 159 | + a required parameter, in which case a warning will be emitted. |
| 160 | + Remove the double splat to continue passing a positional hash. |
| 161 | + [[Feature #14183]](https://bugs.ruby-lang.org/issues/14183) |
| 162 | + |
| 163 | + {% highlight ruby %} |
| 164 | + h = {}; def foo(*a) a end; foo(**h) # [] |
| 165 | + h = {}; def foo(a) a end; foo(**h) # {} and warning |
| 166 | + h = {}; def foo(*a) a end; foo(h) # [{}] |
| 167 | + h = {}; def foo(a) a end; foo(h) # {} |
| 168 | + {% endhighlight %} |
| 169 | + |
| 170 | +NOTE: Too many deprecation warnings about keyword argument incompatibility |
| 171 | +have been pointed out to be too verbose. Currently, two possible solutions |
| 172 | +are discussed; disabling deprecation warnings by default |
| 173 | +([#16345](https://bugs.ruby-lang.org/issues/16345)) |
| 174 | +or suppressing duplicated warnings |
| 175 | +([#16289](https://bugs.ruby-lang.org/issues/16289)). |
| 176 | +The final decision is not made, but will be fixed by the official release. |
| 177 | + |
| 178 | +## Other Notable New Features |
| 179 | + |
| 180 | +* A method reference operator, `.:`, was introduced |
| 181 | + as an experimental feature in earlier previews, but was reverted. |
| 182 | + [[Feature #12125]](https://bugs.ruby-lang.org/issues/12125), |
| 183 | + [[Feature #13581]]( https://bugs.ruby-lang.org/issues/13581), |
| 184 | + [[Feature #16275]](https://bugs.ruby-lang.org/issues/16275) |
| 185 | + |
| 186 | +* Numbered parameter as the default block parameter is introduced |
| 187 | + as an experimental feature. |
| 188 | + [[Feature #4475]](https://bugs.ruby-lang.org/issues/4475) |
| 189 | + |
| 190 | +* A beginless range is experimentally introduced. It might not be |
| 191 | + as useful as an endless range, but would be good for DSL purposes. |
| 192 | + [[Feature #14799]](https://bugs.ruby-lang.org/issues/14799) |
| 193 | + |
| 194 | + {% highlight ruby %} |
| 195 | + ary[..3] # identical to ary[0..3] |
| 196 | + rel.where(sales: ..100) |
| 197 | + {% endhighlight %} |
| 198 | + |
| 199 | +* `Enumerable#tally` is added. It counts the occurrence of each element. |
| 200 | + |
| 201 | + {% highlight ruby %} |
| 202 | + ["a", "b", "c", "b"].tally |
| 203 | + #=> {"a"=>1, "b"=>2, "c"=>1} |
| 204 | + {% endhighlight %} |
| 205 | + |
| 206 | +* Calling a private method on `self` is now allowed. |
| 207 | + [[Feature #11297]](https://bugs.ruby-lang.org/issues/11297), |
| 208 | + [[Feature #16123]](https://bugs.ruby-lang.org/issues/16123) |
| 209 | + |
| 210 | + {% highlight ruby %} |
| 211 | + def foo |
| 212 | + end |
| 213 | + private :foo |
| 214 | + self.foo |
| 215 | + {% endhighlight %} |
| 216 | + |
| 217 | +* `Enumerator::Lazy#eager` is added. |
| 218 | + It generates a non-lazy enumerator from a lazy enumerator. |
| 219 | + [[Feature #15901]](https://bugs.ruby-lang.org/issues/15901) |
| 220 | + |
| 221 | + {% highlight ruby %} |
| 222 | + a = %w(foo bar baz) |
| 223 | + e = a.lazy.map {|x| x.upcase }.map {|x| x + "!" }.eager |
| 224 | + p e.class #=> Enumerator |
| 225 | + p e.map {|x| x + "?" } #=> ["FOO!?", "BAR!?", "BAZ!?"] |
| 226 | + {% endhighlight %} |
| 227 | + |
| 228 | +## Performance improvements |
| 229 | + |
| 230 | +* JIT [Experimental] |
| 231 | + |
| 232 | + * JIT-ed code is recompiled to less-optimized code when an |
| 233 | + optimization assumption is invalidated. |
| 234 | + |
| 235 | + * Method inlining is performed when a method is considered as pure. |
| 236 | + This optimization is still experimental and many methods are |
| 237 | + NOT considered as pure yet. |
| 238 | + |
| 239 | + * The default value of `--jit-min-calls` is changed from 5 to 10,000. |
| 240 | + |
| 241 | + * The default value of `--jit-max-cache` is changed from 1,000 to 100. |
| 242 | + |
| 243 | +* ~~`Symbol#to_s`, `Module#name`, `true.to_s`, `false.to_s`, |
| 244 | + and `nil.to_s` now always return a frozen String. |
| 245 | + The returned String is always the same for a given object. |
| 246 | + [Experimental] |
| 247 | + [[Feature #16150]](https://bugs.ruby-lang.org/issues/16150)~~ reverted |
| 248 | + |
| 249 | +* The performance of `CGI.escapeHTML` is improved. |
| 250 | + [GH-2226](https://github.com/ruby/ruby/pull/2226) |
| 251 | + |
| 252 | +* The performance of Monitor and MonitorMixin is improved. |
| 253 | + [[Feature #16255]](https://bugs.ruby-lang.org/issues/16255) |
| 254 | + |
| 255 | +## Other notable changes since 2.6 |
| 256 | + |
| 257 | +* Some standard libraries are updated. |
| 258 | + * Bundler 2.1.0.pre.3 |
| 259 | + ([History](https://github.com/bundler/bundler/blob/2-1-stable/CHANGELOG.md#210pre3-november-8-2019)) |
| 260 | + * RubyGems 3.1.0.pre.3 |
| 261 | + ([History](https://github.com/rubygems/rubygems/blob/3.1/History.txt)) |
| 262 | + * CSV 3.1.2 |
| 263 | + ([NEWS](https://github.com/ruby/csv/blob/v3.1.2/NEWS.md)) |
| 264 | + * Racc 1.4.15 |
| 265 | + * REXML 3.2.3 |
| 266 | + ([NEWS](https://github.com/ruby/rexml/blob/v3.2.3/NEWS.md)) |
| 267 | + * RSS 0.2.8 |
| 268 | + ([NEWS](https://github.com/ruby/rss/blob/v0.2.8/NEWS.md)) |
| 269 | + * StringScanner 1.0.3 |
| 270 | + * Some other libraries that have no original version are also updated. |
| 271 | + |
| 272 | +* Promote stdlib to default gems |
| 273 | + * The following default gems were published on rubygems.org |
| 274 | + * benchmark |
| 275 | + * cgi |
| 276 | + * delegate |
| 277 | + * getoptlong |
| 278 | + * net-pop |
| 279 | + * net-smtp |
| 280 | + * open3 |
| 281 | + * pstore |
| 282 | + * singleton |
| 283 | + * The following default gems were only promoted at ruby-core, |
| 284 | + but not yet published on rubygems.org. |
| 285 | + * monitor |
| 286 | + * observer |
| 287 | + * timeout |
| 288 | + * tracer |
| 289 | + * uri |
| 290 | + * yaml |
| 291 | + |
| 292 | +* `Proc.new` and `proc` with no block in a method called with a block |
| 293 | + is warned now. |
| 294 | + |
| 295 | +* `lambda` with no block in a method called with a block errs. |
| 296 | + |
| 297 | +* Update Unicode version and Emoji version from 11.0.0 to 12.0.0. |
| 298 | + [[Feature #15321]](https://bugs.ruby-lang.org/issues/15321) |
| 299 | + |
| 300 | +* Update Unicode version to 12.1.0, |
| 301 | + adding support for U+32FF SQUARE ERA NAME REIWA. |
| 302 | + [[Feature #15195]](https://bugs.ruby-lang.org/issues/15195) |
| 303 | + |
| 304 | +* `Date.jisx0301`, `Date#jisx0301`, and `Date.parse` support the |
| 305 | + new Japanese era. |
| 306 | + [[Feature #15742]](https://bugs.ruby-lang.org/issues/15742) |
| 307 | + |
| 308 | +* Require compilers to support C99 |
| 309 | + [[Misc #15347]](https://bugs.ruby-lang.org/issues/15347) |
| 310 | + * Details of our dialect: |
| 311 | + <https://bugs.ruby-lang.org/projects/ruby-master/wiki/C99> |
| 312 | + |
| 313 | +* ~~`Regexp#match{?}` with `nil` raises TypeError as String, Symbol. |
| 314 | + [[Feature #13083]](https://bugs.ruby-lang.org/issues/13083)~~ reverted |
| 315 | + |
| 316 | +3895 files changed, 213426 insertions(+), 96934 deletions(-) |
| 317 | + |
| 318 | +See [NEWS](https://github.com/ruby/ruby/blob/v2_7_0_preview3/NEWS) |
| 319 | +or [commit logs](https://github.com/ruby/ruby/compare/v2_6_0...v2_7_0_preview3) |
| 320 | +for more details. |
| 321 | + |
| 322 | +With those changes, |
| 323 | +[stat](https://github.com/ruby/ruby/compare/v2_6_0...v2_7_0_preview3) |
| 324 | +since Ruby 2.6.0! |
| 325 | + |
| 326 | +Enjoy programming with Ruby 2.7! |
| 327 | + |
| 328 | +## Download |
| 329 | + |
| 330 | +{% assign release = site.data.releases | where: "version", "2.7.0-preview3" | first %} |
| 331 | + |
| 332 | +* <{{ release.url.bz2 }}> |
| 333 | + |
| 334 | + SIZE: {{ release.size.bz2 }} |
| 335 | + SHA1: {{ release.sha1.bz2 }} |
| 336 | + SHA256: {{ release.sha256.bz2 }} |
| 337 | + SHA512: {{ release.sha512.bz2 }} |
| 338 | + |
| 339 | +* <{{ release.url.gz }}> |
| 340 | + |
| 341 | + SIZE: {{ release.size.gz }} |
| 342 | + SHA1: {{ release.sha1.gz }} |
| 343 | + SHA256: {{ release.sha256.gz }} |
| 344 | + SHA512: {{ release.sha512.gz }} |
| 345 | + |
| 346 | +* <{{ release.url.xz }}> |
| 347 | + |
| 348 | + SIZE: {{ release.size.xz }} |
| 349 | + SHA1: {{ release.sha1.xz }} |
| 350 | + SHA256: {{ release.sha256.xz }} |
| 351 | + SHA512: {{ release.sha512.xz }} |
| 352 | + |
| 353 | +* <{{ release.url.zip }}> |
| 354 | + |
| 355 | + SIZE: {{ release.size.zip }} |
| 356 | + SHA1: {{ release.sha1.zip }} |
| 357 | + SHA256: {{ release.sha256.zip }} |
| 358 | + SHA512: {{ release.sha512.zip }} |
| 359 | + |
| 360 | +## What is Ruby |
| 361 | + |
| 362 | +Ruby was first developed by Matz (Yukihiro Matsumoto) in 1993, |
| 363 | +and is now developed as Open Source. It runs on multiple platforms |
| 364 | +and is used all over the world especially for web development. |
0 commit comments