MAIN course
On IRC vasko asked how to handle a --verbose
-flag. This is quite simple.
sub debug($level, |c) {
say(|c) if $*VERBOSE && $*DEBUG-LEVEL ≥ $level;
}
sub MAIN(:v(:verbose($*VERBOSE)), :D(:debug-level($*DEBUG-LEVEL))) {
debug 1, 'FYI, all is fine';
}
I can spot two pieces laying on our boilerplate. If you do a lot of shell-scripting, supporting -v
and -D
might be quite common. Also, every time we call debug
we type a space and a comma to many.
proto sub MAIN(Bool :v(:verbose($*VERBOSE)) = False, Int :D(:debuglevel($*DEBUG-LEVEL)) = 1, |) is export {
&debug1 = &debug.assuming(1) if $*DEBUG-LEVEL ≥ 1;
&debug2 = &debug.assuming(2) if $*DEBUG-LEVEL ≥ 2;
&debug3 = &debug.assuming(3) if $*DEBUG-LEVEL ≥ 3;
&debug4 = &debug.assuming(4) if $*DEBUG-LEVEL ≥ 4;
&debug5 = &debug.assuming(5) if $*DEBUG-LEVEL ≥ 5;
&debug6 = &debug.assuming(6) if $*DEBUG-LEVEL ≥ 6;
&debug7 = &debug.assuming(7) if $*DEBUG-LEVEL ≥ 7;
&debug8 = &debug.assuming(8) if $*DEBUG-LEVEL ≥ 8;
&debug9 = &debug.assuming(9) if $*DEBUG-LEVEL ≥ 9;
my &*debug1 = &debug.assuming(1);
{*}
}
sub debug($level, |c) {
say(|c) if $*VERBOSE; # and $*DEBUG-LEVEL ≥ $level;
}
my (&debug1, &debug2, &debug3, &debug4, &debug5, &debug6, &debug7, &debug8, &debug9) X= {;};
sub EXPORT() {
Map.new: '&debug1' => &debug1, '&debug2' => &debug2, '&debug3' => &debug3, '&debug4' => &debug4, '&debug5' => &debug5, '&debug6' => &debug6, '&debug7' => &debug7, '&debug8' => &debug8, '&debug9' => &debug9
}
This module exports a sub for each log-level. Those default to an empty block, until MAIN
is called. Depending on the log-level, we rebind them to the actual sub debug
with a fitting .assuming
. We also wire up the dynvar $*VERBOSE
. I wrote them in all caps to indicate they are constant-ish. This all works because an export of the form '&debug1' => &debug1
does export an &
-sigiled container, which we can change even after sub EXPORT
and the use
-statement have finished their work.
use fancy-debug;
multi sub MAIN(*%_) {
debug1 'level1';
debug2 'level2';
say 'i haz a done!';
}
Since we supply extra named arguments that are handled in the proto, we have to please the dispatcher with *%_
. Repeating the named arguments would work too.
Thanks to vasko, I could identify dynvars in argument aliases as an ENODOC and found a way new way to remove the MAIN
-course from my boilerplate.
-
December 13, 2021 at 21:572021.50 _ for Micros – Rakudo Weekly News