Большая часть фанфар вокруг Ruby 2.2 была посвящена обновлениям сборки мусора (GC). GC теперь будет очищать символы и имеет новый инкрементный алгоритм, который сокращает время паузы. Эти изменения очень интересны, но были добавлены и новые методы. Посмотрим, какие еще новые игрушки поставлены 2.2.
Связывание # local_variables
Если вы когда-нибудь хотели узнать локальные переменные, определенные в области видимости, у меня есть метод для вас. Вставьте это куда угодно и узнайте, какие переменные используются:
def addition(x, y) puts binding.local_variables.inspect z = x + y puts binding.local_variables.inspect z end > addition(2, 3) [😡, :y, :z] [😡, :y, :z] 5
Binding # приемник
Может быть, вы не заботитесь о местных переменах. Вы хотите знать, какой объект получает вызов метода?
class Cat def self.type binding.receiver end end > Cat.type Cat class Tiger < Cat end > Tiger.type Tiger
Большинство из нас напрямую не имеют дело с привязками, но если вы занимаетесь жизнью, вам стало немного легче.
Dir # fileno
Получение дескриптора файла для объекта IO
не является чем-то новым. Теперь вы можете получить его и для каталога. Файловые дескрипторы — это способ ссылки на определенный открытый файл, каталог и т. Д. Вы, вероятно, использовали их раньше, даже не осознавая этого. В системах POSIX 0, 1 и 2 зарезервированы для стандартного входа, стандартного выхода и стандартной ошибки соответственно.
Вы когда-нибудь использовали что-то вроде 2>&1
в командной строке? Вы ссылались на дескрипторы файлов.
> $stdout.fileno 1 > Dir.new('.').fileno 8
Имейте в виду, этот новый метод доступен только в системах POSIX. Если вы попытаетесь вызвать его в Windows, он NotImplementedError
.
Перечислимых # slice_after
Этот метод является дополнением к существующему методу slice_before
. Я не сталкивался с slice_before
в дикой природе, поэтому мне пришлось посмотреть, как это работает.
Как следует из названия, slice_before
используется для slice_before
кубиков. Учитывая способ сопоставления элемента в перечисляемом, он найдет совпадение и разделит его на части непосредственно перед совпадением:
> [1, 'a', 2, 'b', 'c', 3, 'd', 'e', 'f'].slice_before { |e| e.is_a?(Integer) }.to_a [[1, "a"], [2, "b", "c"], [3, "d", "e", "f"]]
В этом случае он делал сокращения перед целыми числами 1
, 2
и 3
.
Аргумент может быть передан вместо блока. Когда это происходит, аргумент проверяется с помощью ===
(т. Е. Равенство регистра). Мы можем получить тот же результат, что и выше, передав Integer
:
> [1, 'a', 2, 'b', 'c', 3, 'd', 'e', 'f'].slice_before(Integer).to_a [[1, "a"], [2, "b", "c"], [3, "d", "e", "f"]]
Хотите угадать, что делает slice_after
? Вместо нарезки перед матчем, он нарезает после:
> [1, 'a', 2, 'b', 'c', 3, 'd', 'e', 'f'].slice_after(Integer).to_a [[1], ["a", 2], ["b", "c", 3], ["d", "e", "f"]]
Перечислимых # slice_when
Особенно забавным дополнением является slice_when
. В отличие от slice_after
, этот метод принимает только блок. Он перебирает перечисляемые пары элементов в блок. Когда блок возвращает true
, перечислимое разделяется между парой элементов:
> [1, 3, 4, 5, 7, 8, 9, 10, 12].slice_when { |a, b| a + 1 != b }.to_a [[1], [3, 4, 5], [7, 8, 9, 10], [12]]
Здесь мы нашли серии последовательных чисел, разрезая их, когда второе число не является первым числом плюс один.
Учитывая массив чисел, вы можете легко узнать, сколько у вас каждого:
> Array.new(10) { rand(3) + 1 }.sort.slice_when(&:!=).map { |x| [x.first, x.size] } [[1, 4], [2, 4], [3, 2]]
В этом заезде мы получили 1
четыре раза, 2
четыре раза и 3
раза.
Float # next_float, Float # prev_float
Эти функции возвращают следующее или предыдущее представимое число с плавающей точкой. Обратите внимание на слово « представимое » в этом предложении, не все числа могут быть представлены.
> 1.0.next_float 1.0000000000000002
Обратите внимание, как пропустили 1.0000000000000001
? Он не может быть представлен с помощью Float
:
> 1.0000000000000001 1.0
Также стоит отметить, что расстояние между двумя шагами не всегда одинаково:
> 2.0.prev_float 1.9999999999999998 > 2.0.next_float 2.0000000000000004
Очевидно, что подобные методы полезны для поиска значений ULP и выполнения других действий, которые вы, скорее всего, никогда не сделаете. Они могут быть не самыми полезными в глобальном масштабе методами, но если они вам понадобятся, вы будете рады, что они есть.
File.birthtime, File # birthtime, File :: Stat # birthtime
У нас были atime
, ctime
и mtime
чтобы проверить различные времена доступа и изменения, связанные с файлом. До 2.2 у нас не было времени рождения (т.е. времени создания) файла. Вы заметите, что он, как и другие, поставляется в классах и экземплярах:
> File.new('test', 'w').birthtime 2015-01-06 19:24:44 -0600 > File.birthtime('test') 2015-01-06 19:24:44 -0600
Также доступно в File::Stat
:
> File::Stat.new('test').birthtime 2015-01-06 19:24:44 -0600
Само ядро #
Руби вышла и получила метод идентификации. Для тех, кто не знаком, метод идентификации возвращает объект, к которому он обращался:
> 1.itself 1
В этот момент вам может быть интересно, где это полезно. Одним из наиболее распространенных примеров является группировка:
> [2, 3, 3, 1, 2, 3, 3, 1, 1, 2].group_by(&:itself) {2=>[2, 2, 2], 3=>[3, 3, 3, 3], 1=>[1, 1, 1]}
Он также может быть использован как способ не использовать метод, такой как map
или select
. В функциональном программировании это может быть хорошим способом избежать того, что в противном случае может быть неудобным условием.
Метод # Карри
Возможно, вы не поняли, что Ruby способен к карри и частичному применению. В прошлом вы могли вызывать curry
только на Proc
. Эта же сила теперь доступна вам на Method
.
def sum(*args) args.reduce(:+) end > inc = method(:sum).curry(2).(1) #<Proc:0x007ff68ac96728 (lambda)> > inc.(3) 4
Метод # super_method
Ранее мы нашли объект, получающий метод с binding.receiver
. Мы также можем узнать о родителе метода. Вызов super_method
возвращает метод, который вы получили бы, если бы вы вызвали super
. Если у метода нет родителя, он возвращает nil
.
class Cat def speak 'meow' end end class Tiger < Cat def speak 'roar' end end > Tiger.new.method('speak') #<Method: Tiger#speak> > Tiger.new.method('speak').super_method #<Method: Cat#speak> > Cat.new.method('speak').super_method nil
String # unicode_normalize, String # unicode_normalize !, String # unicode_normalized?
Знаете ли вы, что в Unicode некоторые символы могут быть представлены несколькими способами? Взять, к примеру, «е» с острым акцентом. Вы можете представить его с помощью канонической композиции (NFC) формы нормализации, используя одну кодовую точку:
> nfc = "\u{e9}" "é"
Вы также можете представить его с помощью формы нормализации канонического разложения (NFD), комбинируя две кодовые точки:
> nfd = "\u{65}\u{301}" "é"
В этой форме обычное «е» в сочетании с «◌́» создает «é», которое вы видите выше. Хотя эти два могут давать похожий результат, они не одинаковы:
> nfc == nfd false
unicode_normalize
выполняет преобразование строк из одной формы в другую. По умолчанию он конвертируется в NFC:
> nfc == nfd.unicode_normalize true
Вы также можете передать символ, указывающий форму для преобразования в:
> nfc.unicode_normalize(:nfd) == nfd true
Эти формы существуют, потому что они имеют ценность в разных ситуациях. Коды NFC короче, но если вы хотите убрать акценты из слова для, скажем, целей поиска, форму NFD будет легче обрабатывать. Хотя NFC и NFD являются наиболее распространенными, вы также можете передать :nfkc
и :nfkd
если необходимо.
Ударная версия этого делает то, что вы ожидаете, и изменяет строку, получающую сообщение.
Вызов unicode_normalized?
проверяет, соответствует ли строка нужной форме. Он принимает тот же аргумент, что и unicode_normalize
:
> nfc.unicode_normalized? true > nfc.unicode_normalized?(:nfd) false
Время уточнять
Многие из этих методов не каждый день инструменты. Это постепенные улучшения, которые поддерживают язык. За последние несколько лет в Ruby произошли большие изменения. Изменения между 1.8, 1.9 и 2.0 выпусками были монументальными. Теперь язык сфокусирован на уточнении некоторых грубых граней, созданных этим процессом. Фактически, 2.2 позволяет вам создавать ключи символов в кавычках в хешах с конечным двоеточием:
{ 'programming-language': :ruby }
Больше не должно быть хэшей с символьными ключами с добавленной случайной ракетой из-за дефисного атрибута HTML. Я думаю, это то, что мы все можем отстать.