Monkey::Patch(3pm)

πŸ“¦
version 0.03 Β· 2 versions
  • 0.03 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking (latest)
  • 0.03 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– Monkey::Patch πŸ’–

okay so bestie, gather round 🫢 β€” this is Monkey::Patch, a Perl module for scoped monkeypatching. And the tagline? "(you can at least play nice)" β€” like, we're gonna mess with other people's subs, but we're gonna be ✨polite✨ about it. Iconic behaviour, honestly.

It lives in the User Contributed Perl Documentation, and you already know it's serving Monkey::Patch(3pm) realness. πŸ’…


🌸 VERSION 🌸

version 0.03 β€” yes she's smol, yes she's mighty. πŸŽ€


πŸ¦‹ SYNOPSIS πŸ¦‹

use Monkey::Patch qw(:all);

sub some_subroutine {
    my $pkg = patch_class 'Some::Class' => 'something' => sub {
        my $original = shift;
        say "Whee!";
        $original->(@_);
    };
    Some::Class->something(); # says Whee! and does whatever
    undef $pkg;
    Some::Class->something(); # no longer says Whee!

    my $obj = Some::Class->new;
    my $obj2 = Some::Class->new;

    my $whoah = patch_object $obj, 'twiddle' => sub {
        my $original = shift;
        my $self     = shift;
        say "Whoah!";
        $self->$original(@_);
    };

    $obj->twiddle();  # says Whoah!
    $obj2->twiddle(); # doesn't
    $obj->twiddle()   # still does
    undef $whoah;
    $obj->twiddle();  # but not any more

see how the vibes just… switch back? that's the whole point. the moment you undef the handle, the patch is GONE. main character exits stage left. πŸ’€βœ¨


🌈 SUBROUTINES 🌈

These are the icons you can grab β€” either one at a time, or all together via :all. no gatekeeping. 🫢

✨ patch_package (package, subname, code) ✨

Wraps package's subroutine named subname with your code. πŸ’«

Your code gets the original subroutine as its first argument, followed by every argument the subroutine would've normally gotten anyway. So you always have the original coderef in hand and you can absolutely call it whenever you want.

tiny little thing though: if there was no subroutine by that name in the first place, that coderef will just… do nothing. silently. 🫠 no drama, no error, just vibes.

πŸŽ€ patch_class (class, methodname, code) πŸŽ€

Literally patch_package, except β€” and here's the slay β€” the @ISA chain gets walked when you try to call the original subroutine, in case there wasn't any subroutine by that name sitting directly in the package. inheritance found, bestie. πŸ‘‘

πŸ’œ patch_object (object, methodname, code) πŸ’œ

Same energy as patch_class, except your code only fires for the one object you passed, not the whole entire class. 🫢 one special little guy. no collateral damage.


🧚 HANDLES 🧚

Every single one of the patch functions hands you back a handle object. And the way that handle works is genuinely the whole trick: the second you lose the value of the handle, the monkey patch is unwrapped. 😭

How do you "lose" it? Many ways, bestie:

  • calling in void context πŸ’€
  • assigning over the variable
  • undef-ing the variable
  • just letting it go out of scope

All of those count. All of them un-patch. πŸ¦‹

And here's the part that ate: you can stack monkeypatches and let go of the handles in any order you want β€” they obey a stack discipline, and the most recent valid monkeypatch is always the one that gets called. πŸ₯žβœ¨

Oh and when you call that original argument inside your wrapper routine? It always calls the next-most-recent monkeypatched version. Or, y'know, the original subroutine. whichever is next in line. 🫑


πŸ’€ BUGS πŸ’€

okay so. this magic is only faintly black β€” but mucking around with the symbol table is not for the faint of heart, and I mean that fr fr. 😭

If you see any strange behavior, report it! That's how this module gets better. be the change. 🫢

and that's the whole page, bestie β€” she's short, she's sweet, she'll rewrite your methods behind your back and then quietly put them back. πŸ’…

this documentation came to you courtesy of perl v5.36.0, dated 2022-11-29, and filed under Monkey::Patch(3pm). mwah πŸ’– go patch something responsibly ✨

πŸ“¦ where this page comes from