1. Особенности работы с переменными и литералами в Perl6
2. Perl6 — Операции над переменными, анонимные блоки
3. Perl6 — Условные операторы, циклы
4. Perl6 — Работа с функциями
5. Perl6 — Классы
6. Perl6 — Ввод-вывод, модули
7. Perl6 — Комментарии, пробельные символы, скобки
8. Perl6 — Перегрузка операторов
9. Perl6 — Работа с типами данных
10. Perl6 — Обработка исключений
В прошлой статье мы говорили об отлове исключений, что происходило в специальном вложенном блоке CATCH. На самом деле этот блок является особой разновидностью — Phasers (я просто не могу перевести это слово). Phasers — это специальные вложенные блоки, которые выполняются при определенных условиях. С чем же их готовить увидите под катом.
Рассмотрим основных представителей Phaser'ов:
- BEGIN {...}*
Данный блок выполняется единожды при компиляции приложения, причем последний вычисленный результат (как и в дальнейшем у блоков отмеченных звездочкой) может быть использован как результат для присвоения переменной:say "Test say"; my $block = BEGIN { say "Compile say"; "Compile time " ~ now; } say $block;
В данном случае переменной блок будет присваиваться строка отражающая время компиляции (Причем как я понял сам блок выполняется при компиляции, а при выполнении скрипта переменной присваивается уже вычисленного значения).
В результате мы увидим на экране:Compile say Test say Compile time Instant:1377026323.088
Причем, если внутри блока BEGIN произойдет исклчение:
say "Test say"; my $block = BEGIN { die "Compile die"; "Compile time " ~ now; } say $block;
То на экране мы уже не увидим надписи «Test say», а сразу «Compile die», хотя вывод и происходит раньше чем присвоение результата выполнения блока BEGIN.
Ну и последний пример по этому блоку, чтобы развеять возможные сомнения:say "Test say"; BEGIN { say "Compile say"; } say "Test say 2"; BEGIN { say "Compile say 2"; }
В результате мы увидим на экране:
Compile say Compile say 2 Test say Test say 2
- CHECK {...}*
Аналогично предыдущему, но действия выполняются после выполнения компиляции но до выполнения самого скрипта, однако как я заметил в обратном порядке следования в коде:say "Test say"; BEGIN { say "Compile say"; } CHECK { say "Check say"; } say "Test say 2"; BEGIN { say "Compile say 2"; } CHECK { say "Check say 2"; }
В результате мы увидим на экране:
Compile say Compile say 2 Check say 2 Check say Test say Test say 2
- INIT {...}*
Данный блок выполняется при запуске скрипта:say "Test say"; BEGIN { say "Compile say"; } CHECK { say "Check say"; } INIT { say "Init say"; } say "Test say 2"; BEGIN { say "Compile say 2"; } CHECK { say "Check say 2"; } INIT { say "Init say 2"; }
В результате вывод следующий:
Compile say Compile say 2 Check say 2 Check say Init say Init say 2 Test say Test say 2
- END {...}
Блок выполняется при остановке скрипта. Стоит отметить, что выполняется он так же как и в случае с CHECK в обратном порядке как были встречены в скрипте, и ещё одну важную вещь — данный блок выполняется даже если в скрипте произошло исключение:say "Test say"; BEGIN { say "Compile say"; } CHECK { say "Check say"; } INIT { say "Init say"; } END { say "End say"; } say "Test say 2"; BEGIN { say "Compile say 2"; } CHECK { say "Check say 2"; } INIT { say "Init say 2"; } END { say "End say 2"; } die "test die";
В результате видим на экране:
Compile say Compile say 2 Check say 2 Check say Init say Init say 2 Test say Test say 2 test die in block at blablablaperl.p6:37 End say 2 End say
- ENTER {...}*
Данный блок выполняется при любом выполнении блока, в который вложен блок ENTER:loop (my $i=0; $i <4; $i++) { ENTER { say $i; } say "Another loop entry"; } ENTER { say "Test Enter"; }
Вывод данного скрипта:
Test Enter 0 Another loop entry 1 Another loop entry 2 Another loop entry 3 Another loop entry
Стоит также отметить то, что можно блоки Phasers вкладывать друг в друга.
- LEAVE {...}
Выполняется при завершении работы блока, в который LEAVE был вложен. Вот тут вот я и сново столкнулся с проблемами, из-за которых я и отложил в прошлый раз изучение — я опять начал получать невнятные ошибки если поставил не туда пробел. А пример с блоком LEAVE у меня просто напросто не скомпилировался, оповещая меня о ошибке с неправильным количеством параметров у оператора return, который я кстате и не пытался использовать. Но пример я всетаки приведу:loop (my $i=0; $i <4; $i++) { LEAVE { say "Test leave"; } say "Another loop entry"; }
Если вдруг кто-нибудь сможет это скомпилировать, поведайте пожалуйста в комментариях.
Как в дальнейшем я выяснил, не работает часть, связанная с выходом из блока. Но перейдем дальше: - KEEP {...}
Данный блок выполняется при успешном выполнении всего блока (как именно определяется успешность проверить не смог, так как скрипт с использованием такого блока не компилируется). - UNDO {...}
Аналогично предыдущему блоку, но в случае если выполнение было завершено не успешно. Пример тоже не компилируем. - FIRST {...}*
Данный блок выполняется только при первом запуске блока, в который вложен FIRST:loop (my $i=0; $i <4; $i++) { FIRST {say "Test keep";} say "Another loop entry"; }
Соответственно вывод:
Test keep Another loop entry Another loop entry Another loop entry Another loop entry
Так же в отдельный список выведены операторы, которые действуют подобно Phaser'ам, которые пишутся в нижнем регистре:
- do {...}*
Выполняет все операции в блоке, а результат представляет в виде терма. Пример использования:if ( do {my $a = 10; $a = $a*2;} == 20) { say "It's ok"; }
Таким образом мы вложили вычисление внутрь блока if, а сам блок do можно будет использовать потом для сравнения. Пример конечно очень плохой для ваших пальцев (можно и линейкой схлопотать по ним за такое), но для того чтобы показать для чего он может быть использован пример сгодится.
- once {...}*
Данный блок должен будет выполниться лишь раз. К сожалению проверить я так и не смог, так как пример не компилируем:my $i = once { say "Test once"; }; $i(); $i(); $i();
Жалуется на то, что не смог найти функцию &once.
- try {...}*
Знакомый по предыдущей статье блок, игнорирующий все исключения. - lazy {...}*
По описанию должен возвращать «обещание» о выполнении. К сожалению результат для него как и у 'once' блока. Как я понял данный блок должен помочь нам в организации «ленивых вычислений». - async {...}
Выполняет блок в новом потоке. К сожалению опять же не смог скомпилировать пример. Зато теперь имею представление о том как будет происходить работа с потоками.
Чтож, пожалуй пора заканчивать. Как-то даже длинновай пост получился из-за примеров, но надеюсь вам понравилось.
Автор: WarFair