Блог Ruby-разработчика

Что нового в Ruby 2.4?

| Comments

Скоро выйдет стабильный релиз Ruby 2.4. Ознакомимся что же нас ждет нового.

Float#round

Изменилось поведение метода round. Разработчики добавили возможность указать в какую сторону необходимо округлять, передав в этот метод дополнительный параметр :half, который может принимать значения: :even, :up, :down. Для примера:

1
2
(3.5).round(half: :up)
=> 4

Эти изменения касаются также таких методов как: floor, ceil, truncate. В них можно передать эту опцию.

IO#gets

Напомню что метод gets используется для получения пользовательского ввода в вашем скрипте. Вы наверняка использовали его в задачках по Ruby. Так вот, если пользователь вводил какие либо данные, к вам в результате приходила строка с переносом \n Чтобы его убрать использовался метод chomp. Теперь мы можем указать опцию chomp в методе gets

1
2
3
4
5
6
# 2.3
input_string = gets
=> 'tratata\n'
# 2.4
input_string = gets(chomp: true)
=> 'tratata'

Dir, File, Pathname #empty?

Поздравляю теперь мы можем передать путь в метод empty? и выяснить содержит ли папка/файл/путь что-то внутри Метод File.empty? эквивалентен методу File.zero?, который уже давно был в библиотеке для работы с файлами.

Hash#transform_values

Как по мне довольно удобный метод добавили в класс Hash. Теперь мы можем изменять значения hash в итераторе. Например вот так:

1
2
3
4
# 2.4
data = {x: 1, y: 2, z: 3}
data.transform_values{|value| value * 2 }
=> {x: 2, y: 4, z: 6}

Kernel#clone

При использовании clone или dup, можно теперь передать дополнительный аргумент, в котором указать будет ли объект freeze(недоступным для изменения).

1
2
3
4
5
6
# 2.4
frozen_string = "frozen".freeze
dup = frozen_string.clone(freeze: false)

dup.frozen?
=> false

Binding#irb

Есть такой замечательный gem pry. Достаточно в любом месте кода поместить binding.pry и у вас появляется возможность использовать консоль pry для дебага вашего приложения. В Ruby 2.4 добавлена похожая фича, только нужно указать binding.irb.

Regexp#match?

Для регулярок добавили новый метод match? который работает аж в 3 раза быстрее чем методы match, ===, =~. При использовании медленных методов, руби создавал объект класса MatchData, а в новом методе он не создается, за счет этого повышенная скорость работы.

1
2
3
4
5
6
7
8
/^foo (\w+)$/ =~ 'foo bar'      # => 0
                                # => #<MatchData "foo bar" 1:"bar">

/^foo (\w+)$/.match('foo baz')  # => #<MatchData "foo baz" 1:"baz">
                                # => #<MatchData "foo baz" 1:"baz">

/^foo (\w+)$/ === 'foo qux'     # => true
                                # => #<MatchData "foo qux" 1:"qux">
1
2
3
# 2.4
/^foo (\w+)$/.match?('foo wow') # => true
                                # => nil

Regexp#named_captures

Довольно забавная фича. Позволяет сделать именованные группы в регулярном выражении, и в последствии преобразовать это все в hash с результатами. Лучше один раз увидеть.

1
2
3
# 2.4
pattern = /(?<name1>\w+) (?<name2>\w+)/
pattern.match('Herr Kresken').named_captures # => { "name1" => "Herr", "name2" => "Kresken" }

Также для похожих целей можно использовать метод values_at, который также теперь можно применять к отматченному результату

1
2
3
# 2.4
pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
pattern.match('2016-02-01').values_at(:year, :month) # => ["2016", "02"]

Кроме именованных ключей, вы можете передать индексы групп, например 1, 3

1
2
3
# 2.4
pattern = /(\d{4})-(\d{2})-(\d{2})$/
pattern.match('2016-07-18').values_at(1, 3) # => ["2016", "18"]

Integer#digits

Как получить массив чисел составляющих число? Раньше это можно было сделать так Преобразовать число в строку, вызвать метод chars, через map сделать to_i

1
123.to_s.chars.map(&:to_i).reverse # => [3, 2, 1]

Теперь стало проще:

1
2
# 2.4
123.digits                  # => [3, 2, 1]

Array#min, max

Array класс обзавелся своими методами min, max, который работают практически в 2 раза быстрее чем соответствующие методы Enumerable

Обьединение Bignum Fixnum в Integer

Довольно серьезное изменение структуры языка. В Ruby 2.4 убрали классы Fixnum и Bignum и объединили их в один Integer

1
2
3
4
5
# 2.3:
numerics # => [Complex, Rational, Bignum, Float, Fixnum, Integer, BigDecimal]

# 2.4:
numerics # => [Complex, Rational, Float, Integer, BigDecimal]

Использование в условиях мультиприсвоения

Теперь в условиях можно использовать множественное присвоение

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2.4
branch1 =
  if (foo, bar = %w[foo bar])
    'true'
  else
    'false'
  end

branch2 =
  if (foo, bar = nil)
    'true'
  else
    'false'
  end

branch1 # => "true"
branch2 # => "false"

Заключение

Неплохие добавочки в язык, точно знаю что использовал бы transform_values, недавно был случай когда нужно было проверить папку на наличие в ней файлов, здесь бы пригодился метод empty?. Вижу применение для named_captures. Остальное также может пригодиться, но лично для меня реже. Помимо добавления функционала были улучшения производительности. Но это уже совсем другая история. На этом все. Подписывайтесь на канал, скоро выйдет новая порция уроков. Добавляйте в закладки

Ссылки к статье

ruby, ruby-2.4

« В чем разница между load и require, include и extend Демонический Linux »

Comments