The first release candidate of Ruby 2.4.0 was recently published. And the final release is scheduled for this week. We would like to share some of the features coming in this new minor version.

Enumerable#sum

Now it is possible to sum all the items of an Enumerable object.

[1, 2, 3, 4, 5].sum

=> 15

Enumerable#sum supports an initial value, which by default is 0 . When summing a collection of non-integer objects, you need to explicitly specify an initial value.

class Library

attr_accessor :books



def initialize(*books)

@books = books

end



def +(other)

dup.tap do |library|

library.books += other.books

end

end

end



ubik = Library.new('Ubik')

factotum = Library.new('Factotum') [factotum, ubik].sum

=> TypeError: Library can't be coerced into Integer



[factotum, ubik].sum(Library.new('The Man in the High Castle'))

=> #<Library:0x0055b1c4ad86a0 @books=["The Man in the High Castle", "Factotum", "Ubik"]>

Fixnum and Bignum unified into Integer

Fixnum and Bignum have been unified into Integer , getting a much more cleaner interface. Bignum objects hold values outside the range of Fixnum . At the moment, long numbers are automatically converted to Bignum when they are greater than 2**62-1 (or 2**30-1 in x86–32 archs).

# Ruby 2.3 (2**62-1).class

=> Fixnum (2**62).class

=> Bignum # Ruby 2.4 (2**62-1).class

=> Integer (2**62).class

=> Integer

This is one of the compatibility issues of this release. At Ruby level, both Fixnum and Bignum constants are bound to Integer , but some inconsistencies could happen:

# Ruby 2.3 Fixnum.ancestors

=> [Fixnum, Integer, Numeric, Comparable, Object, Kernel, BasicObject] Fixnum == Integer

=> false (2**64).is_a?(Fixnum)

=> false 1.is_a?(Bignum)

=> false # Ruby 2.4 Fixnum.ancestors

=> [Integer, Numeric, Comparable, Object, Kernel, BasicObject] Fixnum == Integer

=> true (2**64).is_a?(Fixnum)

(irb): warning: constant ::Fixnum is deprecated

=> true 1.is_a?(Bignum)

(irb): warning: constant ::Bignum is deprecated

=> true

Dir.empty? and File.empty?

Dir and File implement a new class method in order to check if a directory or a file is empty.

Dir.empty?('empty_dir')

=> true Dir.empty?('no_empty_dir')

=> false



File.empty?('empty_file.txt')

=> true File.empty?('file.txt')

=> false

Hash#compact

Ruby 2.4 also supports natively Hash#compact and its bang version. It performs ~25% better than Hash#compact ActiveSupport method.

{ foo: nil, bar: 'baz' }.compact

=> {:bar=>"baz"}

Hash#transform_values

Hash#transform_values ActiveSupport method and its destructive version have also been ported to Ruby 2.4. It performs a transformation to each hash value.

{ a: 1, b: 2, c: 3 }.transform_values { |x| x * 3 }

=> {:a=>3, :b=>6, :c=>9}

Unicode support for String methods #upcase, #downcase, #capitalize and #swapcase

String#upcase , String#downcase , String#capitalize and String#swapcase (and their bang variants) are no longer limited to ASCII characters.

'àbac'.upcase # Ruby 2.3 behaviour

=> 'àBAC' 'àbac'.upcase # Ruby 2.4 behaviour

=> 'ÀBAC'

Regexp#match?

Regexp#match? returns true or false whether the regular expression is matched. This method is much faster than any other, since it avoids creating a MatchData object or saving backref:

/hello/i.match?('Hello world!')

=> true $~

=> nil

Integer#digits

A place-value notation of an integer number can be extracted by using the new #digits method.

123.digits

=> [3, 2, 1]

The default radix is 10 . It accepts any other base as an argument. For example:

16.digits(2)

=> [0, 0, 0, 0, 1]

Array#min and Array#max

Ruby 2.4 Array defines its own #min and #max instance methods instead of using the Enumerable implementations. This notably increases the performance.

Net::HTTP.post

Net::HTTP standard lib introduces a new class method called post :

require 'net/http'

require 'uri'



Net::HTTP.post(URI('https://example.com/users'), body, headers)

… and much more. Check out the Ruby 2.4.0-rc1 changelog at GitHub.