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

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

Совсем скоро выйдет релиз Ruby 2.3.0, а пока доступен пререлиз под номером 1. Давайте посмотрим что новенького появилось.

Ставим ruby 2.3.0-preview1 через rvm, либо rbenv

1
2
3
4
5
6
# RVM
rvm install 2.3.0-preview1

# Rbenv
brew upgrade ruby-build --HEAD
rbenv install 2.3.0-preview1

~ Safe navigation operator ~

Появился новый оператор - &.. В Ruby on Rails есть замечательный метод try!, так вот этот оператор имеет схожую функциональность. Он выполняет проверку на nil до вызова метода у обьекта и возвращает его в случае если сам nil, в противном случае вызывается метод после оператора.

1
2
3
4
5
6
7
8
9
# Ruby <= 2.2
puts "User Admin" if user && user.admin?

# Ruby 2.3
puts "User Admin" if user&.admin?

# Important
user = false
user&.admin? # raise NoMethodError

Но будьте внимательны, если user у вас будет например false, то вы получите NoMethodError

~ Frozen string literals ~

До Ruby 2.2 строки были изменяемые, т.е мы могли взять и сделать что-то подобное str[1] = 'a'. Если нам было необходимо запретить изменение строки, то с помощью метода #freeze это прекрасно получалось

Планируется использование неизменных строк по умолчанию в Ruby 3.0, разработчики хотят увеличить производительность языка, уменьшив количество обьектов в памяти. В версии 2.3 можно включить этот режим, для этого в начало файла нужно поместить комментарий # frozen_string_literal: true

1
2
3
4
5
6
7
# frozen_string_literal: true

str = 'cat'
str[0] = 'b'

# frozen.rb:5:in `[]=': can't modify frozen String (RuntimeError)
#   from frozen.rb:5:in `<main>'

~ Array#dig и Hash#dig ~

Небольшие дополнения к стандартным библиотекам, которые позволяют выполнять такие вещи:

1
2
3
4
5
6
7
8
9
10
list = [
  [2, 3],
  [5, 7, 9],
  [ [11, 13], [17, 19] ]
]

list.dig(1, 2)    #=> 9
list.dig(2, 1, 0) #=> 17
list.dig(0, 3)    #=> nil
list.dig(4, 0)    #=> nil
1
2
3
4
5
6
7
8
9
dict = {
  a: { x: 23, y: 29 },
  b: { x: 31, z: 37 }
}

dict.dig(:a, :x) #=> 23
dict.dig(:b, :z) #=> 37
dict.dig(:b, :y) #=> nil
dict.dig(:c, :x) #=> nil

~ Did you mean? ~

Появилась удобная вещь, в виде подсказки, которая предлагает вам варианты правильного вызова метода, если вы вдруг опечатались

1
2
3
4
5
2.3.0-preview1 :001 > "string".downcaze

NoMethodError: undefined method `downcaze' for "string":String
Did you mean?  downcase
               downcase!

~ Сравнение Hash ~

Теперь можно сравнивать hash. Вот таким образом

1
2
3
{ x: 1, y: 2 } >= { x: 1 } #=> true
{ x: 1, y: 2 } >= { x: 2 } #=> false
{ x: 1 } >= { x: 1, y: 2 } #=> false

Также можно применять и другие операторы сравнения, более подробно здесь

~ Hash#to_proc ~

Hash можно преобразовать в proc обьект, причем вызвав у proc ключ из Hash вы получите значение

1
2
3
4
5
6
h = { foo: 1, bar: 2, baz: 3}
p = h.to_proc

p.call(:foo)  #=> 1
p.call(:bar)  #=> 2
p.call(:quux) #=> nil

Иногда приходится для получения определенных значений из Hash использовать сложную конструкцию, с использованием & это немного упрощается

1
2
3
4
5
6
7
h = { foo: 1, bar: 2, baz: 3}

# bad:
[:foo, :bar].map { |key| h[key] } #=> [1, 2]

# good:
[:foo, :bar].map(&h) #=> [1, 2]

~ Hash#fetch_values ~

Новый метод похож по своей функциональности на Hash#values_at. Он позволяет получить значения по списку ключей. Отличие fetch_values в том, что если ключа не найдется, то будет брошен exception KeyError, вместо возвращения nil, как это реализовано в values_at

1
2
3
4
5
h = { foo: 1, bar: 2, baz: 3}
h.fetch_values(:foo, :bar) #=> [1, 2]

h.values_at(:foo, :quux)    #=> [1, nil]
h.fetch_values(:foo, :quux) #=> raise KeyError

~ Enumerable#grep_v ~

Если вы знакомы с утилитой grep в linux системах, то в случае если мы применим опцию -v в вызове этой консольной утилиты, то в результате выполнения этой команды print "test" | grep t test -v мы ничего не получим на выходе. Эта опция позволяет вывести то что не подошло, т.е. она противоположна grep

1
2
3
4
5
6
7
list = %w(foo bar baz)

list.grep_v(/ba/)
#=> ['foo']

list.grep(/ba/)
#=> ['bar', 'baz']

~ Numeric#positive? и #negative? ~

Добавилось несколько методов из Rails. Названия интуитивно понятны, можно обойтись без примеров

Ссылки

https://www.ruby-lang.org/en/news/2015/11/11/ruby-2-3-0-preview1-released/

ruby, ruby-2.3

Comments