Новое в Ruby 2.1
Хотя релиз Ruby 2.1 еще не выпущен, а лишь планируется 25.12.2013, но уже известны новые возможности, улучшения, изменения в синтаксисе.
25.12.2013 как всегда точно в срок был выпущен релиз Ruby 2.1.0
Естественно, Ruby 2.1 сохраняет все новшества Ruby 2.0.
Refinements
(refinement – усовершенствование, улучшение)
Механизм Refinements был добавлен в Ruby 2.0, но функциональность была ограничена, и механизм был определен как экспериментальный.
Refinements позволяют применять "monkey patches" только в единственном файле Ruby:
module Foo refine String do def foo self + "foo" end end end using Foo puts "bar".foo #=> barfoo
Вне этого файла в String
по прежнему нет метода foo
.
В Ruby 2.1, refinements уже не эксперементальный механизм и может быть использован также внутри модуля (module
) без влияния на глобальное пространство имен в самом файле.
module Foo refine String do def foo self + "foo" end end end module Bar using Foo puts "bar".foo #=> barfoo end
Следует обратить внимание на то, что использование refinements может привести к тому, что получается очень запутывающий код, и поэтому, разработчики предыдущих реализаций Ruby уже указали на что, что они вряд ли будут использовать этот механизм.
Десятичные литералы (Decimal Literals)
Вам, должно быть известно, что числа с плавающей запятой (floats) далеки от идеала при выполнении вычислений с числами с фиксированной десятичной точкой:
0.1 * 3 #=> 0.30000000000000004
Многие разработчики Ruby используют фиксированную точность (количество знаков после запятой) при отображении результата. Однако, это работает хорошо, только если Вы действительно работаете с числами с фиксированной десятичной точкой. В противном случае Вы должны использовать рациональные величины. Совсем не плохо, за исключением того, что не было никакого приемлемого синтаксиса для них (за исключением изменения возвращаемого значения метода Integer#/
).
В Ruby 2.1 вводится суффикс r для decimal/rational литералов:
0.1r #=> (1/10) 0.1r * 3 #=> (3/10)
"Замороженные" строковые литералы
Когда в Вашем коде появляется строковый литерал, Ruby создает новый строковый литерал каждый раз, когда строка кода выполняется. Это происходит потому, что строки в Ruby непостоянны. Это объясняет, почему обозначения (symbol
) более эффективны во многих случаях. Однако, обозначения не строки. Например, если Вы хотите сравнить некоторый ввод данных пользователем с обозначением, Вы должны или преобразовать символ в строку, или строку к обозначению. Это означает, что Вы либо открываете свой код для атаки "отказ в обслуживании", поскольку обозначения не обработаны сборщиком "мусора", либо снова расходуются ресурсы на создание строк.
Один из способов состоит в том, чтобы сохранить строку в константе и затем использовать эту константу вместо строкового литерала:
class Foo BAR = "bar" def bar?(input) input == BAR end end
Сейчас для предотвращения изменения строкового литерала применяется "заморозка", но к сожалению это не дает преимущества в производительности:
class Foo BAR = "bar".freeze def bar?(input) input == BAR end end
Это может стать утомительным. К счастью, Ruby 2.1 представляет синтаксис, делающий что-то эквивалентное "под капотом" (автоматически):
class Foo def bar?(input) input == "bar"f end end
Это код создаст "замороженный" строковый объект один раз и затем снова использует его каждый раз, когда код выполняется.
Вероятно, может показаться, что этот синтаксис выглядит несколько странно. Обоснование заключается в том, что это работает как суффикс для десятичного числа, объясненный выше. Есть прием, который позволяет оформить код несколько иначе:
class Foo def bar?(input) input == %q{bar}f end end
Хотя этот вариант мне лично кажется еще более корявым.
Есть нерешенный вопрос, предлагающий добавить этот суффикс также к массивам и хешам.
Обязательные именованные аргументы
В Ruby 2.0 были добавлены именованные аргументы методов. Однако, именованные аргументы всегда должны иметь значение по умолчанию, соответственно, могут быть пропущены при вызове метода. В Ruby 2.1 теперь возможно указать обязательные именованные аргументы:
def foo(a:) puts a end foo(a: 20) #=> 20 foo # ArgumentError: missing keyword: a
Определение метода возвращает имя метода
В предыдущих версиях Ruby, определение метода с помощью def
возвращает nil
:
def foo() end #=> nil
В Ruby 2.1 сейчас возвращается наименование метода в виде обозначения (symbol
):
def foo() end #=> :foo
Это полезно для метапрограммирования и других подобных техник. Например, Вы знали, что private
также может быть вызван с параметрами?
# только foo будет закрытым методом class Foo def foo end private :foo # bar по прежнему будет открытым def bar end end
Теперь, когда определение метода возвращает имя, это может использоваться, чтобы сделать единственный метод закрытым:
# только foo и bar будут закрытыми class Foo private def foo end private \ def bar end def baz end end
Удаление "мусорных" байтов из строк
Ruby теперь обладает удобным методом, чтобы удалить "байты мусора" из строк:
some_string.scrub("")
Доступ к сетевым интерфейсам
Теперь возможно получить доступ к сетевым интерфейсам через Socket.getifaddrs
:
require 'socket' Socket.getifaddrs.each do | i | puts "#{i.name}: #{i.addr.ip_address}" if i.addr.ip? end
Более быстрые числа для серьезной математики
Ruby 2.1 теперь быстрее, когда дело доходит до больших чисел, поскольку используются 128-битные целые числа. Получено дополнительное увеличение скорости при помощи библиотеки GNU Multiple Precision Arithmetic Library.