Часто бывает так, что хотелось бы иметь возможность указать ответные действия на неожиданные события. Как выясняется, легче всего это сделать, если мы сможем передать блок кода в качестве аргумента другому методу, что означает, что мы хотим рассматривать код в качестве данных.
Новый процедурный объект формируется с использование оператора proc :
- ruby> quux = proc {
- | print "QUUXQUUXQUUX!!!\n"
- | }
- #<Proc:0x4017357c>
Это означает, что quux можно считать объектом, и как большинство объектов, он имеет такое же поведение, то есть может быть вызван. В частности, мы можем попросить его выполниться, через его метод call .
- ruby> quux.call
- QUUXQUUXQUUX!!!
- nil
Итак, после всего этого quux может быть использован в качестве аргумента метода? Конечно.
- ruby> def run( p )
- | print "About to call a procedure...\n"
- | p.call
- | print "There: finished.\n"
- | end
- nil
- ruby> run quux
- About to call a procedure...
- QUUXQUUXQUUX!!!
- There: finished.
- nil
Метод trap позволяет нам назначить ответ по нашему выбору на любой сигнал системы. То есть сделать обработчик сигналов от системы.
- ruby> inthandler = proc{ print "^C was pressed.\n" }
- #<Proc:0x401730a4>
- ruby> trap "SIGINT", inthandler
- #<Proc:0x401735e0>
Обычно нажатие сочетания клавиш Ctrl+C интерпретируется как выход. Сейчас же печатается сообщение и интерпретатор продолжает работать, поэтому мы не потеряли рабочий режим сделав этом. Но вы не захватили интерпретатор навсегда, вы всё еще можете выйти из интерпретатора, нажав сочетание клавиш Ctrl+D или напечатав exit )
Последнее замечание, прежде чем перейти к другим темам. Не обязательно именовать процедурный объекта для того, чтобы привязаться к сигналу от системы. Эквивалент анонимного процедурного объекта выглядит так:
- ruby> trap "SIGINT", proc{ print "^C was pressed.\n" }
- nil
Или ещё более компактно:
- ruby> trap "SIGINT", 'print "^C was pressed.\n"'
- nil
Данная форма записи предоставляет более удобный и читаемый вариант кода, когда вы пишите маленькие анонимные процедуры.