En guarde! Playing with Guard

TL;DR

Playing a bit with Guard.

With a little help from wrapperl (Wrapperl, from the past) and a newly compiled perl-5.38.0 (thanks to perl-builder), I got to play with a lot of new shiny toys!

As a matter of fact, I was taking a look at Guard, with two programs that do what I expected them to.

The first is about function scope_guard, which I suppose is what’s needed most of the times:

#!/usr/bin/env wrapperl
use v5.38;
use warnings;
use Guard;

$|++;

scoped(shift // 'die');

sub scoped ($what) {
   scope_guard(\&en_guarde);
   if ($what eq 'die') {
      die "whatever!";
   }
   elsif ($what eq 'return') {
      say 'about to return...';
      return;
   }
   elsif ($what eq 'exit') {
      say 'exiting...';
      exit 1;
   }
   else {
      say 'dumpiiiing!';
      CORE::dump();
   }
}

sub en_guarde { warn "en_guarde(@_)!" }

This prints:

$ ./guard-1.pl die
whatever! at ./guard-1.pl line 13.
en_guarde()! at ./guard-1.pl line 29.

$ ./guard-1.pl return
about to return...
en_guarde()! at ./guard-1.pl line 29.

$ ./guard-1.pl exit
exiting...
en_guarde()! at ./guard-1.pl line 29.

$ ./guard-1.pl dump
dumpiiiing!
Aborted

Yes, I tried to dump and it indeed dumped right on the post, no questions asked! So there’s a way, after all, and it does not imply cutting the power cord!

Sometimes we just need some more control, like well yes this guard is useful but what if I need to complete some stuff in the upper sub? or what if I change my mind and want to commit instead of rolling back?

Well, guard gets you covered with generating an object whose lifetime dictates the behaviour, including the possibility to cancel. The lifetime thing frees us from the specific lexical scope where the object is generated and allows us to pass it up in the call chain:

#!/usr/bin/env wrapperl
use v5.38;
use warnings;
use Guard;

$|++;

scope_object();
say '';
say 'we will exit the process now';

sub scope_object {
   say 'getting a scope object from a sub, void context';
   get_scope_object();
   say 'see? en_guarde() was triggered out of the box';
   say '';
   say 'getting a scope object from a sub, scalar context (collecting it)';
   my $object = get_scope_object();
   say 'got a scope object from a sub, now returning...';
   return;
}

sub get_scope_object { guard(\&en_guarde) }

sub en_guarde { warn "en_guarde(@_)!" }

This prints:

$ ./guard-2.pl 
getting a scope object from a sub, void context
en_guarde()! at ./guard-2.pl line 25.
see? en_guarde() was triggered out of the box

getting a scope object from a sub, scalar context (collecting it)
got a scope object from a sub, now returning...
en_guarde()! at ./guard-2.pl line 25.

we will exit the process now

I guess it’s all for today!


Comments? Octodon, , GitHub, Reddit, or drop me a line!