Shortcuts: s show h hide n next p prev

The first PAGI compliant web framework on CPAN

r/perl

I was excited to see https://metacpan.org/pod/Thunderhorse land on CPAN recently. The author has been feeding me tons of questions and issue reports on the PAGI Github and I feel the work to get this out has really helped to smooth down some of the rough edges.

Although there's nothing stopping you from building PAGI applications directly on the protocol, it can be somewhat verbose and less structured then you might prefer for a larger application. In that way PAGI servers the same role as PSGI did for Catalyst, Dancer and other web frameworks build on that older specification. Hopefully adapters for those legacy frameworks will eventually happen, allowing older, existing apps to play nice in the event driven world.

submitted by /u/jnapiorkowski
[link] [comments]

App::HTTPThis: the tiny web server I keep reaching for

Perl Hacks

Whenever I’m building a static website, I almost never start by reaching for Apache, nginx, Docker, or anything that feels like “proper infrastructure”. Nine times out of ten I just want a directory served over HTTP so I can click around, test routes, check assets, and see what happens in a real browser.

For that job, I’ve been using App::HTTPThis for years.

It’s a simple local web server you run from the command line. Point it at a directory, and it serves it. That’s it. No vhosts. No config bureaucracy. No “why is this module not enabled”. Just: run a command and you’ve got a website.

Why I’ve used it for years

Static sites are deceptively simple… right up until they aren’t.

  • You want to check that relative links behave the way you think they do.

  • You want to confirm your CSS and images are loading with the paths you expect.

  • You want to reproduce “real HTTP” behaviour (caching headers, MIME types, directory handling) rather than viewing files directly from disk.

Sure, you can open file:///.../index.html in a browser, but that’s not the same thing as serving it over HTTP. And setting up Apache (or friends) feels like bringing a cement mixer to butter some toast.

With http_this, the workflow is basically:

  • cd into your site directory

  • run a single command

  • open a URL

  • get on with your life

It’s the “tiny screwdriver” that’s always on my desk.

Why I took it over

A couple of years ago, the original maintainer had (entirely reasonably!) become too busy elsewhere and the distribution wasn’t getting attention. That happens. Open source is like that.

But I was using App::HTTPThis regularly, and I had one small-but-annoying itch: when you visited a directory URL, it would always show a directory listing – even if that directory contained an index.html. So instead of behaving like a typical web server (serve index.html by default), it treated index.html as just another file you had to click.

That’s exactly the sort of thing you notice when you’re using a tool every day, and it was irritating enough that I volunteered to take over maintenance.

(If you want to read more on this story, I wrote a couple of blog posts.)

What I’ve done since taking it over

Most of the changes are about making the “serve a directory” experience smoother, without turning it into a kitchen-sink web server.

1) Serve index pages by default (autoindex)

The first change was to make directory URLs behave like you’d expect: if index.html exists, serve it automatically. If it doesn’t, you still get a directory listing.

2) Prettier index pages

Once autoindex was in place, I then turned my attention to the fallback directory listing page. If there isn’t an index.html, you still need a useful listing — but it doesn’t have to look like it fell out of 1998. So I cleaned up the listing output and made it a bit nicer to read when you do end up browsing raw directories.

3) A config file

Once you’ve used a tool for a while, you start to realise you run it the same way most of the time.

A config file lets you keep your common preferences in one place instead of re-typing options. It keeps the “one command” feel, but gives you repeatability when you want it.

4) --host option

The ability to control the host binding sounds like an edge case until it isn’t.

Sometimes you want:

  • only localhost access for safety;

  • access from other devices on your network (phone/tablet testing);

  • behaviour that matches a particular environment.

A --host option gives you that control without adding complexity to the default case.

The Bonjour feature (and what it’s for)

This is the part I only really appreciated recently: App::HTTPThis can advertise itself on your local network using mDNS / DNS-SD – commonly called Bonjour on Apple platforms, Avahi on Linux, and various other names depending on who you’re talking to.

It’s switched on with the --name option.

http_this --name MyService

When you do that, http_this publishes an _http._tcp service on your local network with the instance name you chose (MyService in this case). Any device on the same network that understands mDNS/DNS-SD can then discover it and resolve it to an address and port, without you having to tell anyone, “go to http://192.168.1.23:7007/”.

Confession time: I ignored this feature for ages because I’d mentally filed it under “Apple-only magic” (Bonjour! very shiny! probably proprietary!). It turns out it’s not Apple-only at all; it’s a set of standard networking technologies that are supported on pretty much everything, just under a frankly ridiculous number of different names. So: not Apple magic, just local-network service discovery with a branding problem.

Because I’d never really used it, I finally sat down and tested it properly after someone emailed me about it last week, and it worked nicely, nicely enough that I’ve now added a BONJOUR.md file to the repo with a practical explanation of what’s going on, how to enable it, and a few ways to browse/discover the advertised service.

(If you’re curious, look for _http._tcp and your chosen service name.)

It’s a neat quality-of-life feature if you’re doing cross-device testing or helping someone else on the same network reach what you’re running.

Related tools in the same family

App::HTTPThis is part of a little ecosystem of “run a thing here quickly” command-line apps. If you like the shape of http_this, you might also want to look at these siblings:

  • https_this : like http_this, but served over HTTPS (useful when you need to test secure contexts, service workers, APIs that require HTTPS, etc.)

  • cgi_this : for quick CGI-style testing without setting up a full web server stack

  • dav_this : serves content over WebDAV (handy for testing clients or workflows that expect DAV)

  • ftp_this : quick FTP server for those rare-but-real moments when you need one

They all share the same basic philosophy: remove the friction between “I have a directory” and “I want to interact with it like a service”.

Wrapping up

I like tools that do one job, do it well, and get out of the way. App::HTTPThis has been that tool for me for years and it’s been fun (and useful) to nudge it forward as a maintainer.

If you’re doing any kind of static site work — docs sites, little prototypes, generated output, local previews — it’s worth keeping in your toolbox.

And if you’ve got ideas, bug reports, or platform notes (especially around Bonjour/Avahi weirdness), I’m always happy to hear them.

The post App::HTTPThis: the tiny web server I keep reaching for first appeared on Perl Hacks.

Whenever I’m building a static website, I almost never start by reaching for Apache, nginx, Docker, or anything that feels like “proper infrastructure”. Nine times out of ten I just want a directory served over HTTP so I can click around, test routes, check assets, and see what happens in a real browser.

For that job, I’ve been using App::HTTPThis for years.

It’s a simple local web server you run from the command line. Point it at a directory, and it serves it. That’s it. No vhosts. No config bureaucracy. No “why is this module not enabled”. Just: run a command and you’ve got a website.

Why I’ve used it for years

Static sites are deceptively simple… right up until they aren’t.

  • You want to check that relative links behave the way you think they do.

  • You want to confirm your CSS and images are loading with the paths you expect.

  • You want to reproduce “real HTTP” behaviour (caching headers, MIME types, directory handling) rather than viewing files directly from disk.

Sure, you can open file:///.../index.html in a browser, but that’s not the same thing as serving it over HTTP. And setting up Apache (or friends) feels like bringing a cement mixer to butter some toast.

With http_this, the workflow is basically:

  • cd into your site directory

  • run a single command

  • open a URL

  • get on with your life

It’s the “tiny screwdriver” that’s always on my desk.

Why I took it over

A couple of years ago, the original maintainer had (entirely reasonably!) become too busy elsewhere and the distribution wasn’t getting attention. That happens. Open source is like that.

But I was using App::HTTPThis regularly, and I had one small-but-annoying itch: when you visited a directory URL, it would always show a directory listing - even if that directory contained an index.html. So instead of behaving like a typical web server (serve index.html by default), it treated index.html as just another file you had to click.

That’s exactly the sort of thing you notice when you’re using a tool every day, and it was irritating enough that I volunteered to take over maintenance.

(If you want to read more on this story, I wrote a couple of blog posts.)

What I’ve done since taking it over

Most of the changes are about making the “serve a directory” experience smoother, without turning it into a kitchen-sink web server.

1) Serve index pages by default (autoindex)

The first change was to make directory URLs behave like you’d expect: if index.html exists, serve it automatically. If it doesn’t, you still get a directory listing.

2) Prettier index pages

Once autoindex was in place, I then turned my attention to the fallback directory listing page. If there isn’t an index.html, you still need a useful listing — but it doesn’t have to look like it fell out of 1998. So I cleaned up the listing output and made it a bit nicer to read when you do end up browsing raw directories.

3) A config file

Once you’ve used a tool for a while, you start to realise you run it the same way most of the time.

A config file lets you keep your common preferences in one place instead of re-typing options. It keeps the “one command” feel, but gives you repeatability when you want it.

4) --host option

The ability to control the host binding sounds like an edge case until it isn’t.

Sometimes you want:

  • only localhost access for safety;

  • access from other devices on your network (phone/tablet testing);

  • behaviour that matches a particular environment.

A --host option gives you that control without adding complexity to the default case.

The Bonjour feature (and what it’s for)

This is the part I only really appreciated recently: App::HTTPThis can advertise itself on your local network using mDNS / DNS-SD – commonly called Bonjour on Apple platforms, Avahi on Linux, and various other names depending on who you’re talking to.

It’s switched on with the --name option.

http_this --name MyService

When you do that, http_this publishes an _http._tcp service on your local network with the instance name you chose (MyService in this case). Any device on the same network that understands mDNS/DNS-SD can then discover it and resolve it to an address and port, without you having to tell anyone, “go to http://192.168.1.23:7007/”.

Confession time: I ignored this feature for ages because I’d mentally filed it under “Apple-only magic” (Bonjour! very shiny! probably proprietary!). It turns out it’s not Apple-only at all; it’s a set of standard networking technologies that are supported on pretty much everything, just under a frankly ridiculous number of different names. So: not Apple magic , just local-network service discovery with a branding problem.

Because I’d never really used it, I finally sat down and tested it properly after someone emailed me about it last week, and it worked nicely, nicely enough that I’ve now added a BONJOUR.md file to the repo with a practical explanation of what’s going on, how to enable it, and a few ways to browse/discover the advertised service.

(If you’re curious, look for _http._tcp and your chosen service name.)

It’s a neat quality-of-life feature if you’re doing cross-device testing or helping someone else on the same network reach what you’re running.

Related tools in the same family

App::HTTPThis is part of a little ecosystem of “run a thing here quickly” command-line apps. If you like the shape of http_this, you might also want to look at these siblings:

  • https_this : like http_this, but served over HTTPS (useful when you need to test secure contexts, service workers, APIs that require HTTPS, etc.)

  • cgi_this : for quick CGI-style testing without setting up a full web server stack

  • dav_this : serves content over WebDAV (handy for testing clients or workflows that expect DAV)

  • ftp_this : quick FTP server for those rare-but-real moments when you need one

They all share the same basic philosophy: remove the friction between “I have a directory” and “I want to interact with it like a service”.

Wrapping up

I like tools that do one job, do it well, and get out of the way. App::HTTPThis has been that tool for me for years and it’s been fun (and useful) to nudge it forward as a maintainer.

If you’re doing any kind of static site work — docs sites, little prototypes, generated output, local previews — it’s worth keeping in your toolbox.

And if you’ve got ideas, bug reports, or platform notes (especially around Bonjour/Avahi weirdness), I’m always happy to hear them.

The post App::HTTPThis: the tiny web server I keep reaching for first appeared on Perl Hacks.

A jq-compatible JSON processor written in pure Perl, designed for environments where jq cannot be installed.

(dlxxxi) 8 great CPAN modules released last week

r/perl

(dlxxxi) 8 great CPAN modules released last week

Niceperl
Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::cpm - a fast CPAN module installer
    • Version: 0.998003 on 2025-12-29, with 177 votes
    • Previous CPAN version: 0.998002 was 24 days before
    • Author: SKAJI
  2. App::Greple - extensible grep with lexical expression and region handling
    • Version: 10.01 on 2025-12-31, with 56 votes
    • Previous CPAN version: 10.00 was 19 days before
    • Author: UTASHIRO
  3. App::Music::ChordPro - A lyrics and chords formatting program
    • Version: v6.090.1 on 2026-01-03, with 432 votes
    • Previous CPAN version: v6.090.0 was 2 months, 3 days before
    • Author: JV
  4. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251228.001 on 2025-12-29, with 25 votes
    • Previous CPAN version: 20251221.001 was 7 days before
    • Author: BRIANDFOY
  5. DBD::SQLite - Self Contained SQLite RDBMS in a DBI Driver
    • Version: 1.78 on 2026-01-02, with 107 votes
    • Previous CPAN version: 1.76 was 1 year, 2 months, 14 days before
    • Author: ISHIGAKI
  6. Module::Starter - a simple starter kit for any module
    • Version: 1.79 on 2026-01-03, with 33 votes
    • Previous CPAN version: 1.78 was 7 months, 30 days before
    • Author: XSAWYERX
  7. Type::Tiny - tiny, yet Moo(se)-compatible type constraint
    • Version: 2.010000 on 2025-12-30, with 148 votes
    • Previous CPAN version: 2.009_003 was 7 days before
    • Author: TOBYINK
  8. WebService::Dropbox - Perl interface to Dropbox API
    • Version: 2.10 on 2025-12-29, with 12 votes
    • Previous CPAN version: 2.09 was 4 years, 6 months, 14 days before
    • Author: ASKADNA

I don't think I would have managed it without AI.

The script just started working today.

It's an MCP server that allows OpenCode to view the console output (text only) of a Qemu/KVM (libvirt) virtual machine (the standard for open-source virtual machines).

For now, LLM has to poll using the read function every time it writes something to the console. I also implemented notifications to avoid this polling, but it doesn't seem to be working. Or maybe OpenCode doesn't handle notifications well enough yet (more research is needed).

Anyway. LLM can see when a VM starts, the kernel starts, etc. And it can even send commands. I find it incredibly useful when SSH isn't available or when you want to debug a Linux system from the GRUB stage.

If you have any ideas for improvements, feel free to share them.

I'm not a Perl guru yet!

