Плюс он возвращает общее количество элементов во всех измерениях массива, поэтому он может быть массивом с «всего лишь» полумиллиардом элементов и 4 измерениями, чтобы сделать его необходимым 64-битным int.
instance_exec и class_exec - отличные новые функции , но для меня это в основном небольшие изменения (которые уже были перенесены на 1.8.7). Такие вещи, как Method # owner великолепны - когда-нибудь задумывались, где именно в цепочке наследования был определен конкретный метод? my_object.method (: blah) .owner скажет вам :)
В версии 1.9 мне больше всего нравится более последовательные правила области видимости, особенно. в контексте eval. Было глупым упущением (IMO), что константы и переменные класса не искались в instance_eval, 1.9 исправляет это :)
Полная встроенная поддержка многобайтовых кодировок символов, особенно Unicode.
Да и еще: это более чем в два раза быстрее. Еще быстрее, если вы создаете многопоточное приложение с большим количеством задержек ввода-вывода. Несмотря на всю работу, которую по-прежнему тратит на попытки повысить производительность из 1.8, исправить его многопоточность и т. Д., Меня удивляет, что людей не больше волнуют скорость 1.9 или его собственные потоки.
Мне лично нравится новый синтаксис хеширования: {: a => 1}
становится {a: 1}
Мне нравится Symbol # to_proc
, который избавляет вас от необходимости писать лямбду каждый раз, когда вы используете функцию высшего порядка. Итак, тогда как суммирование массива раньше было arr.inject (0) {| memo, val | memo + val}
, теперь вы можете просто написать arr.inject (&: +)
, а не homes.collect {| house | house.price}
, вы можете написать homes.collect (&: price)
.
Некоторые библиотеки (например, ActiveSupport) предоставляют те же функции в версии 1.8, но все же приятно, чтобы она была часть основного языка, а реализация 1.9 намного лучше оптимизирована, чем библиотечный подход.
Ruby 1.9 имеет другое поведение блока :
Параметры блока всегда локальны для своего блока, и вызовы блока никогда не присваивают значения существующим переменным:
Синтаксис блока был расширен, чтобы вы могли объявлять локальные переменные блока, которые гарантированно являются локальными, даже если переменная с таким же именем уже существует во включающей области.
Потоки также различны:
Ruby 1.8 использует только один собственный поток и запускает все потоки Ruby в этом одном собственном потоке. Это означает, что потоки очень легкие, но никогда не работают параллельно.
Ruby 1.9 отличается, он выделяет собственный поток для каждого потока Ruby. Но поскольку некоторые используемые библиотеки C не являются потокобезопасными,
Перечислители.
["a", "b", "c"].map {|elem, i| "#{elem} - #{i}" }
# => ["a - ", "b - ", "c - "]
["a", "b", "c"].each_with_index.map {|elem, i| "#{elem} - #{i}" }
# => ["a - 1", "b - 2", "c - 3"]
Перечислимые
методы возвращают экземпляр Перечислителя
, когда ему не передается ни один блок. В этом случае он используется для передачи map
аргумента index
, взятого из each_with_index
.
Это также было перенесено в 1.8.7.
Мне очень нравятся счетчики - не только для существующих типов, но и для написания моих собственных коллекций в виде классов Enumerator. После перехода на 1.9 мне дважды приходилось создавать адаптеры API для внешних веб-служб, которые извлекают большие наборы результатов JSON или XML. Иногда у меня было ограничение на количество записей, которые я мог получить за один раз, что означало, что мне приходилось выполнять несколько запросов. (Получите первые 500, затем получите записи с 501 по 1000 и т. Д.)
«Старый» способ I ' d, обработал бы их, означал бы получить первый пакет, перебрать все сразу с помощью .each
или .collect
и создать массив объектов Ruby равного размера. Если бы я не мог получить все записи в одном запросе, я бы также перебирал запросы API, каждый раз добавляя их в массив. Это означает, что все время загружается заранее, что воспринимается как медленное извлечение, и я поглощаю много памяти: для исходных данных, для равного количества объектов Ruby, а иногда и для промежуточных операции с массивами. Это расточительно, когда я, вероятно, работаю только с одним объектом за раз.
С помощью перечислителей я могу получить первую партию, сохранить исходные данные как свою «авторитетную» коллекцию, обработать и получить каждый объект Ruby , когда я вхожу в него . Когда я передаю последний элемент, если я знаю, что из источника нужно извлечь больше данных, тогда я могу сделать следующий вызов API. (То есть, отложенная загрузка.) Это означает более быстрый возврат при вызове метода извлечения и более эффективное использование памяти. Каждый объект Ruby имеет право на сборку мусора, как только я закончу с ним и перейду к следующему.
Абстрактная реализация идеи выглядит так:
class ThingyCollection < Enumerator
attr_reader :total
# Returns a new collection of thingies.
def initialize(options={})
# Make the request for the first batch
response = ThingyAPIClient.get_thingies(options)
@total = response.total # Number of ALL thingies, not just first batch
records = response.data # Some array of JSON/XML/etc. from the API
# Create a closure which serves as our enumerator code
enum = Proc.new do |yielder|
counter = 0 # Initialize our iterator
while counter < @total
# If we're at the end of this batch, get more records
if counter == records.length
more = ThingyAPIClient.get_next_thingies(counter, options)
records += more.data
end
# Return a Ruby object for the current record
yielder.yield Thingy.new(records[counter])
counter += 1
end
end
# Pass that closure to the Enumerator class
super(&enum)
end
end
Когда у вас есть это, вы можете перейти им нравится:
thingies = ThingyCollection.new(foo: bar) # Whatever search options are relevant
puts "Our first thingy is #{thingies.next}"
puts "Our second thingy is #{thingies.next}"
thingies.rewind
thingies.each do |thingy|
do_stuff(thingy)
end
Что вы теряете? В основном возможность легко перейти к определенному элементу по ссылке. (Это означает, что вы также теряете «последний», сортировки и т. Д.). Просто получение .next
и несколько вариантов .each
не так богаты, как функции массива, но для большинства общие варианты использования - это все, что мне нужно.
Да, вы можете сделать это с помощью Ruby 1.8.7 благодаря бэкпортингу. Но 1. 9 работает намного быстрее благодаря внутреннему использованию волокон. И если бы не 1.9, не было бы и 1.8.7, поэтому я решил, что она по-прежнему считается моей любимой функцией 1.9.
Ruby 1.9 Fibers предлагает новую мощную конструкцию параллелизма. Ruby Fibers: 8 полезных статей о новой функции параллелизма Ruby содержит ссылки на статьи, связанные с волокнами.
Улучшенная поддержка регулярных выражений. Ruby 1.9 поддерживает именованные группы регулярных выражений - среди многих других улучшений - которые вы можете вспомнить позже в своем регулярном выражении. Дэйв Томас приводит отличный пример .
YARV. Новая виртуальная машина Ruby в версии 1.9 предлагает новую современную виртуальную машину, которая значительно быстрее.
В идеале QA и тестировщики должны привлекаться если не с первого дня, то с самых ранних стадий проекта разработки программного обеспечения, независимо от используемого процесса (каскадный или гибкий). Команде тестирования необходимо:
Убедиться, что требования проекта или спринта ясны, измеримы и тестируемы. В идеальном мире на этом этапе для каждого требования должен быть записан критерий соответствия. Определите, какая информация должна автоматически регистрироваться для устранения неисправностей.
Подготовьте стратегию тестирования для конкретного проекта и определите, какие шаги по обеспечению качества потребуются и на каких этапах проекта: интеграция, стресс, совместимость, проникновение, соответствие, удобство использования, производительность, бета-тестирование и т. Д. Определите допустимые пороги дефектов и проработайте система классификации серьезности дефекта, укажите руководящие принципы для отчетов о дефектах.
Определите, упорядочите и подготовьте тестовую среду: тестовую инфраструктуру и имитирующие службы по мере необходимости; получать, обрабатывать и подготавливать данные испытаний; писать сценарии для быстрого обновления тестовой среды при необходимости; установить процессы отслеживания, связи и устранения дефектов; подготовиться к набору или нанять пользователей для бета-тестирования, тестирования юзабилити или приемочного тестирования.
Предоставьте всю необходимую информацию для формирования расписания проекта, структурной разбивки работ и плана ресурсов.
Напишите тестовые сценарии.
Приведите себя в норму. с предметной областью проблемы, системой AS-IS и предлагаемым решением.
Обычно это не вопрос о том, может ли группа тестирования внести какой-либо полезный вклад в проект на ранней стадии, или о том, является ли такой вклад полезным. Однако это вопрос, степени, в которой организация может позволить себе вышеупомянутую деятельность. Всегда существует компромисс между доступным временем, бюджетом и ресурсами по сравнению с уровнем известного качества конечного результата.
Это в точности противоположно тому, как это работало раньше: сначала был выпущен MRI, затем все другие разработчики прочитали (не очень хорошо спроектированный и, как правило, плохо документированный) исходный код MRI на языке C, чтобы попытаться выяснить, что, черт возьми, предполагалось, что эта новая функция будет реализована, затем они попытались написать исполняемые спецификации, и только тогда у них появился хотя бы отдаленный шанс на фактическую совместимость. Но к тому времени, как правило, новая версия YARV уже была выпущена, и цикл начался заново ... Не говоря уже о том, что разработчики MRI и YARV даже не запускали RubySpecs.
Это ] огромных разветвлений. Например, несмотря на то, что в настоящее время в активной разработке находится более десятка различных реализаций Ruby, и за годы его существования было создано более 30 различных реализаций языка программирования Ruby, этот факт не был признан разработчиками языка программирования Ruby. Для них Ruby и MRI (или в последнее время Ruby и YARV) всегда были одним и тем же: MRI был и языком, и механизмом выполнения, Ruby был одновременно механизмом выполнения и языком. «Спецификацией» языка программирования Ruby был исходный код MRI на C.
Пять недель назад это изменилось: теперь официальная спецификация языка программирования Ruby (по крайней мере, версия 1.9.2 и выше) это исполняемый набор тестов проекта RubySpec. И YARV - это просто еще одна реализация Ruby, полностью равная MacRuby, IronRuby, JRuby, Cardinal, tinyrb, SmallRuby, BlueRuby, MagLev и другие.
Это означает, что так называемые «альтернативные» реализации (которые на данный момент больше не следует называть «альтернативными», потому что YARV потерял свой особый статус) теперь имеют шанс фактически догнать последний язык. функции, реализованные в YARV. Фактически, поскольку большинство других реализаций на самом деле намного лучше спроектированы и реализованы на гораздо лучших языках, чем YARV (который в основном представляет собой огромный беспорядок из спагетти на C), а также имеют больше людей, вполне вероятно, что другие реализации действительно будут Ruby 1.9.2 совместим с до YARV.
потому что YARV утратил свой особый статус) теперь у вас есть шанс наверстать упущенное с последними языковыми функциями, реализованными в YARV. Фактически, поскольку большинство других реализаций на самом деле намного лучше спроектированы и реализованы на гораздо лучших языках, чем YARV (который в основном представляет собой огромный беспорядок из спагетти на C), плюс наличие большего количества людей, вполне вероятно, что другие реализации действительно будут Ruby 1.9.2 совместим с до YARV. потому что YARV утратил свой особый статус) теперь у вас есть шанс наверстать упущенное с последними языковыми функциями, реализованными в YARV. Фактически, поскольку большинство других реализаций на самом деле намного лучше спроектированы и реализованы на гораздо лучших языках, чем YARV (который в основном представляет собой огромный беспорядок из спагетти на C), а также имеют больше людей, вполне вероятно, что другие реализации действительно будут Ruby 1.9.2 совместим с до YARV.Ruby 1.9.2 поддерживает получение информации о параметрах метода. Вы можете получить имя параметров и информацию о них, например, необязательную, требуется или заблокировать.
См. Метод # params для примера.
Хеши заказываются в рубине 1.9. Это очень полезно при реализации некоторых алгоритмов. Вы должны полагаться на драгоценный камень или писать свой собственный упорядоченный хеш в Ruby 1.8.
Поддержка Unicode в 1.8 осуществляется через дополнительные драгоценные камни и доставила мне нескончаемую боль - было бы здорово получить для этого полную языковую поддержку. Некоторые люди жаловались на сложность реализации, но я думаю, они никогда не использовали ICU в C ++!
Кроме того, будет приятно иметь возможность сделать «Привет» [3]
и получить персонажа.
Некоторые тесты показали значительные улучшения по сравнению с 1.8.6, с 1.9.1 - благодаря новой виртуальной машине (YARV) в Ruby Матца
Если у вас есть копия "Programming Ruby" Дэйва Томаса (AKA The Pick-ax book), то раздел о встроенных классах и методах будет весьма полезен. работа по тегированию изменений с 1.8 на 1.9
Как насчет:
(a) новый синтаксис хеширования: {: hello => "world"} можно сократить до {: hello: "world "}
(б) упорядоченные хеши !!