Phasers to Stunning
A little look into Perl6 Phasers
What are Phasers?
● Similar to Perl5 special subroutines like BEGIN and END
● Some significant differences though
● And there’s LOTS more of them
● Program lifetime is divided into phases which have their own phasers :
○ Program execution
○ Block
○ Loop
○ Exception
○ Asynchronous
○ Doc
○ Object (Planned)
Statements or Blocks
# … Long running bit of code
say “Time take {now - INIT now}”;
All Phasers can be applied to either statements or blocks.
Certain Phasers generate a value that’s available at runtime.
(BEGIN, CHECK, INIT and ENTER)
This doesn’t apply to the CHECK and CONTROL Phasers as they require an argument
and must be applied to a block.
Program Execution
Four phases in Program Execution broken into two stages :
● Compilation
○ BEGIN : As soon as possible during compilation. Only ran once. Has a runtime value.
■ Similar to the Perl5 BEGIN block.
○ CHECK : As late as possible during compilation. Only ran once. Has a runtime value.
■ Similar to the Perl5 UNITCHECK block.
● Rutime
○ INIT : As soon as possible during runtime. Only ran once. Has a runtime value.
■ Similar to the Perl5 INIT block.
○ END : As late as possible during runtime. Only ran once.
■ Similar to the Perl5 END block.
CHECK and END Phasers are run in LIFO order.
Precompilation Gotcha
BEGIN and CHECK Phasers are evaluated as compile time.
In a module this will generally mean they are evaluated once at the precompilation
step.
For example :
my $start = BEGIN now;
Will store the time the module was compiled at NOT the time it was used in a script.
They are useful for storing system specific code (OS specific for instance).
Block
Block level Phasers apply to all Block including the implicit top level Block of a script
and Loops.
● PRE : Runs at start, before ENTER. Dies unless True. Outside block level exception
handling.
● ENTER : Runs at start of block. Can have a return value.
● LEAVE : Runs at the end of the block. Outside block level exception handling.
● KEEP : Runs at the end of a successful block.
● UNDO : Runs at the end of an unsuccessful block.
● POST : Runs at end, after LEAVE. Dies unless True. Outside block level exception
handling.
LEAVE, KEEP and UNDO
The LEAVE Phaser will trigger when the block is left in almost* any way.
* Doesn’t trigger if you terminate your program with exit.
The UNDO Phaser will trigger if the block is returning an undefined value.
The KEEP Phaser will trigger if the block is returning a defined value.
PRE and POST
PRE and POST run at the very start and end of a block and will throw and Exception if
they evaluate to False.
Example sub that can only be called between 9-5 local time.
sub do_thing_at_work() {
PRE 9 <= DateTime.now.hour <= 17;
…
}
PRE and POST
The POST block can be defined inside the PRE block in which case it shares scope.
Example sub that errors if it takes over 2 seconds to complete.
sub do_thing_fast() {
PRE {
my $s = now;
POST { now - $s < 2; }
True;
}
…
}
Loop
Loop blocks have three additional Phasers on top of the other Block level ones.
● FIRST : Runs before ENTER once at the start of the loop.
● NEXT : Runs at the end of the loop before LEAVE.
○ Not triggered if a non next exception ends the loop
● LAST : Runs after leave when the loop is completed.
○ This can be because the loop finished or a last or return caused an early exit.
○ Not triggered if the loop ends due to a general exception.
Exception handling
Exceptions for the purpose of Phasers fall into 2 types.
● Control Exceptions
○ Exceptions of the Role X::Control.
○ Used for functionality like next, last or return where you want to override the standard code
paths
○ Generally handled by various Phasers
○ CONTROL Phaser can catch Control Exceptions raised in the current Block context.
○ (NB. This is true after the Rakudo 2019.03 Release)
● General Exceptions
○ All non Control Exceptions
○ CATCH Phaser can catch General Exceptions raised in the current Block context.
try vs CATCH
A try block is a special type of block that does the following :
● Makes Failures (such as 1/0) fatal
● Includes a CATCH block that silently drops any Exception
● Sets $! to the value of the dropped Exception
Sometimes this is what you want. Other times you may want more control over
Exception handling.
You can put a CATCH block inside a try block to catch specific Exceptions.
Asynchronous
There are three Phasers that can trigger because of Asynchronous program flow
● LAST :
○ Within a whenever block if the Supply ends normally (either by running out of values or by
calling done).
○ Triggers after the whenever block.
● QUIT :
○ Within a whenever block if the Supply ends due to an Exception.
○ Triggers after the whenever block.
● CLOSE :
○ Within a Supply block.
○ Triggers when the Supply is closed.
Doc
The BEGIN, CHECK and INIT Phasers can be prefixed with DOC.
In this case they will only run in DOC mode.
What about CHECK and AUTOLOAD?
The CHECK special subroutine in Perl5 doesn’t have a direct correlation in Perl6.
The UNITCHECK functionality was added in 5.10 to mirror CHECK in Perl6.
The AUTOLOAD block is best handled by the FALLBACK method that can be added to
any Class or Role to handle any methods not explicitly defined.
Todays Slides Brought to you by
● Simon Proctor
● Scimon in many places (includes @scimon on Twitter).
● Senior Developer at Zoopla
Thanks
Questions?

