Возможно, это не выглядит так уж особенно потрясающим… но это так и есть. :-) В программировании слишком часто имеются строгие требования к тому, что должно быть сделано и когда. Если вы хотите, например, сохранить файл, вам нужно открыть файл, записать туда информацию, которую вы хотите в нём хранить, а затем закрыть файл. Если вы позабудете закрыть файл, могут случиться «Плохие Вещи™. Но каждый раз, когда вы хотите сохранить или загрузить файл, вам требуется делать одно и то же: открывать файл, выполнять то, что вы действительно желаете сделать, затем закрывать файл. Это утомительно и легко забывается. В Ruby сохранение (или загрузка) файлов работает подобно приведённому выше коду, поэтому вам не нужно беспокоиться ни о чём, кроме того, что вы действительно хотите сохранить (или загрузить). (В следующей главе я покажу вам, где разузнать, как делать такие вещи, как сохранение и загрузка файлов.)
Вы также можете написать методы, которые будут определять, сколько раз (или даже при каком условии) вызывать процедурный объект. Вот метод, который будет вызывать переданный ему proc–объект примерно в половине случаев, и ещё один метод, который будет вызывать его дважды:
def maybeDo someProc
# Условный вызов
if rand(2) == 0
someProc.call
end
end
def twiceDo someProc
# Двойной вызов
someProc.call
someProc.call
end
wink = Proc.new do
puts '
end
glance = Proc.new do
puts '
end
maybeDo wink
maybeDo glance
twiceDo wink
twiceDo glance
<подмигнуть>
<подмигнуть>
<взглянуть>
<взглянуть>
(Если вы перезагрузите эту страницу несколько раз [имеется ввиду страница оригинального учебника –
Прежде, чем мы продолжим, давайте посмотрим на последний пример. До сих пор все передаваемые процедурные объекты были довольно похожи друг на друга. В этот раз они будут совсем другими, и вы увидите, насколько сильно подобный метод зависит от тех процедурных объектов, что были ему переданы. Наш метод примет обычный объект и процедурный объект, и вызовет процедурный объект с обычным объектом в качестве параметра. Если процедурный объект вернёт false, мы закончим выполнение, иначе мы вызовем процедурный объект с возвращённым объектом. Мы будем продолжать так делать, пока процедурный объект не вернёт false (что ему лучше сделать в конце концов, иначе программа «загнётся»). Этот метод вернёт последнее значение, возвращённое процедурным объектом, не равное false.
def doUntilFalse firstlnput, someProc input = firstlnput output = firstlnput
while output
input = output output = someProc.call input end
input
end
buildArrayOfSquares = Proc.new do |array| # Создание массива квадратов чисел
lastNumber = array.last if lastNumber <= 0 false else
array.pop # Уберём последнее число…
array.push lastNumber*lastNumber # …и заменим его на его квадрат…
array.push lastNumber–1 # …за которым идет предыдущее
число.
end
end
alwaysFalse = Proc.new do |justIgnoreMe| false end
puts doUntilFalse([5], buildArrayOfSquares).inspect
puts doUntilFalse ('Я пишу это в 3 часа утра; кто–то меня вырубил!', alwaysFalse)
[25, 16, 9, 4, 1, 0]
Я пишу это в 3 часа утра; кто-то меня вырубил!
Хорошо, признаю, что это был довольно странный пример. Но он показывает, насколько по-разному ведёт себя наш метод, когда ему передают совсем разные процедурные объекты.