Чтение онлайн

на главную

Жанры

Программирование на языке Ruby
Шрифт:

Стандартный итератор для любого объекта называется

each
. Это существенно отчасти из-за того, что позволяет использовать цикл
for
. Но итераторам можно давать и другие имена и применять для разных целей.

В качестве примера рассмотрим многоцелевой итератор, который имитирует цикл с проверкой условия в конце (как в конструкции

do-while
в С или
repeat-until
в Pascal):

def repeat(condition)

 yield

 retry if not condition

end

В этом примере ключевое слово

yield
служит для вызова блока, который задается при таком вызове итератора:

j=0

repeat (j >= 10) do

 j += 1

 puts j

end

С помощью

yield
можно также передать параметры, которые будут подставлены в список параметров блока (между вертикальными черточками). В следующем искусственном примере итератор всего лишь генерирует целые числа от 1 до 10, а вызов итератора порождает кубические степени этих чисел:

def my_sequence

 for i in 1..10 do

yield i

 end

end

my_sequence {|x| puts x**3 }

Отметим, что вместо фигурных скобок, в которые заключен блок, можно написать ключевые слова

do
и
end
. Различия между этими формами есть, но довольно тонкие.

1.2.7. Исключения

Как и многие другие современные языки, Ruby поддерживает исключения.

Исключения — это механизм обработки ошибок, имеющий существенные преимущества по сравнения с прежними подходами. Нам удается избежать возврата кодов ошибок и запутанной логики их анализа, а код, который обнаруживает ошибку, можно отделить от кода, который ее обрабатывает (чаще всего они так или иначе разделены).

Предложение

raise
возбуждает исключение. Отметим, что
raise
— не зарезервированное слово, а метод модуля
Kernel
. (У него есть синоним
fail
.)

raise # Пример 1

raise "Произошла ошибка" # Пример 2

raise ArgumentError # Пример 3

raise ArgumentError, "Неверные данные" # Пример 4

raise ArgumentError.new("Неверные данные ") # Пример 5

raise ArgumentError, " Неверные данные ", caller[0] # Пример 6

В первом примере повторно возбуждается последнее встретившееся исключение. В примере 2 создается исключение

RuntimeError
(подразумеваемый тип), которому передается сообщение
"Произошла ошибка"
.

В примере 3 возбуждается исключение типа

ArgumentError
, а в примере 4 такое же исключение, но с сообщением
"Неверные данные"
. Пример 5 — просто другая запись примера 4. Наконец, в примере 6 еще добавляется трассировочная информация вида
"filename:line"
или
"filename:line:in 'method'"
(хранящаяся в массиве
caller
).

А как обрабатываются исключения в Ruby? Для этой цели служит блок

begin-end
. В простейшей форме внутри него нет ничего, кроме кода:

begin

 #Ничего полезного.

 #...

end

Просто перехватывать ошибки не очень осмысленно. Но у блока может быть один или несколько обработчиков

rescue
. Если произойдет ошибка в любой точке программы между
begin
и
rescue
, то управление сразу будет передано в подходящий обработчик
rescue
.

begin

 x = Math.sqrt(y/z)

 # ...

rescue ArgumentError

 puts "Ошибка при извлечении квадратного корня."

rescue ZeroDivisionError

 puts "Попытка деления на нуль."

end

Того же эффекта можно достичь следующим образом:

begin

 x = Math.sqrt(y/z)

 # ...

rescue => err

 puts err

end

Здесь в переменной

err
хранится объект-исключение; при выводе ее на печать объект будет преобразован в осмысленную символьную строку. Отметим, что коль скоро тип ошибки не указан, то этот обработчик
rescue
будет перехватывать все исключения, производные от класса S
tandardError
. В конструкции
rescue => variable
можно перед символом
=>
дополнительно указать тип ошибки.

Если типы ошибок указаны, то может случиться так, что тип реально возникшего исключения не совпадает ни с одним из них. На этот случай после всех обработчиков

rescue
разрешается поместить ветвь
else
.

begin

 # Код, в котором может возникнуть ошибка...

rescue Type1

 # ...

rescue Type2

 # ...

else

 #Прочие исключения...

Поделиться:
Популярные книги

Умри завтра

Джеймс Питер
5. Рой Грейс
Детективы:
триллеры
8.92
рейтинг книги
Умри завтра

Студент из прошлого тысячелетия

Еслер Андрей
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.25
рейтинг книги
Студент из прошлого тысячелетия

Этот мир не выдержит меня. Том 2

Майнер Максим
2. Первый простолюдин в Академии
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Этот мир не выдержит меня. Том 2

Тепличный цветок

Ритчи Криста
2. Сестры Кэллоуэй
Любовные романы:
современные любовные романы
7.57
рейтинг книги
Тепличный цветок

Дневник (1887-1910)

Ренар Жюль
Проза:
проза прочее
4.00
рейтинг книги
Дневник (1887-1910)

Виктор Глухов агент Ада. Компиляция. Книги 1-15

Сухинин Владимир Александрович
Виктор Глухов агент Ада
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Виктор Глухов агент Ада. Компиляция. Книги 1-15

Старый, но крепкий 5

Крынов Макс
5. Культивация без насилия
Фантастика:
рпг
аниме
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 5

Антон Чехов

Труайя Анри
Проза:
историческая проза
5.00
рейтинг книги
Антон Чехов

Тринадцатый IX

NikL
9. Видящий смерть
Фантастика:
фэнтези
попаданцы
аниме
сказочная фантастика
5.00
рейтинг книги
Тринадцатый IX

Я все еще не царь. Книга XXVI

Дрейк Сириус
26. Дорогой барон!
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Я все еще не царь. Книга XXVI

Третий. Том 4

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 4

Страх — это ключ

Маклин Алистер
Детективы:
крутой детектив
6.25
рейтинг книги
Страх — это ключ

Резонанс Ци. Дилогия

Орлов Андрей Юрьевич
Резонанс Ци
Фантастика:
постапокалипсис
рпг
уся
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Резонанс Ци. Дилогия

Лейтенант. Часть 2. Назад в СССР

Гаусс Максим
9. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Лейтенант. Часть 2. Назад в СССР