Phasers to stunning

  • 1.
    Phasers to Stunning Alittle look into Perl6 Phasers
  • 2.
    What are Phasers? ●Similar to Perl5 special subroutines like BEGIN and END ● Some significant differences though ● And there’s LOTS more of them ● Program lifetime is divided into phases which have their own phasers : ○ Program execution ○ Block ○ Loop ○ Exception ○ Asynchronous ○ Doc ○ Object (Planned)
  • 3.
    Statements or Blocks #… Long running bit of code say “Time take {now - INIT now}”; All Phasers can be applied to either statements or blocks. Certain Phasers generate a value that’s available at runtime. (BEGIN, CHECK, INIT and ENTER) This doesn’t apply to the CHECK and CONTROL Phasers as they require an argument and must be applied to a block.
  • 4.
    Program Execution Four phasesin Program Execution broken into two stages : ● Compilation ○ BEGIN : As soon as possible during compilation. Only ran once. Has a runtime value. ■ Similar to the Perl5 BEGIN block. ○ CHECK : As late as possible during compilation. Only ran once. Has a runtime value. ■ Similar to the Perl5 UNITCHECK block. ● Rutime ○ INIT : As soon as possible during runtime. Only ran once. Has a runtime value. ■ Similar to the Perl5 INIT block. ○ END : As late as possible during runtime. Only ran once. ■ Similar to the Perl5 END block. CHECK and END Phasers are run in LIFO order.
  • 5.
    Precompilation Gotcha BEGIN andCHECK Phasers are evaluated as compile time. In a module this will generally mean they are evaluated once at the precompilation step. For example : my $start = BEGIN now; Will store the time the module was compiled at NOT the time it was used in a script. They are useful for storing system specific code (OS specific for instance).
  • 6.
    Block Block level Phasersapply to all Block including the implicit top level Block of a script and Loops. ● PRE : Runs at start, before ENTER. Dies unless True. Outside block level exception handling. ● ENTER : Runs at start of block. Can have a return value. ● LEAVE : Runs at the end of the block. Outside block level exception handling. ● KEEP : Runs at the end of a successful block. ● UNDO : Runs at the end of an unsuccessful block. ● POST : Runs at end, after LEAVE. Dies unless True. Outside block level exception handling.
  • 7.
    LEAVE, KEEP andUNDO The LEAVE Phaser will trigger when the block is left in almost* any way. * Doesn’t trigger if you terminate your program with exit. The UNDO Phaser will trigger if the block is returning an undefined value. The KEEP Phaser will trigger if the block is returning a defined value.
  • 8.
    PRE and POST PREand POST run at the very start and end of a block and will throw and Exception if they evaluate to False. Example sub that can only be called between 9-5 local time. sub do_thing_at_work() { PRE 9 <= DateTime.now.hour <= 17; … }
  • 9.
    PRE and POST ThePOST block can be defined inside the PRE block in which case it shares scope. Example sub that errors if it takes over 2 seconds to complete. sub do_thing_fast() { PRE { my $s = now; POST { now - $s < 2; } True; } … }
  • 10.
    Loop Loop blocks havethree additional Phasers on top of the other Block level ones. ● FIRST : Runs before ENTER once at the start of the loop. ● NEXT : Runs at the end of the loop before LEAVE. ○ Not triggered if a non next exception ends the loop ● LAST : Runs after leave when the loop is completed. ○ This can be because the loop finished or a last or return caused an early exit. ○ Not triggered if the loop ends due to a general exception.
  • 11.
    Exception handling Exceptions forthe purpose of Phasers fall into 2 types. ● Control Exceptions ○ Exceptions of the Role X::Control. ○ Used for functionality like next, last or return where you want to override the standard code paths ○ Generally handled by various Phasers ○ CONTROL Phaser can catch Control Exceptions raised in the current Block context. ○ (NB. This is true after the Rakudo 2019.03 Release) ● General Exceptions ○ All non Control Exceptions ○ CATCH Phaser can catch General Exceptions raised in the current Block context.
  • 12.
    try vs CATCH Atry block is a special type of block that does the following : ● Makes Failures (such as 1/0) fatal ● Includes a CATCH block that silently drops any Exception ● Sets $! to the value of the dropped Exception Sometimes this is what you want. Other times you may want more control over Exception handling. You can put a CATCH block inside a try block to catch specific Exceptions.
  • 13.
    Asynchronous There are threePhasers that can trigger because of Asynchronous program flow ● LAST : ○ Within a whenever block if the Supply ends normally (either by running out of values or by calling done). ○ Triggers after the whenever block. ● QUIT : ○ Within a whenever block if the Supply ends due to an Exception. ○ Triggers after the whenever block. ● CLOSE : ○ Within a Supply block. ○ Triggers when the Supply is closed.
  • 14.
    Doc The BEGIN, CHECKand INIT Phasers can be prefixed with DOC. In this case they will only run in DOC mode.
  • 15.
    What about CHECKand AUTOLOAD? The CHECK special subroutine in Perl5 doesn’t have a direct correlation in Perl6. The UNITCHECK functionality was added in 5.10 to mirror CHECK in Perl6. The AUTOLOAD block is best handled by the FALLBACK method that can be added to any Class or Role to handle any methods not explicitly defined.
  • 16.
    Todays Slides Broughtto you by ● Simon Proctor ● Scimon in many places (includes @scimon on Twitter). ● Senior Developer at Zoopla
  • 17.