I'm working on a complicated piece of code for a client, and I really have to put extra attention to the code I'm writing. It's relatively difficult to come up with a test data to check everything, but I can at least ensure I give the modules enough data to cover most of the code.
To make a long story short, I want to have assertions and enable them only in some tests.
package MyModule; BEGIN { *__ASSERT__ = $main::__ASSERT__ ? sub () { 1 } : sub () { 0 }; } sub routine { my ($self, %args) = @_; ... if( __ASSERT__) { die "\$kayo is '$kayo' and not 'whap'" unless $kayo eq 'whap'; } ... }
Now I only have to write:
BEGIN { our $__ASSERT__ = 1; } use MyModule;
And the assertion code is enabled. Otherwise it's optimized away (don't forget the prototype as I first did, otherwise the __ASSERT__()
method will always be called). Assertions for FREE! NO extra code when we don't want them (which is most of the time) and NO runtime penalty.
And I can even verify this very assertion, thanks to Data::Dumper recent power upgrade:
$ perl -MData::Dumper -MMyModule -e '$Data::Dumper::Deparse = 1; print Dumper \&MyModule::routine' $VAR1 = sub { package MyModule; my($self, %args) = @_; ... '???'; ... }
That’s old hat.B::Deparse
itself.
What would be really cool is if someone came up with a way to supply
sub assert(&) { shift->() or croak "Assertion failed" }
to module client code, and then included a way to walk the caller’s optree and slice out all the calls to this function when the code is not running in debug mode, preferrably with respect to lexical scopes, and signified by import
/unimport
– to the overall effect of making this work as if it was a pragma, using use assertions
and no assertions
.
(Now that I think about it… isn’t Perl 5.10 supposed to have assertions?)