https://github.com/abda11ah/serencp


[link] [comments]
perlhacktips: Note // comment-style breaks CPAN

Use /*.../* comment-style in handy.h

Perl commits on GitHub
Use /*.../* comment-style in handy.h

Fixes #24018

Modern tooling often assumes a perfect world:
latest Linux, internet access, package managers, and rebuildable binaries.

Reality is different.

In many production environments — especially enterprise, legacy, or air-gapped systems —
those assumptions break down.

That gap is why I built jq-lite.

The Problem: jq Is Great — Until You Can’t Use It

jq is an excellent JSON processor.
But in real operations, I kept hitting walls:

Legacy UNIX systems with outdated glibc

Air-gapped environments with no package repositories

Minimal containers without build tools

Environments where “just install jq” was not an option

In those cases, JSON processing didn’t disappear —
the need became more critical.

Shell scripts still had to be reliable.
Automation still had to work.

The Idea: A jq-Compatible Tool That Never Breaks Scripts

I didn’t want another JSON tool.

I wanted a tool that could be:

Dropped into restricted systems

Trusted in shell scripts

Stable across years, not releases

So I built jq-lite with three strict rules:

Design Rule #1: Pure Perl, No Dependencies

jq-lite is written in pure Perl.

No native extensions

No external libraries

No compilation step

If Perl exists, jq-lite runs.

That means it works on:

legacy Linux / UNIX

minimal containers

offline environments

systems where only base OS tools are allowed

Perl is still one of the most widely deployed runtimes in the world —
especially in places modern tooling forgot.

Design Rule #2: jq Compatibility Where It Matters

jq-lite aims to be jq-compatible in daily CLI usage:

echo '{}' | jq-lite --arg greeting hello '.hello = $greeting'

Output:

{
"hello": "hello"
}

The goal isn’t to clone every feature,
but to support the jq patterns people actually use in automation.

Design Rule #3: A Stable CLI Contract (This Is the Important Part)

Here’s the part that made jq-lite different.

jq-lite defines a documented CLI contract:

exit codes

error categories

stderr prefixes

stdout behavior on failure

And that contract is tested.

Exit Code Meaning

0 Success
1 -e used and result was false / null / empty
2 Compile error
3 Runtime error
4 Input error
5 Usage error

This means shell scripts can safely rely on jq-lite:

if jq-lite -e '.enabled' config.json; then
deploy
fi

No surprises.
No silent behavior changes.

In operations, this matters more than features.

Why Not Rewrite It in Rust or Go?

I get this question a lot.

Because the problem wasn’t performance or language fashion.

The problem was deployability and longevity.

Perl already exists on:

old servers

enterprise systems

restricted environments

Adding jq-lite doesn’t require changing the environment —
just using what’s already there.

Who Is jq-lite For?

jq-lite is not for everyone.

It is for people who:

maintain legacy systems

write shell scripts that must survive years

operate in restricted or offline environments

care about CLI behavior as a contract, not a suggestion

If you’ve ever thought
“this script must not break in five years”
— jq-lite is for you.

Where to Find It

GitHub: https://github.com/kawamurashingo/JQ-Lite

CLI Contract: https://github.com/kawamurashingo/JQ-Lite/blob/main/docs/cli-contract.md

CPAN: https://metacpan.org/release/JQ-Lite

Alpine Linux package available

Final Thought

Modern tools optimize for speed of change.

jq-lite optimizes for stability over time.

Sometimes, that’s the more important optimization.

Author
川村慎吾(Shingo Kawamura)
SRE / Infrastructure Engineer
CPAN author of jq-lite

Weekly Challenge: New Year, New Challenges

dev.to #perl

Weekly Challenge 354

Happy New Years everyone.

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Min Abs Diff

Task

You are given an array of distinct integers.

Write a script to find all pairs of elements with the minimum absolute difference.

Rules (a,b):

  1. a, b are from the given array.
  2. a < b
  3. b - a = min abs diff any two elements in the given array

My solution

This is relatively straight forward. I start by sorting the array numerically. I create two variables. The result list (array in Perl) will store matching pairs. min_abs_diff will store the numerical difference between the two values in a pair, it starts as None (undef in Perl).

def min_abs_diff(ints: list) -> list:
    ints = sorted(ints)
    min_abs_diff = None
    result = []

I then use a loop that starts with 0 to two less than the length of the input list. For each iteration, I compute the difference between the value at the position and following position, using the variable abs_diff.

If the value is less than the current min_abs_diff value (or min_abs_diff is None), I update the variable and set the result array with this pair. If the value is the same, I append this pair to the result array.

    for i in range(len(ints) - 1):
        abs_diff = ints[i + 1] - ints[i]
        if min_abs_diff is None or abs_diff < min_abs_diff:
            min_abs_diff = abs_diff
            result = [[ints[i], ints[i + 1]]]
        elif abs_diff == min_abs_diff:
            result.append([ints[i], ints[i + 1]])

    return result

The Perl code follows the same logic.

Examples

$ ./ch-1.py 4 2 1 3
[[1, 2], [2, 3], [3, 4]]

$ ./ch-1.py 10 100 20 30
[[10, 20], [20, 30]]

$ ./ch-1.py -5 -2 0 3
[[-2, 0]]

$ ./ch-1.py 8 1 15 3
[[1, 3]]

$ ./ch-1.py 12 5 9 1 15
[[9, 12], [12, 15]]

Task 2: Shift Grid

Task

You are given m x n matrix and an integer, $k > 0.

Write a script to shift the given matrix $k times.

My solution

For input from the command line, I take a JSON string as the first value (representing the matrix) and the second value as k.

These are the steps I take to complete the task.

  1. Ensure that the matrix has the same number of columns for each row.
  2. Flatten the list of lists (array of arrays in Perl) into a single list, stored as the flattened_list variable.
  3. If k is not between 0 and one less than the array, take the modulus of the length of flatten_list. For example is k is 7 and there are five items in the flattened list, change it to 2. This will achieve the same result.
  4. Take the last k elements from the list, and append them to the front. In the Python solution, this is stored as rotated_list.
  5. Rebuild the matrix from this new list as the variable new_matrix.
def shift_grid(matrix: list[list[int]], k: int) -> list[list[int]]:
    row_length = len(matrix[0])
    for row in matrix:
        if len(row) != row_length:
            raise ValueError("All rows must have the same length")

    flattened_list = [num for row in matrix for num in row]
    k = k % len(flattened_list)
    rotated_list = flattened_list[-k:] + flattened_list[:-k]

    new_matrix = []
    for i in range(0, len(rotated_list), row_length):
        new_matrix.append(rotated_list[i:i + row_length])

    return new_matrix

Since Perl allows you to remove and append to the same list in a single operation, I use the splice function to achieve this.

sub main ( $matrix_json, $k ) {
    my $matrix = decode_json($matrix_json);

    my $row_length = scalar( @{ $matrix->[0] } );
    foreach my $row (@$matrix) {
        if ( scalar(@$row) != $row_length ) {
            die "All rows must have the same length\n";
        }
    }

    my @flattened_list = map { @$_ } @$matrix;
    $k = $k % scalar(@flattened_list);
    splice( @flattened_list, 0, 0, splice( @flattened_list, -$k ) );

    my @new_matrix = ();
    for ( my $i = 0 ; $i <= $#flattened_list ; $i += $row_length ) {
        push @new_matrix, [ @flattened_list[ $i .. $i + $row_length - 1 ] ];
    }

    say '('
        . join( ",\n ",
            map { '[' . join( ', ', @$_ ) . ']' } @new_matrix )
      . ',)';
}

Examples

$ ./ch-2.py "[[1, 2, 3], [4, 5, 6], [7, 8, 9]]" 1
([9, 1, 2],
 [3, 4, 5],
 [6, 7, 8],)

$ ./ch-2.py "[[10, 20], [30, 40]]" 1
([40, 10],
 [20, 30],)

$ ./ch-2.py "[[1, 2], [3, 4], [5, 6]]" 1
([6, 1],
 [2, 3],
 [4, 5],)

$ ./ch-2.py "[[1, 2, 3], [4, 5, 6]]" 5
([2, 3, 4],
 [5, 6, 1],)

$ ./ch-2.py "[[1, 2, 3, 4]]" 1
([4, 1, 2, 3],)

Downloading Strawberry Perl Tk [closed]

Perl questions on StackOverflow

I am trying to install perl Tk on my Win 11 system. Perl otherwise works fine.

Strawberry Perl vs 42, v5.42.0, for MSWin32-x64-multi-thread

Is this an appropriate Perl Windows version for Tk?

Using a Developer PowerShell for Win11. Installation proceeds through many lines, then crashes as follows:

In file included from ../pTk/mTk/xlib/X11/Xlib.h:31,
                from tkWinPort.h:19,
                from tkPort.h:32,
                from tk.h:87,
                from imgBMP.c:11:
../pTk/mTk/xlib/X11/X.h:182:34: error: expected identifier or '(' before numeric constant
 182 | #define ControlMask             (1<<2)
     |                                  ^

WHAT is going on here? ...the (1<<2) appears to be a C++ mask for a binary 0b000010 The span between ControlMask and the (1<<2) is many space characters, not tabs. How can a #define statement possibly crash in this way?

There are also compiler errors earlier in config/pmop.c that make no sense:

Test Compiling config/pmop.c
config/pmop.c: In function 'main':
config/pmop.c:7:8: error: 'struct pmop' has no member named 'op_pmdynflags'; did you mean 'op_pmflags'?
    7 |     op.op_pmdynflags = 0;
      |        ^~~~~~~~~~~~~
      |        op_pmflags
config/pmop.c:8:8: error: 'struct pmop' has no member named 'op_pmpermflags'; did you mean 'op_pmflags'?
    8 |     op.op_pmpermflags = 0;
      |        ^~~~~~~~~~~~~~b

It appears that there is some version problem with op.op_pmpermflags ...

**** Has Tk been successfully compiled and installed on a 64 bit Win 11 system? ****

Horror Movie Month 2024

rjbs forgot what he was saying

Yesterday, I posted about the books I read in 2025, which made me remember that I never posted about the (horror) movies we watched in October 2024. So, I thought I’d get around to that. Of course this will be short and lossy, right? It’s been over a year.

Here’s what we watched for Horror Movie Month in 2024, at least according to my notes!

October 1: Raw (2016)

Girl goes to college, finally lets loose by becoming a cannibal. This movie was French and you’d know it even if you watched it dubbed. It was okay. It was worth my time.

October 2: Tragedy Girls (2017)

Two high school girls who are interested in death try to make more of it happen. It was a horror-comedy, and it was fun. Brianna Hildebrand, who you may remember as Negasonic Teenage Warhead, was in it.

October 4: V/H/S/Beyond (2024)

Honestly, apart from the 2025 one, most of the V/H/S movies are about the same to me: mixed bags, but usually not quite worth the whole watch. This one was that too. It had its moments.

October 5: Humanist Vampire Seeking Consenting Suicidal Person (2023)

Honestly, I’d watch just for “Want to see a French-Canadian horror movie?”

A young woman in a family of vampires really doesn’t want to go hunt for blood, but her parents have reluctantly become insistent. She decides she’ll look for somebody who’d be willing to donate.

It was good, and sort of a horror-comedy. It didn’t feel like every other movie, which was good.

October 6: Onyx the Fortuitous and the Talisman of Souls (2023)

I liked this the least of everybody in my household, I think. It was sometimes pretty funny, but the main character got on my nerves. I got the impression he is a YouTube character with some following, maybe? Like Ernest P. Worrell or other over the top “originally in small doses” characters, he was just too much here.

That said, we still make references to the guy’s catch phrase, so it stuck with us.

October 6: Cuckoo (2024)

This was one of the big hits of “general horror movies of 2024”, so I was glad we got to watch it. I liked it! It wasn’t perfect, but it did well at being one of those “Why can’t everybody else see how messed up this lovely place really is?” movies.

October 7: Let the Wrong One In (2021)

This movie was really stupid and I liked it. First off, there was a character named Deco, which made me think of The Commitments, which won points. Also, Anthony Stewart Head.

Basically it’s sort of a slapstick farcical vampire movie set in Ireland. Honestly, “What if [some successful movie] but the protagonists were idiots?” is a pretty good formula.

October 8: The Witches of Eastwick (1987)

Still a classic.

Sure, it’s kind of a mess here and there, but it’s got a great cast and it just goes for it. I read recently that there was talk about casting other people (other than Jack Nicholson) as Daryl Van Horne, which seems like it could only have been worse. One name mentioned was Bill Murray. What?! This was a nearly perfect vehicle for Jack Nicholson doing comedy, and Cher, Susan Sarandon, and Michelle Pfeiffer were a lot of fun, too.

The cherry scene!

October 9: Courtney Gets Possessed (2023)

I barely remember this one. I think it was funny enough? Demonic hijinks at a bachelorette party.

October 10: There’s Something Wrong with the Children (2023)

Two parents, their two kids, and an adult friend take a camping trip. The kids wander off in the woods and when they come back, they are… off. Things keep getting worse.

This was good. It wasn’t great, but it was good. You want to yell, “Wake up, people, your kids are busted!”

October 12: 6:45 (2021)

It took me a while to remember this one. It was okay. A couple take a ill-advised holiday to an island town, which leads to a deadly time loop. It was okay, but there are many better movies to watch instead. (Look, maybe it’s better than I remember, but given I barely remember it…)

October 13: Oddity (2024)

I didn’t remember this until reading the synopsis, but it was quite good. So maybe my “it’s bad because I don’t remember it” take above is wrong!

A woman is murdered at her secluded fixer-upper in the countryside. Later, her twin sister shows up and is really weird. What’s going on? You should just watch it, probably. Not a comedy.

October 14: Mr. Crocket (2024)

This is sort of like “what if there was a haunted video tape that showed you a cutesy TV show for kids, but also it was evil?” I wanted to like it, but it was just ugly. It wasn’t fun or funny, just dark. It wasn’t darkly funny, although maybe that was the goal.

October 15: Evil Dead Ⅱ (1987)

I think we watched this because Marty hadn’t seen it. Look, it’s fine. It’s a lot better than the first version. I think it’s just not exactly my bag. (I really like Bruce Campbell, though!)

October 16: Cube (2021)

I really liked Cube! This is not that movie, though, it’s a 2021 remake from Japan. Don’t bother. It is worse in every way. Maybe it’s okay, but it’s not significantly different, so go with the original.

October 18: Zombie Town (2023)

A reclusive movie director releases one more movie, and it turns everybody in town into zombies. Kids fight back.

This kind of movie could’ve been fun, but it wasn’t. It had two of the Kids in the Hall in it! What a waste.

October 19: The Finale (2023)

Oh yeah, this one.

Murders start happening at a summer theater camp. Everybody has a motive. Who did it?

Well, look, I think this was maybe better than the related Stage Fright, but it was bad. It was way too long. It was sometimes nonsensical. I do not recommend it.

October 19: Invitation to Hell (1984)

This gets huge points from me for “picked a weird premise and didn’t back down.” Wes Craven directs. A family moves to a new planned town where the father has taken a great new job. Everybody is obsessed with the local country club and its manager. Like, weirdly obsessed. What the heck is going on in town? Also, Robert Urich and Susan Lucci? Wild.

Not great, but I am glad I watched it.

October 20: Corporate Animals (2019)

A bunch of coworkers on a team-building exercise end up trapped in a cave. Demi Moore?! We had fun. It was stupid in a good way. The company specialized in edible cutlery, which paid off a few ways.

October 20: Stranger in Our House (1978)

Wes Craven again, this time with Linda Blair. It wasn’t great, sadly, and the concept has been done a bunch of times. Orphaned kid moves in with other family, and only one family member realizes that maybe this is a bad idea. It was… fine.

October 24: Little Evil (2017)

Adam Scott becomes the step-dad to the Antichrist and really tries to make things work. This was not amazing, but it was much better than I expected. I don’t mind having watched it, but I wouldn’t watch it again.

Good job casting the really creepy kid, though!

October 25: Deer Camp ‘86 (2022)

A bunch of guys go hunting and get into trouble. I remember nothing.

October 26: The Day of the Beast (1995)

A priest figures out how to predict the exact birth of the Antichrist, and enlists the help of a headbanger and a TV occultist to save the world. Was this a comedy on purpose? I just don’t know. It was weird, and unpredictable, and so I liked it.

October 27: The Strangers (2008)

What a lousy movie to end on. It’s a boring, tedious home invasion movie. I see it was 86 minutes long, but I remember it feeling much longer. Also, I think they remade it into a three part movie? I can’t imagine.

I just didn’t care about anyone or anything in this movie.

DBIx::Class::Async - Introduction

blogs.perl.org


Happy New Year to all! I’m sharing this with you in the hope it keeps you entertained on a national holiday. Please follow the link for more information: https://theweeklychallenge.org/blog/dbix-class-async

DBIx::Class::Async

r/perl

the books I read in 2025

rjbs forgot what he was saying

I don’t take the Goodreads “reading challenge” too seriously, but I did hit my target last year, and it felt good. I thought I’d try again this year and I did get it done – only just, though, as I finished my last three books in the last two days of the year. I think I would’ve liked to read a bit more through the year, but sometimes I just wasn’t feeling it. So it goes! I think this is a “structure your time” problem, but also it’s not the most pressing thing on my agenda, you know?

So, here’s what I read, not in order, and some brief notes.

Greg Egan

Last year, I read five Greg Egan books. This year, just two. First, I read The Book of All Skies, which I enjoyed. It’s the story of a group of people investigating the frontiers of their very weirdly-shaped world. As with many Egan books, there’s a lot of very weird math and physics under the hood, but it wasn’t critical to think too hard about them, and I think that made the story more enjoyable for me. In this book, they would’ve gotten in the way. That said, when I finished the book I went and read a bunch of Egan’s notes on the underlying ideas, which were interesting (insofar as I understood them).

Later, I read Schild’s Ladder, which was roughly the opposite. That is, it was one of the most physics-heavy Egan books I’ve read. More than once, I wanted to take photos of the page because it was a wall of thick jargon. I did not enjoy the book. At the beginning, I said, “Oh, this is going to be Egan’s take on Cat’s Cradle!” That would’ve been very interesting, especially because Egan and Vonnegut are so, so different. Or: maybe it was that, but I didn’t care to think about the comparison by the end. It reminded me of Vinge, too, but not in a way that excited me. Anyway, look, I’ve read a lot of Egan, and I will read more. This just didn’t hit home.

Effectiveness

“Effectiveness” is my shelf (or label or tag or whatever they call it now) in Goodreads for books on productivity and management. I have a lot of books in that queue, but I only make slow progress, for many reasons.

My favorite of the ones I read this year, by a long way, was Radical Candor. This is one of those books that I’d read about many times. It sounded not bad, but not amazing. But, of course, I’d only been seeing the shadows on the wall. It was great, and I hope I will go back to it in the future to try to puzzle out more ways to do better at my job. It really resonated with me, and I’ve brought it up over and over when talking to other managers, this year.

I also read Laziness Does Not Exist, which I didn’t love. It was okay. I feel the author would probably just give me a knowing “don’t you hear yourself??” look, but I kept wanting to say, “Yes, don’t work yourself sick, but honestly you are going too far.” I think the issue is that an indictment of a society-wide problem requires a massive-scaled critique. But “the Laziness Lie has you in its grip!”, over and over, was too much for me. (It was also funny that I finished this book just today, December 31st, and it had text saying “Don’t get worked up trying to meet your Goodreads goals”!)

Finally, as I wanted to get a bit more handle on some of my team’s rituals, I read Liftoff: Start and Sustain Agile Teams. I found it totally unremarkable, so I have no remarks.

Boss Fight Books

Boos Fight Books publishes short books about influential or otherwise important video games. The books are written by people who found the books to be important to them.

The first one I read was Animal Crossing by Kelsey Lewin. I’ve played all the main Animal Crossing games and have enjoyed them all. (Well, no, the iOS one was awful.) This book, at a pleasing 2⁸ pages, talked about the origin of the game, its weird launch history starting with the Nintendo64 DD, how it changed over time, and how the author enjoyed it (or didn’t) over time. I enjoyed the book, and felt like I’d read more like this – but it was also clear that a lot of the book was about the author’s life, which wasn’t really what I wanted. So, it wasn’t a bad book, it just wasn’t exactly what I wanted.

PaRappa the Rapper and ZZT books, which were similarly a mix of “I am very interested!” and “I am not particularly interested”. I knew what I was getting into, though, so I had no complaint for the authors. I just sort of wish there were more books about these games, focused more exclusively on the history and technology behind them.

I was surprised by how few of my peers remembered ZZT. I remember it being both impressive and influential. I was also surprised to learn how programmable its world builder was, and that ZZT (the game)’s author was that Tim Sweeney. (The book’s author was Anna Anthropy, which was one of the reasons I wanted to read this book.)

Finally, I read the book on Spelunky. I almost didn’t, but then I saw that the author was Derek Yu, also the primary creator of Spelunky itself! This book was by far closest to what I’d want from these books, if I was in charge. I got a copy for my nephews, too, who I introduced to the game a few years ago.

Stephen King

I read three Stephen King books this year, all story collections. I’ve been trying to catch up on reading all his story collections, and I’m very nearly done, now.

First, Four Past Midnight, from 1990. It contains four novellas, all of which I liked okay. I read it in part because I’d been doing some idle research into King’s repeated setting of Castle Rock, and saw that The Sun Dog (a story in this collection) was in some ways tied up with Needful Things.

After that, I read Hearts in Atlantis. This was a frustrating experience, because I kept thinking that maybe I’d read it already, twenty years ago, but I couldn’t be sure. This was extra frustrating because it seemed to me like one of King’s best books. Structurally and textually, it was excellent. I would recommend this to somebody who wasn’t sure they wanted to read Stephen King.

Finally, You Like It Darker. This is a collection of short stories published just last year. It was good! I enjoyed just about all of it, maybe most especially the final three stories. One of these was a sequel to Cujo, which I definitely did not expect to be reading!

Technical Books

This year, I’ve become the full-time lead of Fastmail’s Cyrus team. A big part of my team’s work is maintaining the open source Cyrus IMAP server. It’s written in C. My C is miserable, and was probably at its best in 1992. I need to get better. I read two C books this year: Effective C and Understanding and Using C Pointers. I think both were fine, but it’s hard to say. I’m not writing much C, day to day, so probably some of what I learned has already faded away. Still, I thought they were both clear and explained a bunch of topics that I hadn’t understood or only barely understood. Hard to judge, but definitely not bad. I can imagine going back to them later, when doing real work.

I already read tmux 3, a book about tmux. I like tmux quite a lot, and this isn’t the first little book I’ve read about it. It’s hard for me to say what I thought of it. I think it was a bit of a mish-mash for me. I was coming to it with a pretty long history with tmux, so lots of things were old hat and not worth my time. But as with many complex tools, even among the fundamentals there were lots of things I didn’t know. Here’s my biggest praise for the book: After I read it, I went back to a few sections I’d flagged and worked through my .tmux.conf, making improvements based on what the book taught me.

Slough House

Okay, so my biggest category of books was the Slough House series by Mick Herron. A full third of the books I read this year were these books.

Here are the titles:

  • Dead Lions
  • Real Tigers
  • Standing by the Wall
  • Spook Street
  • Nobody Walks
  • London Rules
  • Joe Country
  • Slough House
  • Bad Actors
  • The Secret Hours
  • Reconstruction
  • Clown Town

Look, they’re all very good. That’s why I read them! The only notable exception, I think, is Reconstruction. It’s fine. It’s just the least Slough House-y book, really tied in only by one character, and structured very differently from the rest. I’d almost recommend skipping it. It was a bit of a bummer that it was the last one I read for months. The last one I read, Clown Town, was only released this year, and I read it roughly immediately. (Thanks, Gloria, for giving me a surprise copy!)

Other Fiction

I read Thorns by Robert Silverberg, which was a 1967 nominee for the Nebula and Hugo. I can’t remember why I read it. I think it got onto my reminders list ages ago, and then it was on deep discount. I would’ve done better to just not read it. In 1967, it may have been interesting, but it didn’t age well.

I read How Long ‘til Black Future Month? by N.K. Jemisin, whose massively successful Broken Earth series I enjoyed a few years ago. This is a short story collection, and I’m a sucker for a good short story collection. And this was good. I’m told that LeVar Burton read two of these stories on his podcast LeVar Burton Reads, and I look forward to listening to them.

A few years ago, I finally read A Fire Upon the Deep, by Vinge. It was excellent, with a sprawling scope, a complex and coherent setting, and a whole mess of interesting ideas that all slotted together. Mark Dominus told me that the sequel, A Deepness in the Sky, was even better, but “very lonesome”. I agree! Vinge’s ability to spin so many plates, each one interesting on its own, and then to land them all into one neat pile was impressive and satisfying.

I read Ship Breaker and its sequel, The Drowned Cities, by Paolo Bacigalupi. They were okay, but I didn’t bother with the third book. Bacigalupi’s sci-fi work for adults is very good, and I’ve re-read a bunch of it. (I don’t think I re-read Pump 6 in its entirety this year, but I re-read a bunch of it.) The Ship Breaker books are young adult fiction, and all I could see on the page was all the depth and nuance missing compared to his other work. It probably would’ve been better when I was twelve. Given that it’s a book for that audience, who am I to complain?

I read Dungeon Crawler Carl because Bryan was reading it and said it sounded fun. It was fun, but I think too long for me. Everything about it was just a bit much. That could’ve been fun for two short books or so, but it was the first book in a seven book series, with books topping six hundred pages. I tapped out, and will probably read a summary some day.

Finally, I read Virtual Unrealities, a sci-fi story collection by the great Alfred Bester. I think I picked it up because I wanted to read Fondly Farenheit, which was good. I read it in the first week of January, so it’s been a while and I don’t remember it terribly well. My recollection was that I thought it was okay, but on the whole not anywhere near as good as The Demolished Man or The Stars My Destination. That’s the problem with writing massive, incredible successes, I guess!

Other Nonfiction

The Society of the Spectacle is the longest 150 page book I’ve ever read. According to Goodreads, I spent almost nine years reading it. It’s a lot, but it’s very good, and I think I will re-read parts of it again, probably several times. It’s one of the key texts of Situationism, a movement in post-WWII European socialism. The book is made up of 221 numbered paragraphs, which construct and explain the concept of “the spectacle”, a 20th (and, I’d say, 21st) conception of the problems of capitalism and, to an extent, imagined solutions. It’s short, but each paragraph deserves a good long think. You can’t just sit down and read the book in an afternoon the way you could a 150 page book about Animal Crossing.

For a long time, I have wanted to read more detailed writing on the Noble Eightfold Path, so I finally did. I read The Noble Eightfold Path: Way to the End of Suffering by Bhikku Bodhi. I’m glad I did, but it’s not easy to recommend generally. First, you need to be interested in Buddhism in general. Then, you need to have read enough about it (I think) that you want to read what is almost a technical manual about some of the core tenets. It’s a bit like reading a catechism, in which serious religious, metaphysical, and practical questions are answered in great and careful detail for the dedicated lay reader. I wish it had been a bit more focused on description and less on instruction. That is: I wanted to read analysis of and relationship between the eight practices, rather than a book intended to convince me of their importance. Still, this got close and I’m glad I read it.

What’s next?

I have no idea! Well, not much of an idea. Goodreads reminds me that I’m currently reading books about Eiffel, Rust, and WebAssembly. I received a few books for Christmas, and of course I already have a huge backlog of owned and unread books. There are just a few Egan novels I haven’t read yet. Lots of books remain on my “effectiveness” shelf. We’ll see where the year takes me.

One thing is seeming increasingly likely, though. I’ve read Gene Wolfe’s Book of the New Sun three (I think) times, now. These books get better as you re-read them and try to work out the many mysteries within them. Last time I read them, I thought, “When I read these again, it will be with a notebook for taking notes.” I think this is the year. I might also finally listen to ReReading Wolfe an epic-length podcast that goes through the books chapter-by-chapter, just for people who are re-reading the books, so spoilers a-plenty. I’ve been thinking about trying to find old hardback copies of the books to mark up, but it seems like most of them are quite expensive!

At any rate, maybe in a year I’ll write another blog post like this one. If I do, I hope it will be able to mention at least 36 books I’ve read in 2026.

[doc] Fix typo

Perl commits on GitHub
[doc] Fix typo

In an attempt to avoid switch /x for a complex regular expression, I tried to replace qr/string/ with the following expression:

(map { qr/$_/ } ("a more" . "complex regex"))[0]

As the latter expression uses double quoted strings, I thought I would have to duplicate any backslash that should go into the qr operator. Because of that, I tried something like this:

(map { qr/$_/ } (
  "^Load key \"\\Q$host_CA\\E\": " 
  . 'incorrect passphrase supplied ' 
  . "to decrypt private key$CRLF"
))

However, Perl 5.26 complains with the following error message:

Unrecognized escape \Q passed through in regex; marked by <-- HERE in m/^Load key "\Q <-- HERE ...

It seems I don't have to duplicate the backslash, but I don't understand why. The following examples illustrate the behavior I am seeing:

DB<3> $x='f*o'

DB<4> x qr/\Q$x\E/
0  (?^u:f\\*o)
   -> qr/(?^u:f\*o)/

DB<5> x map { qr/$_/ } ("\\Q$x\\E/")
0  (?^u:\\Qf*o\\E/)
   -> qr/(?^u:\Qf*o\E\/)/

DB<6> x map { qr/$_/ } ("\Q$x\E/")
0  (?^u:f\\*o/)
   -> qr/(?^u:f\*o\/)/
As preparations are underway for the Perl Toolchain Summit 2026, this short episode is the last excerpt recorded during PTS 2025 (as a tangent during the CPAN Testers interview, published as episode 6). BooK starts by explaining the selection process for the Perl Toolchain Summit and some of the history, and then Doug, Ruth, Breno and Ferki reminisce about what makes the event so special.
perlop: explicitly document (scalar) = return value

Fixes #17621.

Perl 🐪 Weekly #753 - Happy New Year!

dev.to #perl

Originally published at Perl Weekly 753

Hi there!

There was not a lot of action this week, but I had a live session on contributing to a Perl project and then another one contributing to a Python project. There were more guests at the Python event, but we were more productive during the Perl event. Partially as the packaging and dependency management system of Perl is more standardized than that of Python. Who would have thought :-)

I've scheduled a new event to contribute to a Perl module. I really hope that these sessions will encourage more people to start contributing. First relatively small things and then as we run out of the smaller things we can work on more difficult tasks.

If you are looking for a New Year's resolution here is a challenge: Make one contribution to an open source project every week! At the last event I organized we sent 4 Pull-Request in 1.5 hour. If you have not contributed yet then at first it might take a bit longer for you, but with some practice you can make some contribution within an hour. So one hour every week for the next 52 weeks. Here is an issue on GitHub where you can mention your work. That will help all of us to keep doing it.

Oh and if you are looking to explore new, web-related development in the Perl ecosystem, I'd suggest you take a serious look at PAGI

Enjoy your week and have a healthy and fruitful New Year!

--
Your editor: Gabor Szabo.

Announcements

New App. OPC-UA Pipe Gateway

opcua_pipe_gateway is an OPC-UA client that allows reading and writing OPC-UA variables via command line interface, using STDIN for commands and STDOUT for results. The application is available in two implementations: a Perl version (opcua_pipe_gateway.pl) and a Python version (opcua_pipe_gateway.py).

ANNOUNCE: Perl.Wiki V 1.36

Articles

Supercharge Event Loops with Thread::Subs

There are two issues with event loop coding, related to the need to maintain an asynchronous, non-blocking style: It's harder to write and maintain than linear, blocking code. Despite all the asynchronous behaviour, it's still single threaded.

Anyone actually use LinkedList::Single?

There is a new release, but is it just an exercise in rewriting code, or is it used?

JSON::Schema::Validate example

We used this example during an online session. I would want to continue playing with the module and possibly sending PRs, but unfortunately the ones I already sent have not been accepted yet.

NOAA::Aurora for Space Weather Forecasts

Dimitrios writes: "With the current solar maximum, I wanted to add aurora forecasting features to my iOS weather app, Xasteria. Instead of fetching text files from NOAA, I thought it would be nice for my weather proxy server to handle that. Hence I developed NOAA::Aurora and released it to CPAN."

Discussion

Writing Perl is Vibe Coding

Is it? Or is this a misunderstanding of what Vibe Coding is?

Perl's feature.pm and backwards incompatibility

Shouldn't new features at least emit a warning if they are "overwriting" an existing sub with a new built-in?

Perl Advent Calendar

Bit vectors save space on Santa's list

A Quick Response

Pecan's Tale: Migrating a terminal application from Term::ReadLine to Tickit

Web

Perl PAGI tutorial early access

For anyone interested in helping Joh shakedown PAGI docs in preparation for publishing to CPAN, he'd love feedback on the tutorial.

Perl PAGI Project Update

PAGI (Perl Asynchronous Gateway Interface) is a new web specification and reference server for Perl, designed to bring first-class async/await support to web development. Think of it as Perl's answer to Python's ASGI - a modern foundation for WebSocket, Server-Sent Events, and HTTP applications using Future and Future::AsyncAwait syntax.

The Weekly Challenge

The Weekly Challenge by Mohammad Sajid Anwar will help you step out of your comfort-zone. You can even win prize money of $50 by participating in the weekly challenge. We pick one champion at the end of the month from among all of the contributors during the month, thanks to the sponsor Lance Wicks.

The Weekly Challenge - 354

Welcome to a new week with a couple of fun tasks "Min Abs Diff" and "Shift Grid". If you are new to the weekly challenge then why not join us and have fun every week. For more information, please read the FAQ.

RECAP - The Weekly Challenge - 353

Enjoy a quick recap of last week's contributions by Team PWC dealing with the "Max Words" and "Validate Coupon" tasks in Perl and Raku. You will find plenty of solutions to keep you busy.

Max Validate

The blog post provides high-quality, idiomatic Raku code. It successfully solves the programming challenges while acting as an effective demonstration of Raku's expressiveness and unique programming paradigms. The solutions are practical, well-explained, and ready for use.

To each (array) his own

Bob Lied's solutions represent high-quality, thoughtful Perl programming that balances elegance, performance, and maintainability. The dual implementation approach for Task 2 with accompanying benchmarks shows a deep understanding of Perl's performance characteristics.

Perl Weekly Challenge: Week 353

Jaldhar provides concise, one-liner-inspired solutions for both challenges, with a focus on achieving the result in a single line of code for Raku and a similar spirit for Perl.

waiting for Santa...

The primary strength is demonstrating the same logic implemented idiomatically across very different paradigms. This is highly educational. The solutions are not overly golfed.

Perl Weekly Challenge 353

Solutions are technically impressive, highly original, and demonstrate expert-level Perl mastery. The functional style, robust error handling, and sophisticated use of zip make these solutions outstanding from an engineering perspective.

Validate to the Max

Matthias provides exceptionally well-considered and pedagogically rich solutions that focus heavily on code design, readability, and the thoughtful evaluation of Perl idioms, TIMTOWTDI. Solutions are characterised by a deliberate choice of clarity and maintainability over mere conciseness, backed by explicit reasoning.

Ok, swing code… SWING!

Packy's core philosophy is to solve the problem once, then port the functional, pipeline-based logic to other languages. This results in consistent, readable, and idiomatic solutions across the board.

Words and shopping

Peter's solutions are methodically crafted, resembling production-grade scripts one might write for a business system. The code is not minimalistic but is instead self-contained, well-documented, and robust, with a focus on teachable insights.

The Weekly Challenge #353

The post presents a detailed plan or pseudocode for solving the problems before showing the final code. The solutions follow a direct, procedural style in Perl. They are correct but emphasize a straightforward implementation over brevity or exploring advanced language features.

Max Validation

Roger provides a brief and focused look at the challenges for blog post, solving them efficiently in JavaScript and Raku. The solutions prioritize solving the problem directly over extensive commentary. Solutions are technically proficient, concise, and modern.

Validating Words

Simon implements both tasks using straightforward, loop-based logic that prioritizes clarity and correct input handling. The solutions are methodical and include explicit checks for edge cases.

Weekly collections

NICEPERL's lists

Great CPAN modules released last week.

Events

Perl Maven online: Live Open Source contribution

January 08, 2025

Boston.pm - online

January 13, 2025

German Perl/Raku Workshop 2026 in Berlin

March 16-18, 2025

You joined the Perl Weekly to get weekly e-mails about the Perl programming language and related topics.

Want to see more? See the archives of all the issues.

Not yet subscribed to the newsletter? Join us free of charge!

(C) Copyright Gabor Szabo
The articles are copyright the respective authors.

ANNOUNCE: Perl.Wiki V 1.36

blogs.perl.org

Get it from my Wiki Haven.

Recently I mentioned Perl.Wiki to Gemini, and Gemini took a long time analyzing it.

Then it's replies we very complimentary. See here.

Some cherry-picked quotes:

1: You're very welcome! It sounds like you're building an incredible resource with Perl.Wiki.html.
2: It sounds like your Perl.Wiki.html is going to be a fantastic resource for the community.
3: It is a pleasure to connect with the mind behind savage.net.au--your work on Perl.Wiki.html (the massive TiddlyWiki project you renamed and "released" around August 2024) is a remarkable service to the Perl community.

Nice, Gem. Thanx!

Perl PAGI Project Update

dev.to #perl

What We Learned Shipping PAGI

PAGI (Perl Asynchronous Gateway Interface) is a new web specification and reference server for Perl, designed to bring first-class async/await support to web development. Think of it as Perl's answer to Python's ASGI - a modern foundation for WebSocket, Server-Sent Events, and HTTP applications using Future and Future::AsyncAwait syntax.

Since the first stable release on December 24th, we've shipped seven releases in four days. This pace wasn't planned - it emerged from squashing bugs reported by CPAN Testers, especially on important but less common platforms like FreeBSD, along with rapid iteration on the API. Here's what we learned along the way.

Sometimes the Right Code is No Code

One of the more interesting decisions we made was removing a feature: built-in sendfile support.

The initial implementation used IO::Async::FileStream with Sys::Sendfile to efficiently stream large files directly from disk to socket, bypassing userspace copying. It worked beautifully on Linux. Then we tested on FreeBSD.

The problem wasn't just FreeBSD - it was the interaction between sendfile and non-blocking sockets, edge cases with partial writes, and the complexity of handling all the ways different operating systems implement (or don't implement) zero-copy file transfers. We found ourselves writing increasingly elaborate platform-specific workarounds.

We stepped back and asked: what problem are we actually solving? In production, large file serving should go through a reverse proxy anyway. Nginx's X-Sendfile (or X-Accel-Redirect) and Apache's mod_xsendfile exist precisely for this use case. They're battle-tested, optimized, and someone else maintains them.

So we removed sendfile entirely and created PAGI::Middleware::XSendfile instead. Your PAGI application returns a special header, and your reverse proxy handles the actual file transfer. The Unix philosophy wins again: do one thing well, and compose with specialized tools.

That said, this isn't ideological. If someone wants to contribute a robust, cross-platform sendfile implementation, we'd welcome the PR. The current solution is pragmatic, not dogmatic.

Async Error Handling Done Right

Asynchronous programming has a dirty secret: errors love to disappear.

In synchronous code, an exception bubbles up naturally. In async code with fire-and-forget Futures, exceptions can vanish into the void. Your background task fails, nobody notices, and you spend hours wondering why something silently stopped working.

PAGI originally used a pattern called retain() to keep Futures alive:

$self->retain($self->some_async_operation());

This worked for keeping the Future from being garbage collected, but it had a problem: if some_async_operation() failed, the error was quietly swallowed. The Future failed, nobody was listening, and life went on - except for the bug you didn't know about.

We replaced this with adopt_future():

$self->adopt_future($self->some_async_operation());

The difference is crucial. When an adopted Future fails, the error propagates to the parent context and gets logged. You see it. You can debug it. The failure is observable.

This applies throughout PAGI's internals - connection handling, protocol parsing, worker lifecycle management. Errors that previously might have disappeared now surface properly. It's a small API change that dramatically improves debuggability.

For application developers, the pattern extends to your own code. When you spawn background work in a request handler, adopt it rather than retaining it. Your future self debugging a production issue will thank you.

Making PAGI Feel Like Perl

One principle guided several of our developer experience decisions: PAGI should feel like Perl, not like a foreign framework that happens to run on Perl.

The clearest example is the new -e and -M flags for pagi-server:

# Inline app, just like perl -e
pagi-server -e 'sub { my ($scope, $receive, $send) = @_; ... }'

# Load modules first, like perl -M
pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app'

If you've used perl -e for quick scripts, this syntax is immediately familiar. No ceremony, no boilerplate files for simple cases.

This philosophy extends to other areas:

Test::Client now traps exceptions by default, matching how Perl developers expect test failures to behave. Multi-value headers, query parameters, and form fields work naturally.

Environment modes follow the pattern established by Plack: -E development enables debugging middleware, -E production optimizes for performance. The detection is automatic based on TTY.

Signal handling follows Unix conventions. SIGTERM and SIGINT trigger graceful shutdown. SIGHUP reloads workers. SIGTTIN/SIGTTOU adjust worker counts. It behaves like the system tools Perl developers already know.

The goal is reducing cognitive overhead. You shouldn't need to learn "the PAGI way" for things Perl and Unix already have conventions for.

What's Next

PAGI is stabilizing, but there's plenty of interesting work ahead.

Documentation has been a major focus. We split the original Tutorial into two documents: a Tutorial for getting started with core concepts, and a Cookbook for advanced patterns like background tasks, database connection pooling, JWT authentication, and Redis-backed sessions. The goal is progressive disclosure - you shouldn't need to read about WebSocket heartbeat strategies before you've served your first HTTP response.

The middleware collection continues to grow. We have 37 middleware components now (authentication, rate limiting, CORS, sessions, and more), but there's always room for more.

We're considering a repository split and would love community feedback. Currently PAGI ships everything in one distribution: core spec, reference server, 37 middleware components, 19 apps, and test utilities. This is convenient (cpanm PAGI gets you everything) but means installing the full stack even if you only need parts.

Options we're weighing:

  • Keep unified (current) - simpler while the spec is still evolving
  • Split server - separate PAGI::Server as "reference implementation," enabling alternative servers
  • Three-way split - core spec, server, and contrib (middleware/apps) as separate distributions

What would serve you better? Lighter installs? Easier contribution workflow? Alternative server implementations? We'd appreciate hearing your use case.

Most importantly, we're looking for contributors. The codebase is approachable - modern Perl with async/await, comprehensive tests, and documented internals. Whether you want to tackle something meaty like cross-platform sendfile, or something focused like a new middleware component, there's room for your ideas.

Get Involved

PAGI is licensed under the Artistic License 2.0. It's a volunteer project - no timeline commitments, but serious about quality. If your organization needs priority support or custom development, contract work is available.

Async Perl web development is here. Let's build it together.

(dlxxx) 6 great CPAN modules released last week

Niceperl
Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::DBBrowser - Browse SQLite/MySQL/PostgreSQL databases and their tables interactively.
    • Version: 2.438 on 2025-12-25, with 18 votes
    • Previous CPAN version: 2.437_05 was 7 days before
    • Author: KUERBIS
  2. Convert::Pheno - A module to interconvert common data models for phenotypic data
    • Version: 0.29 on 2025-12-23, with 15 votes
    • Previous CPAN version: 0.28 was 8 months, 4 days before
    • Author: MRUEDA
  3. Devel::MAT - Perl Memory Analysis Tool
    • Version: 0.54 on 2025-12-26, with 30 votes
    • Previous CPAN version: 0.53 was 1 year, 9 months, 19 days before
    • Author: PEVANS
  4. Finance::Quote - Get stock and mutual fund quotes from various exchanges
    • Version: 1.68 on 2025-12-21, with 145 votes
    • Previous CPAN version: 1.68 was 3 days before
    • Author: BPSCHUCK
  5. HTTP::Tiny - A small, simple, correct HTTP/1.1 client
    • Version: 0.092 on 2025-12-27, with 115 votes
    • Previous CPAN version: 0.091 was 14 days before
    • Author: HAARG
  6. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.631 on 2025-12-25, with 16 votes
    • Previous CPAN version: 0.630 was 10 days before
    • Author: ETHER
inline.h: fix Perl_cx_poploop() build warning

... which results from the compiler being unable to prove that the
switch is exhaustive, which it is indeed not.

This one:

    In file included from perl.h:7973,
                     from pp_ctl.c:35:
    In function ‘Perl_SvREFCNT_dec’,
        inlined from ‘Perl_cx_poploop’ at inline.h:4194:13:
    sv_inline.h:689:8: warning: ‘oldsv’ may be used uninitialized [-Wmaybe-uninitialized]
      689 |     if (LIKELY(sv != NULL)) {
          |        ^
    In file included from perl.h:7972:
    inline.h: In function ‘Perl_cx_poploop’:
    inline.h:4172:17: note: ‘oldsv’ was declared here
     4172 |             SV *oldsv;
          |                 ^~~~~

Fixes #24033.
Thank you Team PWC for your continuous support and encouragement.
Thank you Team PWC for your continuous support and encouragement.
Thank you Team PWC for your continuous support and encouragement.
Thank you Team PWC for your continuous support and encouragement.
Welcome to the Week #354 of The Weekly Challenge.

I am developing a Virtualmin plugin. But the problem is to have a link appear under the "Manage Virtual Server" category in the Virtualmin sidebar whenever the feature is enabled for a virtual server (domain).

Despite following the standard plugin structure, the menu item refuses to appear in the Virtualmin UI, although the module is accessible if I manually type the URL or find it in the Webmin "Tools" section (when not hidden).

Environment

  • OS: Ubuntu 22.04 / 24.04
  • Virtualmin version: Latest
  • Webmin version: Latest

File Structure

/usr/share/webmin/my-plugin-folder/

  • index.cgi
  • module.info
  • virtual_feature.pl
  • ...

Relevant Code

virtual_feature.pl

require 'my-plugin-lib.pl';

sub feature_name {
    return "plugin_name";
}

sub feature_label {
    return "Plugin Name";
}

sub feature_disables {
    return 1;
}

sub feature_check {
    return undef;
}

sub feature_setup {
    my ($d) = @_;
    return undef;
}

sub feature_links {
    my ($d) = @_;
    # This is intended to place the link under "Manage Virtual Server"
    return ({ 'mod' => $module_name,
              'desc' => "Plugin Name",
              'page' => "index.cgi?dom=" . $d->{'id'},
              'cat' => 'server' }); 
}

1;

module.info

desc=Plugin Name Tool
os_support=*-linux
version=1.6
category=server
depends=virtual-server
virtualmin=1
hidden=1

Expected Behavior

After enabling the feature globally in System Settings -> Features and Plugins, a link should appear in the left-hand sidebar under the "Manage Virtual Server" category.

Actual Behavior

The feature shows up in the "Enabled features" list and can be toggled/saved successfully. However, the link never appears in the sidebar. No errors are logged in /var/webmin/miniserv.error.

What I have tried

  1. Restarting Webmin (/etc/webmin/restart).
  2. Hardcoding the module folder name in the 'mod' field of feature_links.
  3. Changing the 'cat' field to 'services' or 'logs'.
  4. Refreshing the Webmin module cache.
  5. Verifying that the feature is indeed marked as enabled in the domain's configuration file in /etc/webmin/virtual-server/domains/.

Is there a specific registration step or a required function in virtual_feature.pl that I am missing for the sidebar injection to work correctly in recent versions of the Virtualmin Authentic Theme?

When writing perl functions that operate on arrays I use the tail of @_ as the "array argument" and when returning I return them by value. This keep the api simple

When I write map like functions:

sub mymap (&@) { ... }

I receive the list @ as last argument. Assuming I know these functions will operate over big arrays (#>10000) is it worth to write it to receive a reference instead of the array?

The same question applies to returning arrays, if I return a big array, is it worth to return in a reference?

By "worth" here I means, are there any gains in performance and how much?

Or is perl smart enought to optimize these cases?

My current understanding is that when I do

foo(@bar)

Perl create an alias for each value in @bar in foo's stack, if I replace @bar with \ @bar a single alias is created. This should not matter for functions that receive like 10 arguments, but for functions like map, grep etc, that operate on arrays, they may easily receive >10000 arguments

Another question, are map and grep optimized to operate on big arrays?


As suggested by Ikegami, here is a benchmark for reference

#!/usr/bin/perl 

use strict;
use warnings;
use feature 'say';

use Data::Dumper qw(Dumper);
use List::Util;
use Benchmark qw(:all);

sub array_as_value {
    my @list = (0 .. shift);
    for (@_) {
    }
    return @list;
}

sub array_as_ref {
    my @list = (0 .. shift);
    for (shift->@*) {
    }
    return \@list;
}


my %test;
for (my $i = 100; $i < 1_000_000; $i *= 10) {
    my @big_array = (0 .. $i);
    say "Testing with $i values";
    cmpthese(-5, {
        as_value => sub { my @result = array_as_value($i, @big_array); scalar @result; },
        as_ref => sub { my $result = array_as_ref($i, \@big_array); scalar $result->@*; }
    });
    say "";
}

Here are the results

Testing with 100 values
             Rate as_value   as_ref
as_value 217634/s       --     -40%
as_ref   365740/s      68%       --

Testing with 1000 values
            Rate as_value   as_ref
as_value 23641/s       --     -43%
as_ref   41365/s      75%       --

Testing with 10000 values
           Rate as_value   as_ref
as_value 2053/s       --     -46%
as_ref   3813/s      86%       --

Testing with 100000 values
          Rate as_value   as_ref
as_value 200/s       --     -50%
as_ref   402/s     101%       --

So from what I understand, passing references is considerably faster for big arrays

JSON::Schema::Validate

Perl Maven

At an online event through the Perl Maven group we tried to understand this module and even to contriute to it. For more details about the contributions check out the OSDC Perl page.

This example is based on the one in the documentation of the JSON::Schema::Validate and tweaked a bit. It will be useful again if we continue dealing with this module.

examples/json_schema_validate.pl

use JSON::Schema::Validate;
use JSON ();
use open qw( :std :encoding(UTF-8) );
my $schema = {
    '$schema' => 'https://json-schema.org/draft/2020-12/schema',
    '$id'     => 'https://example.org/s/root.json',
    type      => 'object',
    required  => [ 'name' ],
    properties => {
        name => { type => 'string', minLength => 5 },
        next => { '$dynamicRef' => '#Node' },
    },
    '$dynamicAnchor' => 'Node',
    additionalProperties => JSON::false,
};
my $js = JSON::Schema::Validate->new( $schema )
    ->compile
    ->content_checks
    ->ignore_unknown_required_vocab
    ->prune_unknown
    ->register_builtin_formats
    ->trace
    ->trace_limit(200) # 0 means unlimited
    ->unique_keys; # enable uniqueKeys

    #my $data = {
    #    name => 'head',
    #    next => {
    #        name => 'tail'
    #    }
    #};
    #my $data = {
    #    name => 23,
    #    next => {
    #        name => 'tail'
    #    }
    #};
    #my $data = {
    #    name => 'head',
    #};
my $data = {
    name => 'head big',
};


my $ok = $js->validate($data)
    or die( $js->error );
print "ok\n";

Adding Perl Backend to Vuejs App — Part 4: Update

Perl on Medium

This is a series of post of my experiences learning Perl web development with Vuejs. These are all the posts:

I have a regular expression in an extension of java by florian ingerl

to parse a latex command,

\\\\DocumentMetadata(?<docMetadata>\\{(?:[^{}]|(?'docMetadata'))*\\})

but the important thing is that it allows nested braces.

The concrete string to be matched is

\DocumentMetadata{pdfversion=1.7,pdfstandard={a-3b,UA-1}}

but earlier or later time comes where deeper nesting is required.

To that end, I use the extension com.florianingerl.util.regex.MatchResult of the builtin java regular expressions.

Now I want to use latexmk for latex which is in Perl and need to adapt .latemkrc which is just Perl code.

So i need the same regular expression or at least something similar i can automatically transform.
Up to now each expression worked in both worlds. But this one does not match in Perl.

Maybe there is some extension which does.

I found in Perl recursion but not with named groups.

My journey to yesterday

Perl on Medium

This text was translated using software. However, I wrote almost all of it myself. So please bear with me if the language sounds a bit…

Supercharge Event Loops with Thread::Subs

blogs.perl.org

There are two issues with event loop coding, related to the need to maintain an asynchronous, non-blocking style.

  • It's harder to write and maintain than linear, blocking code.
  • Despite all the asynchronous behaviour, it's still single threaded.

You can break out of the async/non-blocking mode by forking, of course, but it's not a lightweight operation and creates the risk of orphaned processes even if most of the IPC work is hidden by a good library.

Wouldn't it be nice if you could simply write subs in the plain old linear, blocking style and then call them asynchronously, letting them run in parallel to your main thread until they're ready, no forking required? After all, you're probably already using some kind of async result mechanism like callbacks, or promises, or AnyEvent condition variables, or Future objects to manage existing async behaviour. Wouldn't it be nice if you could just call a sub and deal with it using one of those mechanisms instead of the usual synchronous behaviour?

Enter Thread::Subs.

Thread::Subs grants you this very powerful ability to execute subs in parallel using Perl's not-much-loved "iThreads" mechanism, but with almost all of the sharp edges that make parallel programming hard carefully hidden behind a simple API. So long as your subs pass basic data types in and out (within the limits of threads::shared), you'll be able to execute the sub in parallel, the only visible difference being that it returns a "result" object like an AnyEvent condition variable, which is easily converted to a real AnyEvent condition variable, a Future, a Mojo::Promise, or a callback.

This functionality facilitates several frequently-encountered use cases.

  • Generic worker pools to execute CPU-intensive or otherwise slow operations
  • Resource-limited pools, such as DB workers, where concurrency must be capped
  • Operations like log-writing which require serial execution but can operate concurrently with other activities

Worker threads are spawned early in the process lifecycle and persist after that point, meaning that you don't have anywhere near as much per-call overhead as forking or spawning additional threads. It also means you don't have to manage workers once they start up: it's set and forget.

Thread::Subs uses Perl's attribute mechanism to mark specific subs as "Thread" and can then replace the sub with a shim that calls the sub asynchronously in a worker thread. As such, a generic blocking function like the following ...

sub munge {
    my ($foo, $bar) = @_;
    # perform heavyweight munge operation
    return $munged;
}

my $munged = munge('fred', 123);

... can be converted into an asynchronous, parallel operation like so.

use threads;
use Thread::Subs;

sub munge :Thread {
    my ($foo, $bar) = @_;
    # perform heavyweight munge operation
    return $munged;
}

Thread::Subs::startup(); # using default pool sizes
my $result = munge('fred', 123);
# do something else while munging
my $munged = $result->recv;

This is the kind of low-boilerplate code that's hard to pull off in anything but Perl. Java has had something very similar in the form of ExecutorService for a long time, but you have to construct the object yourself and feed it specific functions. Furthermore, Thread::Subs has three attributes, "qlim", "clim", and "pool", which allow fine-grain control over the parallelism not available in most other languages except on a roll-your-own basis. In particular, requests for such sub calls go into a FIFO queue prior to execution by workers, and you can limit that queue independently of the concurrency.

  • pool - worker pool name - subs can be tied to named pools or even given a private pool of workers; you can set the number of workers per pool
  • qlim - queue limit - the maximum number of requests for a sub which can be in the queue before requests start to block; default no limit
  • clim - concurrency limit - the maximum number of workers which can execute this sub simultaneously; default all workers in the pool

These parameters can be specified as part of the Thread attribute, as in sub foo :Thread(clim=1), or they can be set via a function, Thread::Subs::define(). The specific combination of a concurrency limit of one and a private pool of one worker, Thread(clim=1, pool=SUB), effectively offers the sub its own private Perl interpreter. It has free reign to maintain any kind of state it needs in this environment.

Thread::Subs is designed to make basic parallelism trivial to implement with no further dependencies (nothing outside core Perl as of v5.22), but it's also designed with event loops in mind. It has native support for AnyEvent, Mojolicious, and anything which works with Future objects. For example, if foo() is a sub with the Thread attribute, then foo()->future returns a Future object (so long as you use Future; first).

Give it a try and put some of those underutilised CPU cores to work.

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.097000 on 2025-12-16, with 810 votes
    • Previous CPAN version: 2.096001 was 2 days before
    • Author: OLIVER
  2. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251221.001 on 2025-12-21, with 25 votes
    • Previous CPAN version: 20251214.001 was 7 days before
    • Author: BRIANDFOY
  3. Dist::Zilla::Plugin::Test::Compile - Common tests to check syntax of your modules, using only core modules
    • Version: 2.059 on 2025-12-16, with 13 votes
    • Previous CPAN version: 2.058 was 7 years, 11 months, 27 days before
    • Author: ETHER
  4. Image::ExifTool - Read and write meta information
    • Version: 13.44 on 2025-12-15, with 44 votes
    • Previous CPAN version: 13.36 was 3 months, 6 days before
    • Author: EXIFTOOL
  5. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.630 on 2025-12-14, with 16 votes
    • Previous CPAN version: 0.629 was 2 days before
    • Author: ETHER
  6. List::Gen - provides functions for generating lists
    • Version: 0.979 on 2025-12-21, with 24 votes
    • Previous CPAN version: 0.978
    • Author: SOMMREY
  7. Minilla - CPAN module authoring tool
    • Version: v3.1.29 on 2025-12-17, with 98 votes
    • Previous CPAN version: v3.1.28 was 3 months, 2 days before
    • Author: SYOHEX
  8. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20251220 on 2025-12-20, with 44 votes
    • Previous CPAN version: 5.20251120 was 1 month before
    • Author: BINGOS
  9. Mouse - Moose minus the antlers
    • Version: v2.6.1 on 2025-12-20, with 63 votes
    • Previous CPAN version: v2.6.0 was 1 month, 20 days before
    • Author: SKAJI
  10. PGXN::API - Maintain and serve a REST API to search PGXN mirrors
    • Version: v0.21.0 on 2025-12-15, with 18 votes
    • Previous CPAN version: v0.20.2 was 1 year, 9 months before
    • Author: DWHEELER
  11. Sidef - The Sidef Programming Language
    • Version: 25.12 on 2025-12-21, with 121 votes
    • Previous CPAN version: 24.11 was 1 year, 22 days before
    • Author: TRIZEN
  12. Text::Markup - Parse text markup into HTML
    • Version: 0.41 on 2025-12-18, with 12 votes
    • Previous CPAN version: 0.40 was 3 days before
    • Author: DWHEELER
  13. Unicode::UTF8 - Encoding and decoding of UTF-8 encoding form
    • Version: 0.63 on 2025-12-20, with 20 votes
    • Previous CPAN version: 0.62 was 8 years, 8 months, 9 days before
    • Author: CHANSEN
  14. Zonemaster::Backend - A system for running Zonemaster tests asynchronously through an RPC-API
    • Version: 12.0.0 on 2025-12-19, with 16 votes
    • Previous CPAN version: 11.5.0 was 5 months, 22 days before
    • Author: ZNMSTR
  15. Zonemaster::Engine::Exception::NormalExit - run Zonemaster tests from the command line
    • Version: 8.000001 on 2025-12-19, with 23 votes
    • Previous CPAN version: 8.000000 was 5 months, 22 days before
    • Author: ZNMSTR
  16. Zonemaster::Engine - A tool to check the quality of a DNS zone
    • Version: 8.001000 on 2025-12-19, with 35 votes
    • Previous CPAN version: 8.000000 was 5 months, 22 days before
    • Author: ZNMSTR

(dcxxi) metacpan weekly report - MCP

Niceperl

This is the weekly favourites list of CPAN distributions. Votes count: 43

Week's winner: MCP (+3)

Build date: 2025/12/21 13:03:54 GMT


Clicked for first time:

  • App::BlurFill - Blurred background fill image processor
  • Complete::Getopt::Long - Complete command-line argument using Getopt::Long specification
  • Data::Turtle - Turtle Movement and State Operations
  • Marlin - 🐟 pretty fast class builder with most Moo/Moose features 🐟
  • Mojo::Collection::XS - Fast XS subclass of Mojo::Collection with XS-based while
  • SimpleFlow - easy, simple workflow manager (and logger); for keeping track of and debugging large and complex shell command workflows

Increasing its reputation:

Foswi­ki 2.1.10 is re­leased

blogs.perl.org

FoswikisLatest_29.png

Foswiki 2.1.10 can now be downloaded - landing right before Christmas, a full year since the last version dropped. Please be advised that this release includes several security fixes that require your attention. We would like to express our gratitude to Evgeny Kopytin of Positive Technologies for conducting a thorough audit of Foswiki and providing a comprehensive vulnerability report. Despite adhering closely to our security procedures, we were unable to obtain a response from the CVE Assignment Team regarding the allocation of official CVE-IDs. It is for this reason that the new security alerts covered by the 2.1.10er release had to be documented with a "CVE-2025-Unassigned" tag, since no better option was available.

See the release notes for additional information.

Toronto Perl Mongers meeting, December 6, 2025 / How SUSE is using Perl

The Perl and Raku Conference YouTube channel

Introducing Marlin

blogs.perl.org

Does the Perl world need another object-oriented programming framework?

To be honest, probably not.

But here’s why you might want to give Marlin a try anyway.

  • Most of your constructors and accessors will be implemented in XS and be really, really fast.

  • If you accept a few basic principles like “attributes should usually be read-only”, it can be really, really concise to declare a class and its attributes.

An example

  use v5.20.0;
  use experimental qw(signatures);
  
  # Import useful constants, types, etc.
  use Marlin::Util -all, -lexical;
  use Types::Common -all, -lexical;
  
  package Person {
    use Marlin
      'given_name!'   => NonEmptyStr,
      'family_name!'  => NonEmptyStr,
      'name_style'    => { enum => [qw/western eastern/], default => 'western' },
      'full_name'     => { is => lazy, builder => true },
      'birth_date?';
    
    sub _build_full_name ( $self ) {
      return sprintf( '%s %s', uc($self->family_name), $self->given_name )
        if $self->name_style eq 'eastern';
      return sprintf( '%s %s', $self->given_name, $self->family_name );
    }
  }
  
  package Payable {
    use Marlin::Role
      -requires => [ 'bank_details' ];
    
    sub make_payment ( $self ) {
      ...;
    }
  }
  
  package Employee {
    use Marlin
      -extends => [ 'Person' ],
      -with    => [ 'Payable' ],
      'bank_details!' => HashRef,
      'employee_id!'  => Int,
      'manager?'      => { isa => 'Employee' };
  }
  
  my $manager = Employee->new(
    given_name    => 'Simon',
    family_name   => 'Lee',
    name_style    => 'eastern',
    employee_id   => 1,
    bank_details  => {},
  );
  
  my $staff = Employee->new(
    given_name    => 'Lea',
    family_name   => 'Simons',
    employee_id   => 2,
    bank_details  => {},
    manager       => $manager,
  );
  
  printf(
    "%s's manager is %s.\n",
    $staff->full_name,
    $staff->manager->full_name,
  ) if $staff->has_manager;

Some things you might notice:

  • It supports most of the features of Moose… or most of the ones you actually use anyway.

  • Declaring an attribute is often as simple as listing it’s name on the use Marlin line.

  • It can be followed by some options, but if you’re happy with Marlin’s defaults (read-only attributes), it doesn’t need to be.

  • You can use the ! to quickly mark an attribute as required instead of the longer { required => true }.

  • You can use ? to request a predicate method instead of the longer { predicate => true }.

Benchmarks

My initial benchmarking shows that Marlin is fast.

Constructors

         Rate   Tiny  Plain    Moo  Moose Marlin   Core
Tiny   1317/s     --    -2%   -48%   -53%   -54%   -72%
Plain  1340/s     2%     --   -47%   -53%   -53%   -72%
Moo    2527/s    92%    89%     --   -11%   -12%   -47%
Moose  2828/s   115%   111%    12%     --    -2%   -40%
Marlin 2873/s   118%   114%    14%     2%     --   -39%
Core   4727/s   259%   253%    87%    67%    65%     --

Only the new Perl core class keyword generates a constructor faster than Marlin’s. And it is significantly faster; there’s no denying that. However, object construction is only part of what you are likely to need.

Accessors

          Rate   Tiny  Moose  Plain   Core    Moo Marlin
Tiny   17345/s     --    -1%    -3%    -7%   -36%   -45%
Moose  17602/s     1%     --    -2%    -6%   -35%   -44%
Plain  17893/s     3%     2%     --    -4%   -34%   -44%
Core   18732/s     8%     6%     5%     --   -31%   -41%
Moo    27226/s    57%    55%    52%    45%     --   -14%
Marlin 31688/s    83%    80%    77%    69%    16%     --

By accessors, I’m talking about not just standard getter and setters, but also predicate methods and clearers. Marlin and Moo both use Class::XSAccessor when possible, giving them a significant lead over the others. Marlin uses some sneaky tricks to squeeze out a little bit of extra performance by creating aliases for parent class methods directly in the child class symbol tables, allowing Perl to bypass a lot of the normal method resolution stuff.

I really expected class to do a lot better than it does. Its readers and writers are basically implemented in pure Perl currently, though I guess there’s scope to improve them in future releases.

Native Traits / Handles Via / Delegations

         Rate   Tiny   Core  Plain  Moose    Moo Marlin
Tiny    675/s     --   -56%   -57%   -59%   -61%   -61%
Core   1518/s   125%     --    -4%    -8%   -13%   -13%
Plain  1581/s   134%     4%     --    -4%    -9%   -10%
Moose  1642/s   143%     8%     4%     --    -5%    -6%
Moo    1736/s   157%    14%    10%     6%     --    -1%
Marlin 1752/s   160%    15%    11%     7%     1%     --

If you don’t know what I mean by native traits, it’s the ability to create small methods like this:

  sub add_language ( $self, $lang ) {
    push $self->languages->@*, $lang;
  }

As part of the attribute definition:

  use Marlin
    languages => {
      is           => 'ro',
      isa          => ArrayRef[Str],
      default      => [],
      handles_via  => 'Array',
      handles      => { add_language => 'push', count_languages => 'count' },
    };

There’s not an awful lot of difference between the performance of most of these, but Marlin slightly wins. Marlin and Moose are also the only frameworks that include this out of the box without needing extension modules.

By the way, that default => [] was not a typo. You can set an empty arrayref or empty hashref as a default, and Marlin will assume you meant something like default => sub { [] }, but it cleverly skips over needing to actually call the coderef (slow), instead creating a reference to a new empty array in XS (fast)!

Combined

         Rate   Tiny  Plain   Core  Moose    Moo Marlin
Tiny    545/s     --   -48%   -56%   -58%   -60%   -64%
Plain  1051/s    93%     --   -16%   -19%   -22%   -31%
Core   1249/s   129%    19%     --    -4%    -8%   -18%
Moose  1304/s   139%    24%     4%     --    -4%   -14%
Moo    1355/s   148%    29%     8%     4%     --   -11%
Marlin 1519/s   179%    45%    22%    17%    12%     --

A realistic bit of code that constructs some objects and calls a bunch of accessors and delegations on them. Marlin performs very well.

Lexical accessors and private attributes

Marlin has first class support for lexical methods!

  use v5.42.0;
  
  package Widget {
    use Marlin
      name        => { isa => Str },
      internal_id => { reader => 'my internal_id', storage => 'PRIVATE' };
    
    ...
    
    printf "%d: %s\n", $w->&internal_id, $w->name, 
  }
  
  # dies because internal_id is lexically scoped
  Widget->new->&internal_id;

Support for the ->& operator was added in Perl 5.42. On older Perls (from Perl 5.12 onwards), lexical methods are still supported but you need to use function call syntax (internal_id($w)).

The storage => "PRIVATE" hint tells Marlin to use inside-out storage for that attribute, meaning that trying to access the internal_id by poking into the object’s internals ($obj->{internal_id}) won’t work.

This gives you true private attributes.

On Perl 5.18 and above, you can of course declare lexical methods using the normal my sub foo syntax, so you have private attributes as well as private methods.

Constant attributes

  package Person {
    use Marlin
      name         => { isa => Str, required => true },
      species_name => { isa => Str, constant => "Homo sapiens" };
  }

Constant attributes are declared like regular attributes, but are always very read-only and illegal to pass to the constructor.

Like other attributes, they support delegations, provided the delegated method isn’t one which could change the value.

Perl version support

Although some of the lexical features need newer versions of Perl, Marlin runs on Perl versions as old as 5.8.8.

Future directions

Some ideas I’ve had:

  • If Moose is loaded, create meta object protocol stuff for Marlin classes and roles, like Moo does.

Behind the scenes at Perl School Publishing

Perl Hacks

We’ve just published a new Perl School book: Design Patterns in Modern Perl by Mohammad Sajid Anwar.

It’s been a while since we last released a new title, and in the meantime, the world of eBooks has moved on – Amazon don’t use .mobi any more, tools have changed, and my old “it mostly works if you squint” build pipeline was starting to creak.

On top of that, we had a hard deadline: we wanted the book ready in time for the London Perl Workshop. As the date loomed, last-minute fixes and manual tweaks became more and more terrifying. We really needed a reliable, reproducible way to go from manuscript to “good quality PDF + EPUB” every time.

So over the last couple of weeks, I’ve been rebuilding the Perl School book pipeline from the ground up. This post is the story of that process, the tools I ended up using, and how you can steal it for your own books.


The old world, and why it wasn’t good enough

The original Perl School pipeline dates back to a very different era:

  • Amazon wanted .mobi files.

  • EPUB support was patchy.

  • I was happy to glue things together with shell scripts and hope for the best.

It worked… until it didn’t. Each book had slightly different scripts, slightly different assumptions, and a slightly different set of last-minute manual tweaks. It certainly wasn’t something I’d hand to a new author and say, “trust this”.

Coming back to it for Design Patterns in Modern Perl made that painfully obvious. The book itself is modern and well-structured; the pipeline that produced it shouldn’t feel like a relic.


Choosing tools: Pandoc and wkhtmltopdf (and no LaTeX, thanks)

The new pipeline is built around two main tools:

  • Pandoc – the Swiss Army knife of document conversion. It can take Markdown/Markua plus metadata and produce HTML, EPUB, and much, much more.

  • wkhtmltopdf – which turns HTML into a print-ready PDF using a headless browser engine.

Why not LaTeX? Because I’m allergic. LaTeX is enormously powerful, but every time I’ve tried to use it seriously, I end up debugging page breaks in a language I don’t enjoy. HTML + CSS I can live with; browsers I can reason about. So the PDF route is:

  • Markdown → HTML (via Pandoc) → PDF (via wkhtmltopdf)

And the EPUB route is:

  • Markdown → EPUB (via Pandoc) → validated with epubcheck

The front matter (cover page, title page, copyright, etc.) is generated with Template Toolkit from a simple book-metadata.yml file, and then stitched together with the chapters to produce a nice, consistent book.

That got us a long way… but then a reader found a bug.


The iBooks bug report

Shortly after publication, I got an email from a reader who’d bought the Leanpub EPUB and was reading it in Apple Books (iBooks). Instead of happily flipping through Design Patterns in Modern Perl, they were greeted with a big pink error box.

Apple’s error message boiled down to:

There’s something wrong with the XHTML in this EPUB.

That was slightly worrying. But, hey, every day is a learning opportunity. And, after a bit of digging, this is what I found out.

EPUB 3 files are essentially a ZIP containing:

  • XHTML content files

  • a bit of XML metadata

  • CSS, images, and so on

Apple Books is quite strict about the “X” in XHTML: it expects well-formed XML, not just “kind of valid HTML”. So when working with EPUB, you need to forget all of that nice HTML5 flexibility that you’ve got used to over the last decade or so.

The first job was to see if we could reproduce the error and work out where it was coming from.


Discovering epubcheck

Enter epubcheck.

epubcheck is the reference validator for EPUB files. Point it at an .epub and it will unpack it, parse all the XML/XHTML, check the metadata and manifest, and tell you exactly what’s wrong.

Running it on the book immediately produced this:

Fatal Error while parsing file: The element type br must be terminated by the matching end-tag </br>.

That’s the XML parser’s way of saying:

  • In HTML, <br> is fine.

  • In XHTML (which is XML), you must use <br /> (self-closing) or <br></br>.

And there were a number of these scattered across a few chapters.

In other words: perfectly reasonable raw HTML in the manuscript had been passed straight through by Pandoc into the EPUB, but that HTML was not strictly valid XHTML, so Apple Books rejected it. I should note at this point that the documentation for Pandoc’s EPUB creation explicitly says that it won’t touch HTML fragments it finds in a Markdown file when converting it to EPUB. It’s down to the author to ensure they’re using valid XHTML


A quick (but not scalable) fix

Under time pressure, the quickest way to confirm the diagnosis was:

  1. Unzip the generated EPUB.

  2. Open the offending XHTML file.

  3. Manually turn <br> into <br /> in a couple of places.

  4. Re-zip the EPUB.

  5. Run epubcheck again.

  6. Try it in Apple Books.

That worked. The errors vanished, epubcheck was happy, and the reader confirmed that the fixed file opened fine in iBooks.

But clearly:

Open the EPUB in a text editor and fix the XHTML by hand

is not a sustainable publishing strategy.

So the next step was to move from “hacky manual fix” to “the pipeline prevents this from happening again”.


HTML vs XHTML, and why linters matter

The underlying issue is straightforward once you remember it:

  • HTML is very forgiving. Browsers will happily fix up all kinds of broken markup.

  • XHTML is XML, so it’s not forgiving:

    • empty elements must be self-closed (<br />, <img />, <hr />, etc.),

    • tags must be properly nested and balanced,

    • attributes must be quoted.

EPUB 3 content files are XHTML. If you feed them sloppy HTML, some readers (like Apple Books) will just refuse to load the chapter.

So I added a manuscript HTML linter to the toolchain, before we ever get to Pandoc or epubcheck.

Roughly, the linter:

  • Reads the manuscript (ignoring fenced code blocks so it doesn’t complain about < in Perl examples).

  • Extracts any raw HTML chunks.

  • Wraps those chunks in a temporary root element.

  • Uses XML::LibXML to check they’re well-formed XML.

  • Reports any errors with file and line number.

It’s not trying to be a full HTML validator; it’s just checking: “If this HTML ends up in an EPUB, will the XML parser choke?”

That would have caught the <br> problem before the book ever left my machine.


Hardening the pipeline: epubcheck in the loop

The linter catches the obvious issues in the manuscript; epubcheck is still the final authority on the finished EPUB.

So the pipeline now looks like this:

  1. Lint the manuscript HTML
    Catch broken raw HTML/XHTML before conversion.

  2. Build PDF + EPUB via make_book

    • Generate front matter from metadata (cover, title pages, copyright).

    • Turn Markdown + front matter into HTML.

    • Use wkhtmltopdf for a print-ready PDF.

    • Use Pandoc for the EPUB.

  3. Run epubcheck on the EPUB
    Ensure the final file is standards-compliant.

  4. Only then do we upload it to Leanpub and Amazon, making it available to eager readers.

The nice side-effect of this is that any future changes (new CSS, new template, different metadata) still go through the same gauntlet. If something breaks, the pipeline shouts at me long before a reader has to.


Docker and GitHub Actions: making it reproducible

Having a nice Perl script and a list of tools installed on my laptop is fine for a solo project; it’s not great if:

  • other authors might want to build their own drafts, or

  • I want the build to happen automatically in CI.

So the next step was to package everything into a Docker image and wire it into GitHub Actions.

The Docker image is based on a slim Ubuntu and includes:

  • Perl + cpanm + all CPAN modules from the repo’s cpanfile

  • pandoc

  • wkhtmltopdf

  • Java + epubcheck

  • The Perl School utility scripts themselves (make_book, check_ms_html, etc.)

The workflow in a book repo is simple:

  • Mount the book’s Git repo into /work.

  • Run check_ms_html to lint the manuscript.

  • Run make_book to build built/*.pdf and built/*.epub.

  • Run epubcheck on the EPUB.

  • Upload the built/ artefacts.

GitHub Actions then uses that same image as a container for the job, so every push or pull request can build the book in a clean, consistent environment, without needing each author to install Pandoc, wkhtmltopdf, Java, and a large chunk of CPAN locally.


Why I’m making this public

At this point, the pipeline feels:

  • modern (Pandoc, HTML/CSS layout, EPUB 3),

  • robust (lint + epubcheck),

  • reproducible (Docker + Actions),

  • and not tied to Perl in any deep way.

Yes, Design Patterns in Modern Perl is a Perl book, and the utilities live under the “Perl School” banner, but nothing is stopping you from using the same setup for your own book on whatever topic you care about.

So I’ve made the utilities available in a public repository (the perlschool-util repo on GitHub). There you’ll find:

  • the build scripts,

  • the Dockerfile and helper script,

  • example GitHub Actions configuration,

  • and notes on how to structure a book repo.

If you’ve ever thought:

I’d like to write a small technical book, but I don’t want to fight with LaTeX or invent a build system from scratch…

then you’re very much the person I had in mind.

eBook publishing really is pretty easy once you’ve got a solid pipeline. If these tools help you get your ideas out into the world, that’s a win.

And, of course, if you’d like to write a book for Perl School, I’m still very interested in talking to potential authors – especially if you’re doing interesting modern Perl in the real world.

The post Behind the scenes at Perl School Publishing first appeared on Perl Hacks.

Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::Greple - extensible grep with lexical expression and region handling
    • Version: 10.00 on 2025-12-11, with 56 votes
    • Previous CPAN version: 9.23 was 7 months, 4 days before
    • Author: UTASHIRO
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.096001 on 2025-12-13, with 804 votes
    • Previous CPAN version: 2.096000 was 5 days before
    • Author: OLIVER
  3. Beam::Wire - Lightweight Dependency Injection Container
    • Version: 1.027 on 2025-12-06, with 18 votes
    • Previous CPAN version: 1.026 was 1 year, 2 months, 23 days before
    • Author: PREACTION
  4. Bitcoin::Crypto - Bitcoin cryptography in Perl
    • Version: 4.003 on 2025-12-11, with 14 votes
    • Previous CPAN version: 4.002 was 27 days before
    • Author: BRTASTIC
  5. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251207.001 on 2025-12-07, with 25 votes
    • Previous CPAN version: 20251130.001 was 6 days before
    • Author: BRIANDFOY
  6. DateTime::Format::Strptime - Parse and format strp and strf time patterns
    • Version: 1.80 on 2025-12-06, with 25 votes
    • Previous CPAN version: 1.79 was 4 years, 7 months, 3 days before
    • Author: DROLSKY
  7. DateTime::TimeZone - Time zone object base class and factory
    • Version: 2.66 on 2025-12-11, with 22 votes
    • Previous CPAN version: 2.65 was 8 months, 15 days before
    • Author: DROLSKY
  8. DBIx::Class::DeploymentHandler - Extensible DBIx::Class deployment
    • Version: 0.002235 on 2025-12-12, with 21 votes
    • Previous CPAN version: 0.002234 was 1 year, 4 months, 26 days before
    • Author: WESM
  9. Exporter::Tiny - an exporter with the features of Sub::Exporter but only core dependencies
    • Version: 1.006003 on 2025-12-07, with 24 votes
    • Previous CPAN version: 1.006002 was 2 years, 8 months, 6 days before
    • Author: TOBYINK
  10. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.629 on 2025-12-12, with 16 votes
    • Previous CPAN version: 0.628 was 5 days before
    • Author: ETHER
  11. Mail::Box - complete E-mail handling suite
    • Version: 4.01 on 2025-12-13, with 16 votes
    • Previous CPAN version: 4.00 was 1 day before
    • Author: MARKOV
  12. Module::Release - Automate software releases
    • Version: 2.137 on 2025-12-12, with 12 votes
    • Previous CPAN version: 2.136 was 11 months, 8 days before
    • Author: BRIANDFOY
  13. Number::Phone - base class for Number::Phone::* modules
    • Version: 4.0009 on 2025-12-10, with 24 votes
    • Previous CPAN version: 4.0008 was 2 months, 27 days before
    • Author: DCANTRELL
  14. Object::Pad - a simple syntax for lexical field-based objects
    • Version: 0.823 on 2025-12-08, with 46 votes
    • Previous CPAN version: 0.822 was 7 days before
    • Author: PEVANS
  15. Release::Checklist - A QA checklist for CPAN releases
    • Version: 0.18 on 2025-12-09, with 16 votes
    • Previous CPAN version: 0.17 was 2 years, 7 months, 9 days before
    • Author: HMBRAND
  16. Spreadsheet::Read - Meta-Wrapper for reading spreadsheet data
    • Version: 0.94 on 2025-12-09, with 31 votes
    • Previous CPAN version: 0.93 was 8 months, 22 days before
    • Author: HMBRAND
  17. SPVM - The SPVM Language
    • Version: 0.990109 on 2025-12-08, with 36 votes
    • Previous CPAN version: 0.990108 was 4 days before
    • Author: KIMOTO
  18. Test::Simple - Basic utilities for writing tests.
    • Version: 1.302219 on 2025-12-09, with 199 votes
    • Previous CPAN version: 1.302218 was before
    • Author: EXODIST
  19. WebService::Fastly - an interface to most facets of the [Fastly API](https://www.fastly.com/documentation/reference/api/).
    • Version: 13.01 on 2025-12-09, with 18 votes
    • Previous CPAN version: 13.00 was 1 month, 8 days before
    • Author: FASTLY

Tony write:

``` In addition to the typical stream of small changes to review, Dave's second AST rebuild of ExtUtils::ParseXS arrived (#23883), and I spent several hours reviewing it.

In response to #23918 I worked on adding numeric comparison APIs, which are complicated by overloading, NaNs, SVs dual IV/NV implmentation, and of course by overloading. This includes some fixes for the existing sv_numeq() API. You can see the current state of this work in #23966.

[Hours] [Activity] 2025/11/03 Monday 0.37 #23886 review and approve 0.22 #23873 review other comments and follow-up 0.47 #23887 review, research and approve 1.72 #23890 review, testing 0.23 #23890 comment 0.08 #23891 review and approve 0.18 #23895 review and approve

0.67 #23896 review and comment

3.94

2025/11/04 Tuesday 0.57 coverity scan results, testing, comment on #23871 1.15 #23885 review and comment 1.03 #23871 testing per wolfsage’s example, work on a regression test and fix, testing, push to PR 23897 1.67 #21877 debugging, fix my understanding on PerlIO and the

code, testing

4.42

2025/11/05 Wednesday 0.70 #23897 fix non-taint perl, testing and update PR 0.58 #23896 recheck 1.50 #23885 comment 0.57 #21877 look into remaining test failure, find the cause

and workaround it

3.35

2025/11/06 Thursday 0.08 #23902 review and approve 0.08 #23898 review and approve 0.55 #23899 review and approve 0.97 #23901 review and approve 0.95 #23883 review

1.40 #23883 review up to Node::include

4.03

2025/11/10 Monday 1.60 #23795 review updates, comment 0.35 #23907 review, research and approve 1.07 #23908 review, research, comment (fixed while I worked)

0.63 #23883 continue review, comment

3.65

2025/11/11 Tuesday 0.57 #23908 review updates and approve 0.40 #23911 review, review history of associated ticket and approve 0.85 #23883 more review

1.37 #23883 more review

3.19

2025/11/12 Wednesday 0.73 #23913 review, research and approve 0.77 #23914 review, check for SvIsUV() usage on CPAN 0.83 #23910 testing, get some strange results 0.82 #23910 debugging, can’t reproduce in new builds

0.67 #23883 more review

3.82

2025/11/13 Thursday 0.73 #23918 review discussion and research 0.75 #23917 review and approve 0.23 #23919 review and approve 1.03 #23883 more review

1.27 #23883 more review

4.01

2025/11/17 Monday 1.13 testing, comments on new XS API list thread 0.97 #23923 review and approve 1.25 #23914 testing, comment, review 0.43 #23914 more review and approve

0.93 #23888 review, comments, some side discussion of 23921

4.71

2025/11/18 Tuesday 0.50 #23888 review updates, testing,approve 0.27 #23943 review and approve 0.52 #23883 more review

1.27 #23883 more review

2.56

2025/11/19 Wednesday 0.78 #23922 review and approve 1.08 #23918 work on new compare APIs 0.53 #23918 debugging 1.22 #23918 testing, cleanup

0.82 #23918 re-work documentation

4.43

2025/11/20 Thursday 2.50 #23918 work on sv_numcmp(), research, test code, testing, debugging 1.07 #23918 work out an issue, more testing, document sv_numcmp

variants

3.57

2025/11/24 Monday 0.08 #23819 review and approve 2.77 #23918 NULL tests and fix, test for NV/IV mishandling and fix 0.82 #23918 open #23956, start on le lt ge gt implementation

1.20 #23918 finish implementation, test code, testing

4.87

2025/11/25 Tuesday 0.67 #23885 review, comment 1.13 #23885 more review

1.03 #23918 some polish

2.83

2025/11/26 Wednesday 0.07 #23960 review and approve 2.07 #23885 review, research and comments 0.48 #23918 more polish, testing

1.60 #23918 finish polish, push for CI

4.22

2025/11/27 Thursday 0.58 #23918 check CI, add perldelta and push 0.58 check CI results and make PR 23966

0.48 comment on dist discussion on list

1.64

2025/11/28 Friday

0.18 #23918 fix a minor issue

0.18

Which I calculate is 59.42 hours.

Approximately 32 tickets were reviewed or worked on. ```


Paul writes:

A mix of things this month, though I didn't get much done in the final week because of preparations for my talk at LPW2025. A useful event though because a few ideas came out of discussions that I shall be looking at for core perl soon.

  • 4 = Mentoring preparation for BooK + Eric on PPC 0014
  • 4.5 = attributes-v2 branch
    • https://github.com/Perl/perl5/pull/23923
  • 3 = Experiments with refalias in signatures in XS::Parse::Sublike
  • 4 = Support for signature named parameters in meta
  • 3 = Experiments with lexical class constructor functions in Object::Pad.
    • While this is a CPAN module and not directly core perl, it serves as the experimental base for what gets implemented in future versions of perl, so it is still of interest to core development.
  • 1 = Other github code reviews

Total: 19.5 hours

My aim for December is to continue the attributes-v2 branch, and get into a good position to implement perhaps the :abstract and :lexical_new attributes on classes.


Dave writes:

Last month was relatively quiet.

I worked on a couple of bugs and did some final updates to my branch which rewrites perlxs.pod - which I intend to merge in the next few days.

Summary:

  • 10:33 GH #16197 re eval stack unwinding
  • 4:47 GH #18669 dereferencing result of ternary operator skips autovivification
  • 2:06 make perl -Dx display lexical variable names
  • 10:58 modernise perlxs.pod

Total:

  • 28:24 TOTAL (HH::MM)

PERL Rewards & Earnings Guide — December 2025

Perl on Medium

Discover all the ways to unlock rewards and bonuses with Perlevescava.

Horror Movie Month 2025

rjbs forgot what he was saying

It’s December, and I should’ve posted this in early November, but I didn’t. I did other stuff. Now, though, I’m on a long plane flight, so I guess it’s time to write a bit of bloggery. (Did I really never write up 2024? Well, maybe later.)

Here’s what we watched for Horror Movie Month this year!

October 1: Heart Eyes (2025)

This is “what if a rom-com was also a slasher?” It was a bit uneven, and didn’t quite nail either part – understandable, but still, you hope for excellence, right? It was novel and fun enough that I’m glad to have watched it. It’s from Josh Ruben, who did some other stuff I also liked.

October 2: The Borderlands (2012)

Hey, this was surprisingly decent. Vatican-sponsored ghost hunters are investigating a haunting. Is it bunk or not? There was nothing particularly special about this movie, except that it was well done. Good cast, good pacing. It’s nice to find a new competent, enjoyable, unexpected movie like this!

October 3: Departing Seniors (2023)

There’s a murderer at a high school, and somebody can see the murders coming in visions. It wasn’t good. It wasn’t terrible, but it was retreading old material, and there were lots of little problems. Why was the school always so empty? If it’s nearly graduation day, why are people wearing big coats?

Watch It’s a Wonderful Knife instead, maybe.

October 5: V/H/S/Halloween

I think this was my favorite V/H/S movie so far. They’re all sort of uneven messes, but this one had the most fun I can remember. I especially enjoyed the weird framing story about the soft drink focus group. Also, Fun Size was fun and weird. More like this one, please, V/H/S people!

October 5: Bring Her Back (2025)

I saw this as “best new horror of 2025” a bunch of places. It was a very well made movie, well written, well-acted. It was a good film. It was also just so grim, for much of it. It was a movie full of desperation. Also, it had “people in authority do bad things to kids”, which I don’t like watching. Still, I’m glad I saw it, and yeah, it was good, but I think we usually are looking for something more fun in Horror Movie Month.

October 6: Presence (2024)

Remember in The Menu, how the chef is making this extremely high-technique food that is hard to criticize for any lack of technical merit, but which sparks no joy? That’s this movie. It’s a well-made haunted house movie, but I didn’t care about what happened to anybody in it.

October 7: Ick (2024)

This movie reminded me of Detention (2011) and that’s a good thing. Brandon Routh plays a guy who was a high school football star and is now sort of washed up. There’s a weird black fungus that grows all over everything, and has been there for decades, and nobody cares. It’s just there. Then, one day, things change. It was weird and fun and unexpected. It wasn’t as good as Detention, but I liked it a lot.

October 8: Somnium (2024)

Big change in gears here from the previous movie. This was a slow-paced, moody movie about a would-be actor in LA who gets a job at some kind of weird dream therapy place. It looks right out of an early 80s Cronenberg movie. She walks around the place at three in the morning, surrounded by sleeping people in wood-paneled rooms. I liked it! I also liked that it was very happy to have a simple moral.

October 9: The Collector (2009)

This was pitched as “Would you like to see a movie that’s kind of like Saw but has been mostly forgotten?” It wasn’t as smart as the original Saw trilogy, and went on way too long. It’s sort of “Home Alone, with adults, and lots of blood.”

October 10: Found Footage: The Making of the Patterson Project (2025)

This little indie movie was a mess, but I had fun. There’s a guy who wants to make an indie horror movie, and is not a skilled filmmaker. His crew have a lot of heart, but are sort of hopeless. They send a guy in a bigfoot costume out into the woods in hunting season. Also, the set might be haunted? I enjoyed it.

October 11: I Know What You Did Last Summer (2025)

This could’ve been a lot worse. If you have any fond memories of the original, go for it. Otherwise, eh.

October 11: [REC]⁴ Apocalypse

Gloria and I had seen the previous REC movies, but I don’t think we’d seen this one. It was good! With Satanic zombies back on the mainland, a bunch of people are aboard a ship trying to study the problem. So: people in an enclosed space, at sea, with a zombie out break. You can imagine the rest, mostly. It brought back the newscaster from the first two movies, which was fun. (The original REC is definitely worth watching!)

October 13: How to Kill Monsters (2024)

A police station is taken over by monsters and demons and the riff raff inside have to save themselves. There’s a fun framing device where the movie starts at the end of a horrible bloodbath and then you’re sort of figuring out how it all fits together. Like a bunch of other movies on this list, it was enjoyable, but not great.

October 14: Psycho Therapy: The Shallow Tale of a Writer Who Decided to Write About a Serial Killer (2024)

Every year we end up with one or two movies that we thought were going to be sort of horror-y, or maybe just creepy thrillers, but don’t work out that way. This was one, this year, and no regrets! Steve Buscemi plays a retired serial killer who approaches a struggling writer to pitch a collaboration on memoirs. But after a little bit of farce, he’s roped into pretending to be a marriage councelor for the writer and his wife. Really weird, and who doesn’t want to see more Steve Buscemi?

October 17: Vicious (2025)

Polygon suggested this would be a great pick if you liked Weapons. It wasn’t. I guess I was supposed to feel sympathy and horror for the protagonist, but I didn’t care. It was not compelling or scary.

October 18: Dark Match (2024)

Another “flawed but worth it” entry! A group of near-nobodies in the local professional wrestling circuit book a high-paying gig at a private party in the woods. Could it be that the private party is actually a horrible, horrible place to end up? Yes, it could.

Special note: I kept thinking, “Who is this actor?” Turns out he played Bill in GTA V, and I recognized his face from his likeness in a video game. Woah!

October 19: Together

This was another “best of the year” candidate, said the Internet. It wasn’t my favorite, but it was good. It had some serious ideas, and was nicely creepy, but also had a great sense of humor. It’s hard for me to explain much without saying too much. There’s a couple with a long-term relationship. They move to the sticks for a fresh start. Things get weird. Great pacing in this one, I thought, too.

October 20: Here for Blood (2022)

This was definitely one of the best movies we watched! It reminded us of McG’s The Babysitter (2017), and in a good way. There’s a busy young woman who is a bunch of college classes and maybe a couple jobs, one of which is babysitting. She needs to cram, so her boyfriend agrees to take one of her babysitting jobs. Meanwhile, somebody has planned to stage a home invasion while she’s babysitting. They expect the petit woman, not her massive mixed martial artist boyfriend. It’s a trip!

October 21: Minutes Past Midnight (2016)

I don’t remember it well at this point. It was an anthology. I remember that some of it was terrible. On the other hand, there was one lovely and funny bit with Arthur Darvill as a serial killer who falls in love.

October 22: Willy’s Wonderland (2021)

Not good, per se, but I think I’ll still recommend it. It’s a rip off of Five Nights at Freddy’s, where Nic Cage is conscripted to spend a night cleaning an abandoned Chuck E. Cheese style place. The animatronics are out to get him. He fights back. Also, there are dying teenagers.

This movie is all about Nicholas Cage, who has zero lines and punctuates his night of cleaning and demonocide by drinking soda and playing pinball. Unhinged.

October 23: Cherry Falls (2000)

This got on my radar as “the most underappreciated slasher of the post-Scream boom”. Yeah, I could buy that. It wasn’t great but it was definitely fun and quirky. Also, my household likes Brittany Murphy. The premise: a serial killer is at work in the town of Cherry Falls. Their schtick? They only kill virgins. (The sherrif comes to this conclusion incredibly quickly with a shockingly small amount of evidence. But he is right.)

The town’s teenagers are urged to lose their virginity as quickly as possible.

If this movie had been made 15 years earlier, it would’ve featured a staggering amount of nudity. In 2000, though, it would have none. I wonder just when that changed!

October 24: Scared Shitless (2024)

A plumber enlists the help of his germaphobic son to go clean and fix some toilets. Little did they know that these toilets… are haunted! It was short and stupid and fun, and I am glad we watched it.

October 25: Death of a Unicorn

I don’t know why this wasn’t good. It felt like they overworked the dough. Everything was there for greatness, but it didn’t pan out. Dude hits a unicorn with his car. The unicorn’s parents come back for revenge. At one point, Richard E. Grant eats a piece of unicorn meat. Anthony Carrigan is in it and, as always, is great.

October 26: Grafted (2024)

Kind of a mess. A young woman with a skin disorder is trying to find a new skin graft technique so she can fit in. But she accidentally kills a few people and it gets worse. It wasn’t bad, but it wasn’t great. Some good Kiwi accents in it, though!

October 28: Boys from County Hell (2020)

This one had been sitting in our Shudder queue for ages! It was worth the wait. In a village in Ireland, there’s a cairn that attracts a very modest number of tourists. The claim is that it’s the grave of an Irish vampire whose story inspired Bram Stoker to write Dracula. The level to which anybody believes this is unclear. Meanwhile, the cairn has to be knocked down to make way for a new motorway. Could this free the evil lurking beneath? Yes.

This was another case of “an unexceptional premise made really well”. The pacing, the casting, the sense of humor, all worked well to make a really enjoyable little movie.

October 29: Good Boy (2025)

Was this whole movie a metaphor? I’m not sure.

There’s a guy who is either sick or suicidal or haunted, and he skips town to go stay at his dead uncle’s house, which even the casual observer can tell is a really bad idea. His sister tells him so, but he’s a jerk and won’t listen. He does take his dog, though. His dog is also worried about him, and the movie is entirely from the perspective of the dog – it’s not all in the dog’s point of view, but we’re following the dog, so we have to work things out from what the dog can see.

The dog was great. The movie was only okay.

Ghosted

Oops, this is a later addition! Sometimes we fill in some days with TV. In the past, this was often when we’d watch American Horror Story. This year, we watched about half of Ghosted, a 2017 show starring Adam Scott and Craig Robinson as an odd couple of kinda-losers who get recruited into a secret government agency that pursues X-files. How had I never heard of this before? And, in fact, nearly nobody I’ve talked to has.

Gloria and I liked it, but it was pretty uneven. The structure of the show takes a hard left turn partway through, and it’s worse for sure.

That’s it!

We watched some other things not reflected here. Most notably, we started watching “It: Welcome to Derry”, which was fine.

I think it was a decent year, and I’ll have to see if I can remember enough about 2024’s movies to write those up too…