PERLPRAGMA(1)

πŸ’– PERLPRAGMA πŸ’–

okay bestie, so this is the perlpragma page from the Perl Programmers Reference Guide β€” it's literally the whole tutorial on how to write your own user pragma, and it's giving main character energy. let's go 🫢


✨ NAME ✨

perlpragma β€” how to write a user pragma πŸŽ€


🌸 DESCRIPTION 🌸

okay so first things first: a pragma is a module that messes with some aspect of Perl's compile time or run time behaviour. think strict, think warnings β€” iconic behaviour modifiers, you know the vibe.

and here's the slay: starting with Perl 5.10 you are no longer limited to the built-in pragmata. nope! you can now create your own user pragmata that modify the behaviour of user functions inside a lexical scope. it's giving power, it's giving control, it's giving your code, your rules. periodt. πŸ’…


πŸ¦‹ A basic example πŸ¦‹

say you need to build a class that implements overloaded mathematical operators, and you want to ship your very own pragma that works basically like use integer;. so like, you'd want this code:

use MyMaths;

my $l = MyMaths->new(1.2);
my $r = MyMaths->new(3.4);

print "A: ", $l + $r, "\n";

use myint;
print "B: ", $l + $r, "\n";

{
    no myint;
    print "C: ", $l + $r, "\n";
}

print "D: ", $l + $r, "\n";

no myint;
print "E: ", $l + $r, "\n";

to spit out this:

A: 4.6
B: 4
C: 4.6
D: 4
E: 4.6

so basically i.e., wherever use myint; is in effect, addition operations get forced to integer, and by default they absolutely are not. and then the default behaviour gets restored again via no myint;. the way that scoping just… works?? obsessed. 😭✨

the minimal implementation of the package MyMaths would look something like this:

package MyMaths;
use v5.36;
use myint();
use overload '+' => sub {
    my ($l, $r) = @_;
    # Pass 1 to check up one call level from here
    if (myint::in_effect(1)) {
        int($$l) + int($$r);
    } else {
        $$l + $$r;
    }
};

sub new {
    my ($class, $value) = @_;
    bless \$value, $class;
}

1;
bestie, notice how we load the user pragma myint with an empty list () β€” that's on purpose! it prevents its import from being called. no accidental import calls here, we're too smart for that πŸ§ πŸ’…

the actual interaction with Perl's compilation happens inside package myint:

package myint;

use v5.36;

sub import {
    $^H{"myint/in_effect"} = 1;
}

sub unimport {
    $^H{"myint/in_effect"} = 0;
}

sub in_effect {
    my $level = shift // 0;
    my $hinthash = (caller($level))[10];
    return $hinthash->{"myint/in_effect"};
}

1;

since pragmata are implemented as modules β€” like literally any other module β€” use myint; turns into:

BEGIN {
    require myint;
    myint->import();
}

and no myint; turns into:

BEGIN {
    require myint;
    myint->unimport();
}

so yeah, the import and unimport routines get called at compile time for the user's code. that's the whole trick, it's not even sneaky, it's just elegant. ⭐

user pragmata store their state by writing to the magical hash %^H, which is why those two routines manipulate it. the state info inside %^H is stored in the optree, and you can retrieve it read-only at runtime with caller(), at index 10 of the list of returned results. πŸ”₯

in our example pragma, the retrieval gets wrapped up all cozy into the routine in_effect(), which takes as its parameter the number of call frames to go up to find the value of the pragma in the user's script. it uses caller() to figure out the value of $^H{"myint/in_effect"} back when each line of the user's script was called β€” and therefore provides the correct semantics in the subroutine implementing the overloaded addition. see? it all connects. iykyk πŸ’œ


πŸ”‘ Key naming πŸ”‘

there is only one single %^H, but arbitrarily many modules that want to use its scoping semantics. so to avoid stepping on each other's toes (rude!), they gotta make sure they use different keys in the hash. 🫢

so the convention is: a module should only use keys that begin with the module's name (that's the name of its main package) followed by a / character. after that module-identifying prefix, the rest of the key is entirely up to the module β€” it can include literally any characters whatsoever, go feral bestie. πŸ’…

for example, a module Foo::Bar should use keys such as Foo::Bar/baz and Foo::Bar/$%/_!. modules that follow this convention all play nicely with each other, no drama, no collisions. ✨

the Perl core uses a handful of keys in %^H that do not follow this convention β€” but that's only because they predate it. and good news: keys that do follow the convention won't conflict with the core's historical keys. so you're safe, bestie. 🌸


🧠 Implementation details 🧠

okay so the optree is shared between threads. which means there's a real possibility that the optree will outlive the particular thread (and therefore the interpreter instance) that created it. so true Perl scalars cannot be stored in the optree. no cap. 😭

instead, a compact form is used, and it can only store values that are:

  • integers (signed and unsigned)
  • strings
  • undef

references and floating point values get stringified. so if you need to store multiple values or complex structures, you should serialise them β€” for example with pack. the deletion of a hash key from %^H is recorded, and as ever it can be distinguished from the existence of a key with value undef using exists. πŸ’…

⚠️ do NOT attempt to store references to data structures as integers which are retrieved via caller and converted back. this will not be threadsafe. accesses would be to the structure without locking (which is not safe for Perl's scalars), and either the structure has to leak, or it has to be freed when its creating thread terminates β€” which may be before the optree referencing it is deleted, if other threads outlive it. like, genuinely, don't. πŸ™ˆ

and that's the whole page bestie, you're officially a pragma author now, go write something iconic πŸ‘‘

perl v5.42.3 Β· 2026-08-03 Β· mwah πŸ’‹ πŸŽ€πŸ¦‹βœ¨

πŸ“¦ where this page comes from