Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Locked in a Box: Closures in Raku

Locked in a Box: Closures in Raku

Extending the basic idea of closures in Perl (see "Locked in a Box: Closures in Perl5") this looks at some of the extensions offered by Raku's types, defaults, and signatures. Taken together these provide a whole new level of flexibility and generality to applying closures for cleaner code.

Steven Lembark

July 14, 2023
Tweet

More Decks by Steven Lembark

Other Decks in Technology

Transcript

  1. Raku closures are... Just closures. They close over a variable.

    Raku has some syntax differences. Can produce simpler, more declarative results. Multiple dispatch opens a brave new world.
  2. Named-sub closures Subs in Raku are lexically scoped. do {

    my $verbose = $ENV{ VERBOSE }; sub message { say @_ if $verbose; } }; &message ‘Foobar’; # this fails
  3. Named-sub closures Subs in Raku are lexically scoped. “our” makes

    it visible. do { my $verbose = $ENV{ VERBOSE }; our sub message { say @_ if $verbose; } }; &message ‘Foobar’;
  4. Named-sub closures The ‘&’ sigil indicates a subref. Doesn’t require

    the ‘&’. my &message = do { my $verbose = $ENV{ VERBOSE }; sub { say @_ if $verbose; } }; message ‘Foobar’;
  5. Input handler Signiture requires two inputs. loop & prompt are

    Raku builtins. sub gen_prompt ( $prompt, &sanity ) { sub() { my $input = ‘’; loop() { $input = prompt( $prompt ) // fail; sanity( $input ) and last; } return $input } }
  6. Input handler Code object via ‘&’ . Cleaner syntax to

    execute. sub gen_prompt ( $prompt, &sanity ) { sub() { my $input = ‘’; loop() { $input = prompt( $prompt ) // fail; sanity( $input ) and last; } return $input } }
  7. Input handler Why use only code? Raku smart matches work!

    sub gen_prompt ( $prompt, $sanity ) { sub() { my $input = ‘’; loop() { $input = prompt( $prompt ) // fail; $input ~~ $sanity and last; } return $input } }
  8. Raku sanity with ~~ $sanity = sub block inline test

    lazy list $sanity = sub( $n ) { 10 <= $n <= 99 }; = { 10 <= $_ <= 99 }; = { 10 <= $^val <= 99 }; = 10 <= * <= 99 ; = 10 .. 99; = /^\d\d$/ gen_prompt( ‘Two digit number:’ => $sanity );
  9. Sequence Generator Perl5 sub generate_counter { my $value = shift;

    my $final = shift // 2**32-1; looks_like_number $value or die ... ; looks_like_number $final or die ... ; $value <= $final or die ... ; sub { $value > $final and return; $value++ } }
  10. Sequence Generator sub generate_counter ( int $value = 0 is

    copy , int $final = ∞ ) { $value > $final and fail; return sub { $value <= $final or fail; return value++ } } Raku
  11. Sequence Generator sub generate_counter ( int $value = 0 is

    copy , int $final = ∞ ) { $value > $final and fail; return sub { $value <= $final or fail; return $value++ } } Raku Args default ro, “is copy” allows rw.
  12. Sequence Generator ∞ avoids arbitrary limits. sub generate_counter ( int

    $value = 0 is copy , int $final = ∞ ) { $value > $final and fail; return sub { $value <= $final or fail; return $value++ } }
  13. Sequence Generator ro args Saner failure message. $first not closed

    over. sub generate_counter ( int $first = 0 , int $final = ∞ ) { $first > $final and fail; my $value = $first; return sub { $value <= $final or fail; return $value++ } }
  14. Sequence Generator “return sub” required for “return $value++” sub generate_counter

    ( int $first = 0 , int $final = ∞ ) { $first > $final and fail; my $value = $first; return sub { $value <= $final or fail; return $value++ } }
  15. Sequence Generator Sans return, use a block. sub generate_counter (

    int $first = 0 , int $final = ∞ ) { $first > $final and fail; my $value = $first; { $value <= $final or fail; $value++ } }
  16. Sequence Generator Raku sequence generator. sub generate_counter ( int $first

    = 0 , int $final = ∞ ) { $first > $final and fail; my $value = $first; { $value <= $final or fail; $value++ } }
  17. Multiple dispatch Raku sub’s have signitures. Same name, differing signiture

    is a “variant”. Selection at runtime based on the arguments.
  18. Sequence variants Generate the correct type of sequences based on

    the argument types. multi gen_seq ( int $first, int $final = ∞ ) { $first <= $final or fail; my $value = $first; { $value <= $final or fail; ++value } } multi gen_seq( string $first, string $final = ∞ ) { $first le $final or fail; my $value = $first; { $value le $final or fail; ++value } }
  19. Summary Raku closures look like Perl closures: Sub ‘closes over’

    variables declared outside sub. Smart match simplifies wide range of validators. Multimethods simplify generation.