📜 ⬆️ ⬇️

What can we expect from Ruby 2.1?

A few days ago, Konstantin Haase, one of the key people in the Ruby community, posted an entry in his blog about the preview version of Ruby 2.1. Changes between versions 2.0 and 2.1 have accumulated enough to read into his presentation, and better in Russian.

NB: Of course, Ruby 2.1 contains all the great features of the previous version - 2.0. Changes from previous versions will not be mentioned.

Refinement mechanism


It is known that the refinement engine is introduced in Ruby 2.0. The implementation of this mechanism turned out to be rather inconsistent, therefore, in version 2.0, its functionality was somewhat limited and marked as experimental.

It is worth recalling that the refinements allow you to apply decoys patches in a single Ruby file:
')
module Foo refine String do def foo self + "foo" end end end using Foo puts "bar".foo 

Outside this file, instances of the String class will not respond to the foo method.

In the new version of Ruby, updates will not be an experimental feature. Moreover, they can be applied not only to the top-level scope, but also to individual modules.

 module Foo refine String do def foo self + "foo" end end end module Bar using Foo puts "bar".foo end 

It is important to keep in mind that overreliance on clarifications may lead to the writing of rather confusing code. The developers of some implementations of Ruby have already stated that they may refuse to support the refinement.

Decimal Literals


When working with Ruby, you can see that the floating-point values ​​do not behave in the best way when they are performed on calculations that are familiar with working with decimal fractions:

 irb(main):001:0> 0.1 * 3 => 0.30000000000000004 

This behavior leads to the fact that a large number of Ruby-developers begin to use whole numbers, imitating a given number of decimal places when presenting the result. Of course, this method works well with a strictly specified number of decimal places. Otherwise, you have to use rational fractions - this is not very bad, but the language does not have a sufficiently convenient syntax to work with them.

The new version of Ruby introduces the r suffix to describe decimal and rational fractions:

 irb(main):001:0> 0.1r => (1/10) irb(main):002:0> 0.1r * 3 => (3/10) 

Immune strings


If the code contains a string declaration, then each time the line containing the code is executed, Ruby creates a new object of the String class. This is due to string mutability . In such cases, characters behave much more efficiently, since they are initialized only once. However, to compare a character with a string, you need to convert a string to a symbol or a character to a string. Performing such transformations is a risky operation, opening up the potential for a DoS attack, since the characters are not released during garbage collection, and any character-to-string conversion creates a new string.

The only way to protect yourself from negative consequences in this case is to store and use the string as a constant:

 class Foo BAR = "bar" def bar?(input) input == BAR end end 

Often, to get rid of mutability, perform line freezing. Freezing the object prevents it from being modified by the Ruby code, but does not give any performance gains:

 class Foo BAR = "bar".freeze def bar?(input) input == BAR end end 

It looks quite ridiculous and cumbersome. Fortunately, Ruby 2.1 offers a new syntax for solving this problem:

 class Foo def bar?(input) input == "bar"f end end 

In the above code, an immutable String object will be created, and wherever it is used, it will be initialized only once.

It is possible that this syntax may seem strange. The same code snippet can be rewritten equivalently:

 class Foo def bar?(input) input == %q{bar}f end end 

In general, the question of applying the suffix f to arrays and hashes remains open.

Mandatory Key Arguments


For some reason, the obligatory key arguments were not mentioned in the announcement of Ruby 2.0. So Ruby 2.0 introduces the required key arguments:

 def foo(a: 10) puts a end foo(a: 20) # 20 foo # 10 

With this approach to declaring methods, you have to specify the default values ​​of the arguments. This is not always possible, so Ruby 2.1 allows you to specify the required key arguments:

 def foo(a:) puts a end foo(a: 20) # 20 foo # ArgumentError: missing keyword: a 

Method declaration returns method name


In previous versions of Ruby, a method declaration with def returned nil .

 def foo() end # => nil 

Now this behavior has changed and the method name is returned as a symbol:

 def foo() end # => :foo 

This is useful for metaprogramming and performing such tricks. For example, does everyone know that the private method can take arguments?

 #     foo class Foo def foo end private :foo #  bar   def bar end end 

Now, when def returns the name of the declared method, you can easily make the methods private:

 #     foo  bar class Foo private def foo end private \ def bar end def baz end end 

Remove extra bytes from strings


Ruby now has a convenient method for removing extra bytes from strings:

 some_string.scrub("") 

It used to be difficult to achieve the same behavior of this method for all existing Ruby implementations, so a library is also available for this.

StringScanner supports named captures


Many people like the StringScanner class from the standard language library. In particular, it is used in Rails to parse route patterns. Sinatra 2.0 will do the same.

In version 1.9, support for named captures was added, but StringScanner did not support them:

 require 'strscan' s = StringScanner.new("foo") s.scan(/(?<bar>.*)/) puts s[:bar] 

In Ruby 2.0, this code will throw an exception:

 TypeError: no implicit conversion of Symbol into Integer 

But when launched on Ruby 2.1, everything will be fine:

 foo 

Work with network interfaces


You can now access network interfaces using the Socket.getifaddrs method:

 require 'socket' Socket.getifaddrs.each do |i| puts "#{i.name}: #{i.addr.ip_address}" if i.addr.ip? end 

An example of the output of such a program:

 lo0: fe80::1%lo0 lo0: 127.0.0.1 lo0: ::1 en0: fe80::1240:f3ff:fe7e:594e%en0 en0: 192.168.178.30 en2: fe80::3e07:54ff:fe6f:147a%en2 

Quick work with numbers for computational tasks


Ruby 2.1 behaves faster when working with large numbers by using 128-bit integers as the internal representation of Bignum objects. Moreover, the use of the GNU Multiple Precision Arithmetic Library provides an additional boost to performance.

Changes in the virtual machine


Now the Ruby virtual machine, along with the use of the global method cache, performs caching at the place of the function call . There are separate slides about it.

Rgenc


The new version of Ruby uses a new generational generation of garbage . Due to this, garbage collection will be faster. Prior to this, a conservative garbage collector was used, which operates according to the “stop the world - mark - sweep” scheme.

In fact, the old collector has not disappeared anywhere. Such things are difficult to change due to the characteristics of the internal and external Ruby C program interface.

However, the Ruby 2.1 virtual machine classifies objects into light and dark . Depending on the assigned class, the behavior of the garbage collector is determined. There are operations that make a bright object dark . For example, working with it from an extension in the C language. Objects such as open files are dark initially.

The new garbage collector works only with light objects.

RubyGems Update


RubyGems received an upgrade to version 2.2.0, which brings several minor improvements.

Nothing is eternal


Do not forget that the recent release is only a preliminary version, and all of the above may change.

Source: https://habr.com/ru/post/195844/


All Articles