Devel::Pragma(3pm)

πŸ’– Devel::Pragma πŸ’–

okay bestie, so this one is Devel::Pragma β€” she's part of the User Contributed Perl Documentation collection (the section 3pm girlies, you know the vibe), and she is literally the helper-functions module for anyone out here writing lexical pragmas. if that's your situation, this page is your bestie fr fr 🫢


✨ NAME ✨

Devel::Pragma β€” helper functions for developers of lexical pragmas


🌸 SYNOPSIS 🌸

package MyPragma;

use Devel::Pragma qw(:all);

sub import {
    my ($class, %options) = @_;
    my $hints  = hints;        # the builtin (%^H) used to implement lexical pragmas
    my $caller = ccstash();    # the name of the currently-compiling package (stash)

    unless ($hints->{MyPragma}) { # top-level
        $hints->{MyPragma} = 1;
    }

    if (new_scope($class)) {
        ...
    }

    my $scope_id = scope();
}

πŸ‘‘ DESCRIPTION πŸ‘‘

so this module hands you helper functions for developers of lexical pragmas β€” and also like, a couple of functions that lowkey might be useful to people who are not writing pragmas at all. generous queen πŸ’…

and the tea on pragmas themselves: you can use them in older versions of perl (from 5.8.1), which only had limited support, and also in the most recent versions, which have improved support. so basically, whenever you show up, she ate. periodt.


πŸŽ€ EXPORTS πŸŽ€

Devel::Pragma exports the following functions on demand. if you want the whole entire squad at once, just use the :all tag. like so:

use Devel::Pragma qw(:all);

πŸ¦‹ hints

this function flips on the scoped behaviour of the hints hash (%^H) and then hands you back a reference to it. iconic behaviour tbh.

so the hints hash is a compile-time global variable β€” and ngl, in recent perls it's also available at runtime β€” and it's the thing you use to implement lexically-scoped features and pragmas. what this function does is give you a convenient way to reach that hash without having to do the bit-twiddling that's needed to enable it on older perls. bestie, we love not touching bits 😭

on top of that, this module loads Lexical::SealRequireHints, which implements the bugfixes required for the correct operation of the hints hash on older perls (< 5.12.0).

the typical move is to call hints from a pragma's import method (and optionally from unimport too):

package MyPragma;

use Devel::Pragma qw(hints);

sub import {
    my $class = shift;
    my $hints = hints;

    if ($hints->{MyPragma}) {
        # ...
    } else {
        $hints->{MyPragma} = ...;
    }

    # ...
}

🧚 new_scope

this one returns true if the scope currently being compiled is different from the scope that was being compiled the last time new_scope was called. and then β€” plot twist β€” subsequent calls will return false while that same scope is still being compiled. so she's basically your little "is this a new scope or nah" detector ✨

new_scope takes an optional parameter that's used to uniquely identify its caller. the usual move is to pass the pragma's class name β€” unless, that is, new_scope is being called by a module that is not intended to be subclassed. like:

package MyPragma;

sub import {
    my ($class, %options) = @_;

    if (new_scope($class)) {
        ...
    }
}

if you don't supply it, the identifier defaults to the name of the calling package. easy πŸ’–

πŸ’œ scope

this returns an integer that uniquely identifies the currently-compiling scope. use it to distinguish or compare scopes.

⚠️ heads up bestie: a warning is issued if scope (or new_scope) is called in a context in which it doesn't make sense β€” i.e. if the scoped behaviour of %^H has not been enabled. and how would it have been enabled? either by explicitly modifying $^H, or by calling hints. that's it. that's the list.

πŸ’€ ccstash

returns the name of the currently-compiling package (stash). important: it only works inside code that's being required β€” either in a BEGIN block via use, or at runtime. so in practice, keep her on a compile-time leash: import methods, and any other methods/functions that can be traced back to import. iykyk 🫢

and when she's called from code that isn't being required? she returns undef. no cap.

you can use her as a replacement for the scalar form of caller to get the name of the package in which use MyPragma was called. and here's the slay: unlike caller, she returns the same value regardless of the number of intervening calls before MyPragma::import is reached. immaculate consistency πŸ’…

package Caller;

use Callee;

package Callee;

use Devel::Pragma qw(ccstash);

sub import {
    A();
}

sub A() {
    B();
}

sub B {
    C();
}

sub C {
    say ccstash; # Caller
}

🌈 fqname

takes a subroutine name and an optional caller (a package name). if you don't hand her a caller, it defaults to ccstash β€” which means fqname needs to be called from import (or from a function/method that can be traced back to import).

she returns the supplied name in package-qualified form. and bonus: old-style ' separators get converted to new-style ::. glow-up behaviour 🌟

the rules, bestie:

  • if the name contains no separators, then the caller/ccstash package name is prepended.
  • if the name is already package-qualified, it's returned unchanged.

and the context thing matters:

  • in list context, fqname returns the package and unqualified subroutine name (e.g. 'Foo::Bar' and 'baz'), and
  • in scalar context it returns the package and sub name joined by '::' (e.g. 'Foo::Bar::baz').

e.g.

package MyPragma::Loader;

use MyPragma (\&coderef, 'foo', 'MyPragmaLoader::bar');

package MyPragma;

sub import {
    my ($class, @listeners) = @_;
    my @subs;

    for my $listener (@listeners) {
        push @subs, handle_sub($listener);
    }
}

sub handle_sub {
    my $sub = shift

    if (ref($ub) eq 'CODE') {
        return $sub;
    } else {
        handle_name($sub);
    }
}

sub handle_name {
    my ($package, $name) = fqname($name); # uses ccstash e.g. foo -> MyPragma::Loader::foo
    my $sub = $package->can($name);
    die "no such sub: $package\::$name" unless ($sub);
    return $sub;
}

⭐ VERSION ⭐

1.1.0


πŸ“ SEE ALSO πŸ“


🌸 AUTHOR 🌸

chocolateboy <chocolate@cpan.org>


Copyright (C) 2008-2016 by chocolateboy

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.1 or, at your option, any later version of Perl 5 you may have available.


and that's the whole page babes πŸ₯Ή she was baked into perl v5.42.3 and dated 2026-08-20, filed under Devel::Pragma(3pm) β€” go forth and write the most lexically-scoped pragmas of your life, bestie πŸ’…βœ¨

πŸ“¦ where this page comes from