To do this, use Attribute::Handlers - a fairly reasonable way to use attributes. We must define a function in a base class that itself has an attribute :ATTR(CODE) . This takes several arguments:
- The package where the sub (or other variable) comes.
- Globref or string
ANON . - A reference to a value (here: coderef).
- Attribute name.
- Additional data for the attribute.
- The phase (compilation) in which the attribute was called.
- The name of the file in which the signature was declared.
- The number of the line in which sub was declared.
So what we can do is write a handler that applies before :
use strict; use warnings; use feature 'say'; BEGIN { package MyRole; use Moose::Role; use Attribute::Handlers; sub SomeFlag :ATTR(CODE) { my ($package, $globref, $code, $attr, $data, $phase, $filename, $line) = @_; ref($globref) eq 'GLOB' or die "Only global subroutines can be decorated with :SomeFlag" . " at $filename line $line.\n";
I have enclosed all of this in a single file, but this is obviously not necessary (just add the required use s).
Output:
Just about to call a flagged sub! at so.pl line 16. Hi from foo sub! Just about to call a flagged sub! at so.pl line 16. Hi from bar sub! Hi from baz sub!
source share