Search code examples
perlperl-module

How do I detect the 'strict' pragma within a module?


Normally when I build a data structure in Perl, I end up having to declare it from %leaf to %root, so I have been tinkering with a module that would allow me to build up from
$seed to $seed->trunk->branch->leaf.

It's not difficult with AUTOLOAD and new subroutines. My question for SO is how do I detect if the 'strict' pragma is in use, so that the module runs in a different mode that would require the variables to be "declared" before usage so I don't accidently assign a value to $seed->drunk when I'm using strict -- assume that the module is called branch and this is valid syntax for module usage

$seed->declare('trunk');
$seed->trunk(new branch);

$seed->trunk->declare('leaf');
$seed->trunk->leaf("value");

How do I detect if the strict pragma is in effect in the calling program from the module?

It may be that this is not possible -- in which case I'd have to use a static variable to handle module independent pragmas.

EDITED / POSTSCRIPT:

I coded out the initial version that doesn't check for 'strictness' or implement a 'declare' subroutine and realized that the autoloader would not provide a simple enough user syntax if it operated by reference, so I wrote it to check for the first parameter and assign the value passed to an element in the object's referred hash table, otherwise if there was no parameter it would return the value of the element specified.

So I am posting the code for the branch module to satisfy your curiosity. Mind you, I haven't implemented a check for strictness, yet.

package branch;

sub new
{
    my $type = shift;
    my $self = { };
    bless $self, $type;
    return $self;
}

sub DESTROY
{
    my $self = shift;
    %$self = undef;
}

sub AUTOLOAD
{
    my $self = shift;
    my $value = shift;

    my $sub = $AUTOLOAD;
    my ($type, $PROGRAM) = ($sub =~ /(.*)::(.*)/);

    if( $value ne undef )
    {
        $$self{$PROGRAM} = $value;
        return $value;
    }
    return $$self{$PROGRAM};
}

1;

Solution

  • Well the first thing would be, strict what? Strict has three subpragmas, with their own behaviors and bits to check. use strict 'refs' doesn't allow you to dereference strings; use strict 'vars' doesn't allow you to access global variables in an unqualified way, and use strict 'subs' disables barewords outside of a few situations. use strict equates to all three, but none of them really seems close enough to what you're asking for to be worth piggy-backing on.

    So to answer your question somewhat directly: element [8] in the list returned by caller($i) returns the compile hint bits in effect for the $ith level caller. If you peek in strict.pm you can see the bits that each subpragma sets and check for them at the caller level that corresponds to the code that's actually calling your method.

    But, returning to my original point, you probably shouldn't, because that's not what strict is about. You should either accept an option on your objects' constructor that decides whether they should behave strictly or not, or if you really want a lexical pragma instead of something that follows your objects around, you should write your own using the information in perlpragma as a tutorial. All perls since 5.10 support arbitrary user-defined pragmas using the %^H hints hash which is exposed as element [10] of the caller info.