Shortcuts: s show h hide n next p prev

In Perl on Linux, I want to check the File status flags of an OS file descriptor number without knowing which Perl file handles, if any, use that file descriptor (the fd might even have been inherited from a parent process and unknown to Perl).

It seems like POSIX::fcntl($fd, F_GETFL, 0) should work but it doesn't. POSIX::fcntl is different than all other i/o functions in the POSIX module e.g. POSIX::open, POSIX::write, etc. POSIX::fcntl is documented as "identical to Perl's builtin fcntl", i.e. it expects a Perl file handle as an argument, not an OS file descriptor (actually it only accepts a file handle glob).

Why is this? Is there any way in Perl to access the OS fcntl function using a file descriptor?

#!/usr/bin/env perl
use strict; use warnings; use POSIX qw/:fcntl_h/; 
{ my $bits = POSIX::fcntl(1, F_GETFL, 0);
  warn "GETFL from fd 1 failed:$!" unless defined($bits);
  printf "GETFL from fd 1 = %08X\n", $bits;
}
{ printf "fileno(STDOUT) = %d\n", fileno(STDOUT);
  #my $bits = POSIX::fcntl(STDOUT, F_GETFL, 0);  # syntax error
  my $bits = POSIX::fcntl(*STDOUT, F_GETFL, 0);
  printf "GETFL from Perl fh = %08X\n", $bits;
}

... which gives output:

GETFL from fd 1 failed:Bad file descriptor at /tmp/t2 line 4.
Use of uninitialized value $bits in printf at /tmp/t2 line 5.
GETFL from fd 1 = 00000000
fileno(STDOUT) = 1
GETFL from Perl fh = 00080002

For the LLM-curious...

https://github.com/viviparous/quellm

I coded this Perl client for querying an Ollama server that I run in my local network with offline LLMs. I wanted a flexible client to suit my querying needs. This was a fun little Perl project and a chance to experiment with various LLMs that Ollama provides.

You can use quellm to query the LLMs and to list/pull/delete LLMs. Some LLMs are quite responsive, others take several minutes to respond. (True, I do not have top-of-the-line hardware!)

Ollama itself is easy to install. I provided some configuration tips in the project's Readme file. I have heard that Ollama is easier to run in Linux than in Windows. I run my Ollama server in Windows but I query it from various Linux and Windows terminals in my network.

Sharing quellm with folks here in case someone else is "LLM-curious".

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

I'm working on a SpamAssassin plugin, which would submit the text of a suspected email to AI (via HTTP POST) and process the response. The response is expected to contain a one-word verdict (one of "HAM", "SPAM", or "UNSURE") and a short reason.

Both fields are returned by the model, according to log. For example:

{ "verdict": "HAM", "reason": "The email appears to be a legitimate response to a GitHub discussion about the performance of llama.cpp with Vulkan, discussing technical details and comparisons with ROCm." }

The plugin correctly informs SpamAssassin too -- I see my AI_HAM among the "tests" of the X-Spam-Status-header.

However, I'd also like the "reason" field to be inserted as a separate header of its own. To that effect, I added the following code to my plugin:

    my $r = $ai_json->{reason};
    $pms->set_tag('AI_STATUS', $r);
    warn("Status tag: " . $pms->get_tag('AI_STATUS'));

and this to my plugin's .pre file:

add_header  all AI-Status _AI_STATUS_

That "Status tag" "warning" is logged correctly, but no X-Spam-AI-Status header is ever added to the incoming messages... What am I missing?

Update: Moving the add_header directive from MyPlugin.pre to MyPlugin.cf causes the new header to appear in the output of spamassassin -t -- for some reason!

But it is still missing from the actual headers of the messages, that've gone through the milter. The original X-Spam-Status header inserted by SpamAssassin itself is present (and now lists my plugin among the tests applied to the messages), but my own header is still not added...

I would like to use a Perl one-liner to modify numeric values in a text file. My data are stored in a text file:

0, 0, (1.263566e+02, -5.062154e+02)
0, 1, (1.069488e+02, -1.636887e+02)
0, 2, (-2.281294e-01, -7.787449e-01)
0, 3, (5.492424e+00, -4.145492e+01)
0, 4, (-7.961223e-01, 2.740912e+01)

These are complex numbers with their respective i and j coordinates: i, j, (real, imag). I would like to modify the coordinates, to shift them from zero-based to one-based indexing. In other words I would like to add one to each i and each j. I can correctly capture the i and j, but I'm struggling to treat them as numbers not as strings. This is the one-liner I'm using:

perl -p -i.bak -w -e 's/^(\d+), (\d+)/$1+1, $2+1/' complex.txt

How do I tell Perl to treat $1 and $2 as numbers?

My expected output would be:

1, 1, (1.263566e+02, -5.062154e+02)
1, 2, (1.069488e+02, -1.636887e+02)
1, 3, (-2.281294e-01, -7.787449e-01)
1, 4, (5.492424e+00, -4.145492e+01)
1, 5, (-7.961223e-01, 2.740912e+01)

Remove PERL_CREATE_GVSV

Perl commits on GitHub
Remove PERL_CREATE_GVSV

PERL_DONT_CREATE_GVSV has been the default for more than 20 years now
(since bdf3085f9fca00a6148ef3f26060d442844b64bd).

There's no real reason to enable PERL_CREATE_GVSV and it's almost
undocumented, perlapi mentions it once in passing. It doesn't seem that
any code on CPAN checks for PERL_CREATE_GVSV or PERL_DONT_CREATE_GVSV.
perlapi: Tabularize display of config.h symbols

Certain symbols in config.h have been displayed with no addtional
information.  The lack of information is because the symbol's name says
it all. For example HAS_SETENV is a boolean indicating if setenv() is
available on the platform.  No further explanation is needed than the
introductory paragraph at the beginning of the section.

Prior to this commit, these symbols were displayed as a comma separated
list wrapping across multiple lines.

This commit organizes them into a table with columns, making them much
easier to read.

autodoc.pl: Extract code into a function

Perl commits on GitHub
autodoc.pl: Extract code into a function

This is in preparation for it to be called from other places

ANN: CPAN::MetaCurator V 1.08, Perl.Wiki V 1.40 etc

blogs.perl.org

Hi All
Big news today.
I've uploaded these files to my Wiki Haven:
a. Perl.Wiki.html V 1.40
b. jsTree V 1.08 (i.e. the matching version of Perl.Wiki).
This version is much nicer than the previous one.
c. MojoLicious.Wiki.html V 1.14

And I've uploaded to CPAN: CPAN::MetaCurator V 1.40.

This version no longer ships 02packages.details.txt, nor a packages table in the SQLite db.

Further, I'm about to start coding CPAN::MetaPackages, which will do nothing but load
02packages.details.txt into its own SQLite db. Then CPAN::MetaCurator will have its own db
and simultaneously link to the packages db.

The point: To make CPAN::MetaCurator's build.dh.sh run much faster, down from
15 hours on my humble Lenovo M70Q 'Tiny' desktop to 1 second, basically.

And the next step is then to ship only differences between successive versions of
02packages.details.txt, so that updating packages.sqlite will be lightning fast.

Perl 🐪 Weekly #760 - Async Perl

dev.to #perl

Originally published at Perl Weekly 760

Hi there,

Perl's asynchronous ecosystem continues to grow, enabling developers to build non-blocking, responsive applications with ease. Modules like IO::Async, async features in Mojolicious, and helpers for asynchronous database operations (such as DBIx::Class::Async) allow event-driven designs, background tasks, and futures/promises, making high-throughput web services, real time APIs, and streaming pipelines straightforward to implement.

Projects like PAGI and PAGI::Server, now with HTTP/2 support, and Thunderhorse showcase how Perl can handle multiple connections efficiently while keeping code clear and maintainable. Together, these tools make it easier to build responsive, scalable, and maintainable applications, all while retaining the expressive, pragmatic style that continues to define Perl.

With each new module and project, Perl's potential in the modern, concurrent world keeps expanding, the best is yet to come.

A small milestone reached with this issue, my 200th edition. Enjoy rest of the newsletter and stay safe.

--
Your editor: Mohammad Sajid Anwar.

Announcements

Join us for TPRC 2026 in Greenville, SC!

It’s great to see the announcement for The Perl and Raku Conference 2026 (TPRC) taking shape, with registration opening and plans underway for a vibrant community gathering in Greenville, SC this June. The post reinforces the value of bringing Perl and Raku developers together for talks, workshops, and networking. A highlight on the opensource calendar that strengthens the ecosystem and connects contributors across projects.

This week in PSC (215) | 2026-02-11

In This week in PSC 215, the Perl Steering Council covered a deep discussion around legal identifier name restrictions for security without reaching consensus and planning to broaden the conversation beyond p5p, tackled the challenge of an absent maintainer for the dual‑life Encode module, and decided to hold off on merging larger PRs like magic v2 and attributes v2 due to the upcoming freeze in this release cycle. These updates give a clear snapshot of ongoing governance and core maintenance decisions within the Perl project.

Articles

Poplar Decisions

The post reflects on the challenge of rational decision‑making with a quirky, human‑centred anecdote, weaving in the idea that structured data models, like decision trees, can help bring objectivity to complex choices. The post’s blend of storytelling and commentary on data structures adds a thoughtful and entertaining perspective for programmers thinking about reasoning and modeling in code.

Mojo with WebSocket

A practical real‑world example of using Mojolicious’ built‑in WebSocket support to build an interactive online chat app in Perl, complete with multiple server variants and integration options like Redis or PostgreSQL. The repository showcases how easily Mojolicious can handle real‑time bidirectional communication with WebSockets, making it a solid reference for Perl developers exploring event‑driven web apps.

Coding Agents using Anthropic and z.ai - presentation at the German Perl Workshop 2026

The post previews Max's talk at the German Perl Workshop 2026, exploring how modern AI coding agents from Anthropic and z.ai can assist with Perl development, what differences exist between the models, and tips for getting them to write good code. It’s an engaging look at practical uses of agentic AI in real world programming contexts, a timely topic for anyone curious about AI‑assisted development.

Beautiful Perl feature: 'local', for temporary changes to global variables

This article highlights one of Perl’s unique strengths, the local keyword, showing how it enables temporary, dynamic changes to global variables without permanent side effects. With clear examples manipulating %ENV, special Perl variables and even symbol table entries, it makes a compelling case for using local judiciously to solve real world problems that lexical scoping alone can’t.

CPAN

PAGI::Server, now with HTTP/2!

The announcement of PAGI::Server 0.001017 highlights experimental HTTP/2 support built on nghttp2, bringing both cleartext h2c and TLS‑based HTTP/2 to Perl web services with automatic protocol detection and solid h2spec compliance. The write‑up explains why HTTP/2 matters for backend performance and modern use cases like gRPC and multiplexed APIs, and it also outlines other quality‑of‑life improvements and operational fixes in the release.

Black box test generator version 0.28 released

Version 0.28 of App::Test::Generator, the black‑box test case generator, has just been released with improved schema extraction and test generation accuracy, tightening detection of getter/setter methods and better typing in generated tests. These enhancements make it easier to produce honest, robust fuzz and corpus driven test harnesses from your Perl modules.

Run::WeeklyChallenge

Run::WeeklyChallenge is a small but useful CPAN module that helps you automate running solutions to challenges from The Weekly Challenge site by passing one or more sets of JSON‑formatted inputs to your code. It cleanly wraps your solution logic and input schema validation, making it easier to test and reuse challenge solutions programmatically.

DBIx::Class::Async

DBIx::Class::Async is a modern asynchronous wrapper for DBIx::Class that allows non‑blocking database operations in Perl, keeping the familiar DBIC interface while running queries in the background via futures. The latest update brings several improvements: caching is now disabled by default (TTL 0), automatic detection of non-deterministic SQL functions (like NOW() and RAND()) ensures safe bypass of caching, cache invalidation on update/delete operations is more precise using primary keys, and count() queries are no longer cached to guarantee accurate row counts. These enhancements make asynchronous DBIC usage both safer and more reliable.

Syntax::Highlight::Engine::Kate

Syntax::Highlight::Engine::Kate provides Perl programs with robust syntax highlighting using the same engine as the Kate editor. The latest update fixes Issue #23 in Template.pm: the testDetectSpaces() regex was corrected, ensuring only spaces and tabs are matched and improving number highlighting in Perl and other languages. The test suite expected outputs were also updated to reflect the corrected highlighting behavior.

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 - 361

Welcome to a new week with a couple of fun tasks "Zeckendorf Representation" and "Find Celebrity". 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 - 360

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

TWC360

This write-up delivers straightforward, idiomatic Perl solutions for both text justification and word sorting, showing practical use of fc for case-insensitive comparisons and clear subroutine design. The concise code examples make the challenge solutions easy to follow and apply.

Full Circle

In this post, an effective solution to The Weekly Challenge #360 is given, with beautiful examples showing how Raku can be implemented for text justification and sorting as the output. Most of the explanations are fairly short, but they are clearly defined, giving lots of examples; and, they consider the idiomatic usage of Raku's features to make the output readable and helpful.

Pertaining to a subtlety of sorting

This article offers a thoughtful take on the Word Sorter task from PWC 360, with a clear explanation of the case-insensitive sort and an efficient Perl solution using a Schwartzian transform. The benchmarking insight and attention to Unicode case folding nuance show both practical coding skill and depth of understanding.

Perl Weekly Challenge: Week 360

This write-up clearly presents both Text Justifier and Word Sorter tasks with simple, idiomatic Perl and Raku solutions that showcase practical string manipulation and sorting techniques. The inclusion of multiple examples and cross-language snippets makes the challenge approachable and highlights the expressive power of each language.

Perl Weekly Challenge 360

This post showcases clear, idiomatic Perl solutions for both the Text Justifier and Word Sorter tasks, with one‑liner examples and concise logic that demonstrate practical use of integer arithmetic and case‑preserving sorting. The included sample inputs and outputs make the behavior easy to follow and verify.

This is exactly the sort of justification that I was looking for

This post methodically implements both Text Justifier and Word Sorter solutions for PWC 360 in clear Perl code, showing careful step-by-step padding logic and idiomatic sorting. The explanations of how the examples are handled make the approach easy to follow and instructive for readers.

Justifying TIMTOWTDI

The post offers well‑structured Perl solutions that clearly implement both text justification and alphabetical word sorting with idiomatic constructs and practical tests. The use of case‑preserving sorting and centered padding logic demonstrates good command of Perl’s core features and makes the solutions easy to follow and reuse.

Word Crimes are Justified

An excellent and clear walk-through of the Perl Weekly Challenge tasks, with well-structured multi-language solutions and thoughtful explanations that make the text justification and word sorting problems easy to follow. The blend of Perl, Raku, Python, and Elixir examples shows both depth and versatility of approach.

Padding and sorting

The post presents the Text Justifier and Word Sorter tasks clearly with well-explained inputs and desired outputs, giving readers a solid grounding in the problem definitions. The examples are practical and show the expected string centering and alphabetical ordering behavior in a way that supports straightforward implementation.

The Weekly Challenge - 360: Text Justifier

This post demonstrates a practical and idiomatic Perl solution by leveraging String::Pad for Text Justifier, showcasing how using existing modules can simplify challenge tasks. The concise examples with clear input/output make it easy to grasp the task mechanics and verify correctness.

The Weekly Challenge - 360: Word Sorter

This write-up delivers a succinct and idiomatic Perl solution to the Word Sorter task, using a case-insensitive sort and clean split/grep logic that keeps words unchanged while ordering them alphabetically. The included test cases make the behavior clear and easy to verify.

Justify the Words

This post delivers clear and well-commented solutions to both Text Justifier and Word Sorter tasks from The Weekly Challenge 360, using concise Lua, Raku, Perl and other language examples with practical explanations of key steps like centered padding and case-insensitive sorting. The author’s discussion of different implementation strategies highlights thoughtful coding decisions that make the techniques accessible and educational for readers.

Padding and sorting

This write‑up walks through both the Text Justifier and Word Sorter tasks from The Weekly Challenge 360 with clear Python and Perl solutions, showing well‑structured logic for string padding and case‑insensitive sorting. The practical examples and side‑by‑side language implementations make the techniques easy to understand and apply.

Perl Power: Two Tiny Scripts, Big Learning!

This write‑up distills both Text Justifier and Word Sorter solutions into clean, minimal Perl scripts with clear logic for padding and sorting, and emphasizes solid test‑driven development and edge‑case handling. The examples and explanation of core techniques make it both beginner‑friendly and technically sound.

Rakudo

2026.06 CƔD YN GYMRAEG

Weekly collections

NICEPERL's lists

Great CPAN modules released last week.

The corner of Gabor

A couple of entries sneaked in by Gabor.

WhatsApp

Do you use WhatsApp? Join the Perl Maven chat group!

Events

Paris.pm monthly meeting

March 11, 2025

German Perl/Raku Workshop 2026 in Berlin

March 16-18, 2025

The Perl and Raku Conference 2026

June 26-29, 2026, Greenville, SC, USA

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.

Add a folding limit on the size of the string repetition multiplier

Historically, given a statement like `my $x = "A" x SOMECONSTANT;`, no
examination of the size of the multiplier (`SOMECONSTANT` in this example)
was done at compile time. Depending upon the constant folding behaviour,
this might mean:
* The buffer allocation needed at runtime could be clearly bigger than
  the system can support, but Perl would happily compile the statement
  and let the author find this out at runtime.
* Constants resulting from folding could be very large and the memory
  taken up undesirable, especially in cases where the constant resides
  in cold code.

This commit addresses the second case by adding a folding threshold for
constant multipliers.
Welcome to the Week #361 of The Weekly Challenge.
Thank you Team PWC for your continuous support and encouragement.

Beautiful Perl series

This post is part of the beautiful Perl features series.
See the introduction post for general explanations about the series.

The last post was about BLOCKs and lexical scoping, a feature present in almost all programming languages. By contrast, today's topic is about another feature quite unique to Perl : dynamic scoping, introduced through the 'local' keyword. As we shall see, lexical scoping and dynamic scoping address different needs, and Perl allows us to choose the scoping strategy most appropriate to each situation.

Using local : an appetizer

Let us start with a very simple example:

say "current time here is ", scalar localtime;

foreach my $zone ("Asia/Tokyo", "Africa/Nairobi", "Europe/Athens") {
  local $ENV{TZ} = $zone;
  say "in $zone, time is ", scalar localtime;
}

say "but here current time is still ", scalar localtime;

Perl's localtime builtin function returns the time "in the current timezone". On Unix-like systems, the notion of "current timezone" can be controlled through the TZ environment variable, so here the program temporarily changes that variable to get the local time in various cities around the world. At the end of the program, we get back to the usual local time. Here is the output:

current time here is Sun Feb  8 22:21:41 2026
in Asia/Tokyo, time is Mon Feb  9 06:21:41 2026
in Africa/Nairobi, time is Mon Feb  9 00:21:41 2026
in Europe/Athens, time is Sun Feb  8 23:21:41 2026
but here current time is still Sun Feb  8 22:21:41 2026

The gist of that example is that:

  1. we want to call some code not written by us (here: the localtime builtin function);
  2. the API of that code does not offer any parameter or option to tune its behaviour according to our needs; instead, it relies on some information in the global state of the running program (here: the local timezone);
  3. apart from getting our specific result, we don't want the global state to be durably altered, because this could lead to unwanted side-effects.

Use cases similar to this one are very common, not only in Perl but in every programming language. There is always some kind of implicit global state that controls how the program behaves internally and how it interacts with its operating system: for example environment variables, command-line arguments, open sockets, signal handlers, etc. Each language has its strategies for dealing with the global state, but often the solutions are multi-faceted and domain-specific. Perl shines because its local mechanism covers a very wide range of situations in a consistent way and is extremely simple to activate.

Before going into the details, let us address the bad reputation of dynamic scoping. This mechanism is often described as something that should be absolutely avoided because it implements a kind of action at distance, yielding unpredictable program behaviour. Yes, it is totally true, and therefore languages that only have dynamic scoping are not suited for programming-in-the-large. Yet in specific contexts, dynamic scoping is acceptable or even appropriate. The most notable examples are Unix shells and also Microsoft Powershell for Windows, that still today all rely on dynamic scoping, probably because it's easier to implement.

Perl1 also used dynamic scoping in its initial design, presumably for the same reason of easiness of implementation, and also because it was heavily influenced by shell programming and was addressing the same needs. When later versions of Perl evolved into a general-purpose language, the additional mechanism of lexical scoping was introduced because it was indispensable for larger architectures. Nevertheless, dynamic scoping was not removed, partly for historical reasons, but also because action at distance is precisely what you want in some specific situations. The next chapters will show you why.

The mechanics of local

In the last post we saw that a my declaration declares a new variable, possibly shadowing a previous variable of the same name. By contrast, a local declaration is only possible on a global variable that already exists; the effect of the declaration is to temporarily push aside the current value of that global variable, leaving room for a new value. After that operation, any code anywhere in the program that accesses the global variable will see the new value ... until the effect of local is reverted, namely when exiting the scope in which the local declaration started.

Here is a very simple example, again based on the %ENV global hash. This hash is automatically populated with a copy of the shell environment when perl starts up. We'll suppose that the initial value of $ENV{USERNAME}, as transmitted from the shell, is Alex:

sub greet_user ($salute) {
  say "$salute, $ENV{USERNAME}";
}

greet_user("Hello");                 # Hello, Alex

{ local $ENV{USERNAME} = 'Brigitte';
  greet_user("Hi");                  # Hi, Brigitte

  { local $ENV{USERNAME} = 'Charles';
    greet_user("Good morning");      # Good morning, Charles
  }

  greet_user("Still there");         # Still there, Brigitte
}

greet_user("Good bye");              # Good bye, Alex

The same thing would work with a global package variable:

our $username = 'Alex';             # "our" declares a global package variable

sub greet_user ($salute) {
  say "$salute, $username";
}

greet_user("Hello");
{ local $username = 'Brigitte';
  greet_user("Hi");
  ... etc.

but if the variable is not pre-declared, we get an error:

Global symbol "$username" requires explicit package name (did you forget to declare "my $username"?)

or if the variable is pre-declared as lexical through my $username instead of our $username, we get another error:

Can't localize lexical variable $username

So the local mechanism only applies to global variables. There are three categories of such variables:

  1. standard variables of the Perl interpreter;
  2. package members (of modules imported from CPAN, or of your own modules). This includes the whole symbol tables of those packages, i.e. not only the global variables, but also the subroutines or methods;
  3. what the Perl documentation calls elements of composite types, i.e. individual members of arrays or hashes. Such elements can be localized even if the array or hash is itself a lexical variable, because while the entry point to the array or hash may be on the execution stack, its member elements are always stored in global heap memory. This last category of global variables is perhaps more difficult to understand, but we will give examples later to make it clear.

As we can see, the single and simple mechanism of dynamic scoping covers a vast range of applications! Let us explore the various use cases.

Localizing standard Perl variables

The Perl interpreter has a number of builtin special variables, listed in perlvar. Some of them control the internal behaviour of the interpreter; some other are interfaces to the operating system (environment variables, signal handlers, etc.). These variables have reasonable default values that satisfy most common needs, but they can be changed whenever needed. If the change is for the whole program, a regular assignment instruction is good enough; but if it is for a temporary change in a specific context, localis the perfect tool for the job.

Internal variables of the interpreter

The examples below are typical of idiomatic Perl programming: altering global variables so that builtin functions behave differently from the default.

# input record separator ($/)
my @lines         = <STDIN>;                     # regular mode, separating by newlines
my @paragraphs    = do {local $/ = ""; <STDIN>}; # paragraph mode, separating by 2 or more newlines
my $whole_content = do {local $/; <STDIN>};      # slurp mode, no separation

# output field and output record separators
sub write_csv_file ($rows, $filename) {
  open my $fh, ">:unix", $filename or die "cannot write into $filename: $!";
  local $, = ",";               # output field separator -- inserted between columns
  local $\ = "\r\n";            # output row separator   -- inserted between rows
  print $fh @$_ foreach @$rows; # assuming that each member of @$rows is an arrayref
}

# list separator in interpolated strings
my @perl_files   = <*.pl>; # globbing perl files in the current directory
my @python_files = <*.py>; # idem for python files
{ local $" = ", ";         # lists will be comma-separated when interpolated in a string
  say "I found these perl files: @perl_files and these python files: @python_files";
}

Interface to the operating system

We have already seen two examples involving the %ENV hash of environment variables inherited from the operating system. Likewise, it is possible to tweak the @ARGV array before parsing the command-line arguments. Another interesting variable is the %SIG hash of signal handlers, as documented in perlipc:

{ local $SIG{HUP} = "IGNORE"; # don't want to be disturbed for a while
  do_some_tricky_computation();
}

Predefined handles like STDIN, STDOUT and STDERR can also be localized:

say "printing to regular STDOUT";
{ local *STDOUT;
  open STDOUT, ">", "captured_stdout.txt" or die $!;
  do_some_verbose_computation();
}
say "back to regular STDOUT";

Localizing package members

Package global variables

Global variables are declared with the our keyword. The difference with lexical variables (declared with my) is that such global variables are accessible, not only from within the package, but also from the outside, if prefixed by the package name. So if package Foo::Bar declares our ($x, @a, %h), these variables are accessible from anywhere in the Perl program under $Foo::Bar::x, @Foo::Bar::a or %Foo::Bar::h.

Many CPAN modules use such global variables to expose their public API. For example, the venerable Data::Dumper chooses among various styles for dumping a data structure, depending on the $Data::Dumper::Indent variable. The default (style 2) is optimized for readability, but sometimes the compact style 0 is more appropriate:

print Dumper($data_tree);
print do {local $Data::Dumper::Indent=0; Dumper($other_tree)};

Carp or URI are other examples of well-known modules where global variables are used as a configuration API.

Modules with this kind of architecture are often pretty old; more recent modules tend to prefer an object-oriented style, where the configuration options are given as options to the new() method instead of using global variables. Of course the object-oriented architecture offers better encapsulation, since a large program can work with several instances of the same module, each instance having its own configuration options, without interference between them. This is not to say, however, that object-oriented configuration is always the best solution: when it comes to tracing, debugging or profiling needs, it is often very convenient to be able to tune a global knob and have its effect applied to the whole program: in those situations, what you want is just the opposite of strict encapsulation! Therefore some modules, although written in a modern style, still made the wise choice of leaving some options expressed as global variables; changing these options has a global effect, but thanks to local this effect can be limited to a specific scope. Examples can be found in Type::Tiny or in List::Util.

Subroutines (aka monkey-patching)

Every package has a symbol table that contains not only its global variables, but also the subroutines (or methods) declared in that package. Since the symbol table is writeable, it is possible to overwrite any subroutine, thereby changing the behaviour of the package - an operation called monkey-patching. Of course monkey-patching could easily create chaos, so it should be used with care - but in some circumstances it is extremely powerful and practical. In particular, testing frameworks often use monkey-patching for mocking interactions with the outside world, so that the internal behaviour of a sofware component can be tested in isolation.

The following example is not very realistic, but it's the best I could come up with to convey the idea in just a few lines of code. Consider a big application equipped with a logger object. Here we will use a logger from Log::Dispatch:

use Log::Dispatch;
my $log = Log::Dispatch->new(
  outputs   => [['Screen', min_level => 'info', newline => 1]],
);

The logger has methods debug(), info(), error(), etc. for accepting messages at different levels. Here it is configured to only log messages starting from level info; so when the client code calls info(), the message is printed, while calls to debug() are ignored. As a result, when the following routine is called, we normally only see the messages "start working ..." and "end working ...":

sub work ($phase) {
  $log->info("start working on $phase");
  $log->debug("weird condition while doing $phase"); # normally not seen - level below 'info'
  $log->info("end working on $phase\n");
}

Now suppose that we don't want to change the log level for the whole application, but nevertheless we need to see the debug messages at a given point of execution. One (dirty!) way of achieving this is to temporarily treat calls to debug() as if they were calls to info(). So a scenario like

work("initial setup");
{ local *Log::Dispatch::debug = *Log::Dispatch::info; # temporarily alias the 'debug' method to 'info'
  work("core stuff")}
work("cleanup");

logs the following sequence:

start working on initial setup
end working on initial setup

start working on core stuff
weird condition while doing core stuff
end working on core stuff

start working on cleanup
end working on cleanup

Monkey-patching techniques are not specific to Perl; they are used in all dynamic languages (Python, Javascript, etc.), not for regular programming needs, but rather for testing or profiling tasks. However, since other dynamic languages do not have the local mechanism, temporary changes to the symbol table must be programmed by hand, by storing the initial code reference in a temporary variable, and restoring it when exiting from the monkey-patched scope. This is a bit more work and is more error-prone. Often there are library modules for making the job easier, though: see for example https://docs.pytest.org/en/7.1.x/how-to/monkeypatch.html in Python.

Monkey-patching in a statically-typed language like Java is more acrobatic, as shown in Nicolas FrƤnkel's blog.

Localizing elements of arrays or hashes

The value of an array at a specific index, or the value of a hash for a specific key, can be localized too. We have already seen some examples with the builtin hashes %ENV or %SIG, but it works as well on user data, even when the data structure is several levels deep. A typical use case for this is when a Web application loads a JSON, YAML or XML config file at startup. The config data becomes a nested tree in memory; if for any reason that config data must be changed at some point, local can override a specific data leaf, or any intermediate subtree, like this:

local $app->config->{logger_file} = '/opt/log/special.log';
local $app->config->{session}     = {storage => '/opt/data/app_session',
                                     expires => 42900,
                                    };

Another example can be seen in my Data::Domain module. The job of that module is to walk through a datatree and check if it meets the conditions expected by a "domain". The inspect() method that does the checking sometimes needs to know at which node it is currently located; so a $context tree is worked upon during the traversal and passed to every method call. With the help of local, temporary changes to the shape of $context are very easy to implement:

  for (my $i = 0; $i < $n_items; $i++) {
    local $context->{path} = [@{$context->{path}}, $i];
    ...

An alternative could have been to just push $i on top of the @{$context->{path}} array, and then pop it back at the end of the block. But since this code may call subclasses written by other people, with little guarantee on how they would behave with respect to $context->{path}, it is safer to localize it and be sure that $context->{path} is in a clean state when starting the next iteration of the loop. Interested readers can skim through the source code to see the full story. A similar technique can also be observed in Catalyst::Dispatcher.

A final example is the well-known DBI module, whose rich API exploits several Perl mechanisms simultaneously. DBI is principally object-oriented, except that the objects are called "handles"; but in addition to methods, handles also have "attributes" accessible as hash members. The DBI documentation explicitly recommends to use local for temporary modifications to the values of attributes, for example for the RaiseError attribute. This is interesting because it shows a dichotomy between API styles: if DBI had a purely object-oriented style, with usual getter and setter methods, it would be impossible to use the benefits of local - temporary changes to an attribute followed by a revert to the previous value would have to be programmed by hand.

How other languages handle temporary changes to global state

As argued earlier, the need for temporary changes to global state occurs in every programming language, in particular for testing, tracing or profiling tasks. When dynamic scoping is not present, the most common solution is to write specific code for storing the old state in a temporary variable, implement the change for the duration of a given computation, and then restore the old state. A common best practice for such situations is to use a try ... finally ... construct, where restoration to the old state is implemented in the finally clause: this guarantees that even if exceptions occur, the code exits with a clean state. Most languages do possess such constructs - this is definitely the case for Java, JavaScript and Python.

Python context managers

Python has a mechanism more specifically targeted at temporary changes of context : this is called context manager, triggered through a with statement. A context manager implements special methods __enter__() and __exit__() that can be programmed to operate changes into the global context. This technique offers more precision than Perl's local construct, since the enter and exit methods are free to implement any kind of computation; however it is less general, because each context manager is specialized for a specific task. Python's contextlib library provides a collection of context managers for common needs.

Wrapping up

Perl's local mechanism is often misunderstood. It is frowned upon because it breaks encapsulation - and this criticism is perfectly legitimate as far as regular programming tasks are concerned; but on the other hand, it is a powerful and clean mechanism for temporary changes to the global execution state. It solves real problems with surprising grace, and it’s one of the features that makes Perl uniquely expressive among modern languages. So do not follow the common advice to avoid local at all costs, but learn to identify the situations where local will be a helpful tool to you!

Beyond the mere mechanism, the question is more at the level of philosophy of programming: to which extent should we enforce strict encapsulation of components? In an ideal world, each component has a well-defined interface, and interactions are only allowed to go through the official interfaces. But in a big assembly of components, we may encounter situations that were not foreseen by the designers of the individual components, and require inserting some additional screws, or drilling some additional holes, so that the global assembly works satisfactorily. This is where Perl's local is a beautiful device.

About the cover picture

The cover picture1 represents a violin with a modified global state: the two intermediate strings are crossed! This is the most spectacular example of scordatura in Heirich Biber's Rosary sonatas (sometimes also called "Mystery sonatas"). Each sonata in the collection requires to tune the violin in a specific way, different from the standard tuning in fifths, resulting in very different atmospheres. It requires some intellectual gymnastics from the player, because the notes written in the score no longer represent the actual sounds heard, but merely refer to the locations of fingers on a normal violin; in other words, this operation is like monkey-patching a violin!

  1. CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=110521795 ↩

[MERGE] assorted LOGOP peephole stuff

Assorted commits which fix a performance regression and do refactoring
of the handling of LOGOPs in the peephole optimiser. In particular,

    @res = $c ? () : @f

had a very slight regression: it should have got faster recently, but
actually got slightly slower. It's now fast again.

This week, I challenged myself to write small but meaningful Perl programs for Weekly Challenge — focusing on clean logic, edge cases, and test-driven validation.

Sometimes, the simplest problems teach the strongest lessons.

Challenge 1: Text Justifier (Centering Text with Custom Padding)

Problem Statement
Write a script to return the string that centers the text within that width using asterisks * as padding.

If the string length is greater than or equal to the width, return the string as-is.

Example
Input:

("Hi", 5)

Output:

*Hi**

Implementation Highlights

  • Calculated total padding required.
  • Split padding evenly left and right.
  • Handled odd padding differences correctly.
  • Covered edge cases like:
    • Empty string
    • Width equal to string length
    • Width smaller than string length

Key Logic

my $pad_total = $width - $len;
my $left_pad = int($pad_total / 2);
my $right_pad = $pad_total - $left_pad;

This ensures perfect centering even when padding is odd.

What I Learned

  • Importance of integer division in layout formatting
  • Handling edge cases makes logic robust
  • Writing test cases increases confidence immediately

Challenge 2: Word Sorter (Alphabetical Word Sorting)

Problem Statement
Write a script to order words in the given sentence alphabetically but keeps the words themselves unchanged.

Example
Input:

"I have 2 apples and 3 bananas!"

Output:

2 3 and apples bananas! have I

Implementation Highlights

  • Split words using whitespace regex
  • Used Perl’s built-in sort
  • Rejoined words with single spaces
  • Managed multiple spaces correctly

Core Logic

my @words = split /\s+/, $str;
return join ' ', sort @words;

Simple. Elegant. Effective.

What I Learned

  • Perl’s sort is powerful and concise
  • Regex-based splitting handles messy input cleanly
  • Even small scripts benefit from structured testing
As you know, The Weekly Challenge, primarily focus on Perl and Raku. During the Week #018, we received solutions to The Weekly Challenge - 018 by Orestis Zekai in Python. It was pleasant surprise to receive solutions in something other than Perl and Raku. Ever since regular team members also started contributing in other languages like Ada, APL, Awk, BASIC, Bash, Bc, Befunge-93, Bourne Shell, BQN, Brainfuck, C3, C, CESIL, Chef, COBOL, Coconut, C Shell, C++, Clojure, Crystal, CUDA, D, Dart, Dc, Elixir, Elm, Emacs Lisp, Erlang, Excel VBA, F#, Factor, Fennel, Fish, Forth, Fortran, Gembase, Gleam, GNAT, Go, GP, Groovy, Haskell, Haxe, HTML, Hy, Idris, IO, J, Janet, Java, JavaScript, Julia, K, Kap, Korn Shell, Kotlin, Lisp, Logo, Lua, M4, Maxima, Miranda, Modula 3, MMIX, Mumps, Myrddin, Nelua, Nim, Nix, Node.js, Nuweb, Oberon, Octave, OCaml, Odin, Ook, Pascal, PHP, PicoLisp, Python, PostgreSQL, Postscript, PowerShell, Prolog, R, Racket, Rexx, Ring, Roc, Ruby, Rust, Scala, Scheme, Sed, Smalltalk, SQL, Standard ML, SVG, Swift, Tcl, TypeScript, Typst, Uiua, V, Visual BASIC, WebAssembly, Wolfram, XSLT, YaBasic and Zig.

File is empty after writing to it

Perl questions on StackOverflow

I'm working on a little wikilink to Markdown link converter with Perl. This is the conversion code:

foreach my $idx (0 .. $args) {
  if (-e -f -r -w $ARGV[$idx]) {
    my $file_name = $ARGV[$idx];
    open(my $file_reader, "<", $file_name) or die "Failed to open file reader: $!";

    my $new_file_content = "";
    while (my $line = <$file_reader>) {
      if ($line =~ /(\[\[.+?\]\])/) {
        my $extracted_text = substr($1, 2, -2);
        my $new_line = $line =~ s/\[\[.+?\]\]/\[$extracted_text\]\(\.\/$extracted_text$ext\)/gr;
        $new_file_content = $new_file_content . $new_line;
      } else {
        $new_file_content = $new_file_content . $line;
      }
    }
    close($file_reader) or die "Failed to close file reader: $!";

    # This is where it writes to the file
    if ($overwrite) {
      print("Overwriting $file_name...\n\n");
      open(my $file_writer, ">", $file_name) or die "Failed to open file writer: $!";
      print($file_writer, $new_file_content);
      close($file_writer) or die "Failed to close file writer: $!";
    } else {
      print("$new_file_content");
    }
  }
}

The link conversion itself is fine, but when writing to the file, it always ends up empty. I'm not sure as to what could be causing this.

(dlxxxvii) 10 great CPAN modules released last week

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

  1. Data::ObjectDriver - Simple, transparent data interface, with caching
    • Version: 0.27 on 2026-02-13, with 16 votes
    • Previous CPAN version: 0.26 was 3 months, 27 days before
    • Author: SIXAPART
  2. DateTime::Format::Natural - Parse informal natural language date/time strings
    • Version: 1.25 on 2026-02-13, with 19 votes
    • Previous CPAN version: 1.24_01 was 1 day before
    • Author: SCHUBIGER
  3. Devel::Size - Perl extension for finding the memory usage of Perl variables
    • Version: 0.86 on 2026-02-10, with 22 votes
    • Previous CPAN version: 0.86 was 1 day before
    • Author: NWCLARK
  4. Marlin - 🐟 pretty fast class builder with most Moo/Moose features 🐟
    • Version: 0.023001 on 2026-02-14, with 12 votes
    • Previous CPAN version: 0.023000 was 7 days before
    • Author: TOBYINK
  5. MIME::Lite - low-calorie MIME generator
    • Version: 3.037 on 2026-02-11, with 35 votes
    • Previous CPAN version: 3.036 was 1 day before
    • Author: RJBS
  6. MIME::Body - Tools to manipulate MIME messages
    • Version: 5.517 on 2026-02-11, with 15 votes
    • Previous CPAN version: 5.516
    • Author: DSKOLL
  7. Net::BitTorrent - Pure Perl BitTorrent Client
    • Version: v2.0.0 on 2026-02-13, with 13 votes
    • Previous CPAN version: 0.052 was 15 years, 10 months before
    • Author: SANKO
  8. Net::Server - Extensible Perl internet server
    • Version: 2.017 on 2026-02-09, with 34 votes
    • Previous CPAN version: 2.016 was 12 days before
    • Author: BBB
  9. Protocol::HTTP2 - HTTP/2 protocol implementation (RFC 7540)
    • Version: 1.12 on 2026-02-14, with 27 votes
    • Previous CPAN version: 1.11 was 1 year, 8 months, 25 days before
    • Author: CRUX
  10. SPVM - The SPVM Language
    • Version: 0.990130 on 2026-02-13, with 36 votes
    • Previous CPAN version: 0.990129 was 1 day before
    • Author: KIMOTO

Which the best way for deploying an Perl Mojolicious web app to an containerized production environment like Docker or Kubernets:

# one process per pod
/script/my_app daemon

or starting an more powerful multiple ones:

# myapp.conf
{
  hypnotoad => {
    listen  => ['https://*:443?cert=/etc/server.crt&key=/etc/server.key'],
    workers => 5
  }
};
 
hypnotoad ./script/my_app

Join us for TPRC 2026 in Greenville, SC!

Perl Foundation News

We are pleased to announce the dates of our next Perl and Raku Conference, to be held in Greenville, SC on June 26-28, 2026.Ā  The venue is the same as last year, but we are expanding the conference to 3 days of talks/presentations across the weekend.Ā  One or more classes will be scheduled for Monday the 29th as well. The hackathon will be running continuously from June 25 through June 29—so if you can come early or stay late, there will be opportunities for involvement with other members of the community.

Mark your calendars and save the dates!

Our website, https://www.tprc.us/Ā  has more details including links to reserve your hotel room and a link to register for the conference at the early bird price.Ā  Watch for more updates as more plans are finalized.

Our theme for 2026 is ā€œPerl is my cast iron panā€.Ā  Perl is reliable, versatile, durable, and continues to be ever so useful!Ā  Just like your favorite cast iron pan! Raku might map to tempered steel.Ā  also quite reliable and useful, and with some very attractive updates!

We hope to see you in June!

My presentation will look at coding agents from Anthropic and z.ai with the following questions:

How (well) can coding agents support Perl code?

What differences are there between the models?

How can I get agents to write good code?

Hope to see you there:

https://act.yapc.eu/gpw2026/

My Blog

blogs.perl.org

This is my first post in this Blog...
I will write about Perl

This week in PSC (215) | 2026-02-11

blogs.perl.org

All three of us attended.

  • We spent a long time debating how to proceed with Karl’s proposal to restrict legal identifier names for security. No consensus emerged, and we resolved to ask the question in a venue with wider reach than p5p.

  • We are faced with an absent maintainer of a CPAN-upstream dual-life module, namely Encode. We discussed this situation in general terms but did not get beyond the question itself – partly due to time constraints. We agreed that this seems likely to occur more often in the future and that p5p will need an agreed way of dealing with it, but what that should be is too big a topic to be contained within the PSC meeting format.

  • There are multiple PRs currently in flight, some of them rather large, including Paul’s magic v2 and attributes v2. We decided that we are too close to contentious changes freeze in this cycle to merge those.

[P5P posting of this summary]

We're happy to have Abigail present at the German Perl Workshop 2026!

Sharding a database, twice richtet sich an Alle und wird in English gehalten.

There comes a time in the life time of a database, the database takes too many resources (be it disk space, number of I/O transactions, or something else) to be handled by a single box.

Sharding, where data is distributed over several identically shaped databases is one technique to solve this.

For a high volume database I used to work with, we hit this limit about a dozen
years ago. Then we hit the limit again two years ago.

In this talk, we will first discuss how we initialized switched our systems to make use of a sharded database, without any significant downtime.

PAGI::Server, now with HTTP/2!

dev.to #perl

PAGI 0.001017 is on CPAN. The headline feature is HTTP/2 support in PAGI::Server, built on the nghttp2 C library and validated against h2spec's conformance suite. HTTP/2 is marked experimental in this release -- the protocol works, the compliance numbers are solid, and we want production feedback before dropping that label.

This post focuses on why h2c (cleartext HTTP/2) between your reverse proxy and backend matters, and how PAGI::Server implements it.

The Quick Version

# Install the HTTP/2 dependency
cpanm Net::HTTP2::nghttp2

# Run with HTTP/2 over TLS
pagi-server --http2 --ssl-cert cert.pem --ssl-key key.pem app.pl

# Run with cleartext HTTP/2 (h2c) -- behind a proxy
pagi-server --http2 app.pl

Your app code doesn't change. HTTP/2 is a transport concern handled entirely by the server. The same async handlers that serve HTTP/1.1 serve HTTP/2 without modification.

"I Have nginx in Front, Why Do I Care?"

If nginx terminates TLS and speaks HTTP/2 to clients, why does the backend need HTTP/2 too?

The answer is h2c -- cleartext HTTP/2 between your proxy and your application server. No TLS overhead, but all of HTTP/2's protocol benefits on the internal hop: stream multiplexing over a single TCP connection, HPACK header compression (especially effective for repetitive internal headers like auth tokens and tracing IDs), and per-stream flow control so a slow response on one stream doesn't block others.

The practical wins: fewer TCP connections between proxy and backend (one multiplexed h2c connection replaces a pool of HTTP/1.1 connections), less file descriptor and kernel memory pressure, and no TIME_WAIT churn from connection recycling.

Where h2c Matters

gRPC requires HTTP/2 -- it doesn't work over HTTP/1.1 at all. If you're building gRPC services, h2c is mandatory.

API gateway fan-out is where multiplexing shines. When your gateway fans out to 10 backend services per request, h2c means 1-2 connections per backend instead of a pool of 50-100.

Service mesh environments (Envoy/Istio sidecars) default to HTTP/2 between services. A backend that speaks h2c natively means one less protocol translation.

A Note on Proxies

Not all proxies handle h2c equally:

  • Envoy has the best h2c upstream support with full multiplexing
  • Caddy makes it trivial: reverse_proxy h2c://localhost:8080
  • nginx supports h2c via grpc_pass for gRPC workloads, but its generic proxy_pass doesn't support proxy_http_version 2.0

For full multiplexing to backends, Envoy or Caddy are better choices than nginx today.

HTTP/2 Over TLS -- No Proxy Required

h2c isn't the only mode. PAGI::Server also does full HTTP/2 over TLS with ALPN negotiation:

pagi-server --http2 --ssl-cert cert.pem --ssl-key key.pem app.pl

This is useful when you don't want the overhead or complexity of a reverse proxy -- internal tools, admin dashboards, development servers, or any app where the traffic doesn't justify a separate proxy layer. Browsers get HTTP/2 directly, with TLS, no nginx required.

What PAGI::Server Does

Dual-Mode Protocol Detection

With TLS, PAGI::Server uses ALPN negotiation during the handshake -- advertising h2 and http/1.1, letting the client choose. The protocol is decided before the first byte of application data.

Without TLS (h2c mode), PAGI::Server inspects the first 24 bytes of each connection for the HTTP/2 client connection preface. If it matches, the connection upgrades to HTTP/2. If not, it falls through to HTTP/1.1. Both protocols coexist on the same port, same worker -- no configuration needed beyond --http2.

Either way, HTTP/1.1 clients are still served normally. The server handles both protocols on the same port.

WebSocket over HTTP/2 (RFC 8441)

Most HTTP/2 implementations skip this. PAGI::Server supports the Extended CONNECT protocol from RFC 8441, which tunnels WebSocket connections over HTTP/2 streams. Multiple WebSocket connections multiplex over a single TCP connection instead of requiring one TCP connection each.

Compliance

Built on nghttp2 (the same C library behind curl, Firefox, and Apache's mod_http2). PAGI::Server passes 137 of 146 h2spec conformance tests (93.8%). The 9 remaining failures are in nghttp2 itself and shared with every server that uses it. Load tested with h2load at 60,000 requests across 50 concurrent connections with no data loss or protocol violations.

Full test-by-test results are published: HTTP/2 Compliance Results.

Multi-Worker and Tunable

HTTP/2 works in multi-worker prefork mode. Each worker independently handles HTTP/2 sessions:

pagi-server --http2 --workers 4 app.pl

Protocol settings are exposed for environments that need fine-tuning:

my $server = PAGI::Server->new(
    app   => $app,
    http2 => 1,
    h2_max_concurrent_streams => 50,   # default: 100
    h2_initial_window_size => 131072,  # default: 65535
    h2_max_frame_size => 32768,        # default: 16384
    h2_max_header_list_size => 32768,  # default: 65536
);

Most deployments won't need to touch these. The defaults follow the RFC recommendations.

Context in the Perl Ecosystem

Perl has had HTTP/2 libraries on CPAN (Protocol::HTTP2, Net::HTTP2), but application servers haven't integrated them with validated compliance testing. PAGI::Server is the first to publish h2spec results and ship h2c with automatic protocol detection alongside HTTP/1.1. If you're currently running Starman, Twiggy, or Hypnotoad, none of them offer HTTP/2.

What Else Is in 0.001017

The rest of the release is operational improvements:

  • Worker heartbeat monitoring -- parent process detects workers with blocked event loops and replaces them via SIGKILL + respawn. Default 50s timeout. Only triggers on true event loop starvation; async handlers using await are unaffected.
  • Custom access log format -- format strings with atoms like %a (address), %s (status), %D (duration).
  • TLS performance fix -- shared SSL context via SSL_reuse_ctx eliminates per-connection CA bundle parsing. 26x throughput improvement at 8+ concurrent TLS connections.
  • SSE wire format fix -- now handles CRLF, LF, and bare CR line endings per the SSE specification.
  • Multi-worker fixes -- shutdown escalation, parameter pass-through, and various stability improvements.

Getting Started

# Install PAGI
cpanm PAGI

# Install HTTP/2 support (optional)
cpanm Net::HTTP2::nghttp2

# Run your app with HTTP/2
pagi-server --http2 app.pl

Links

PWC 360 Pertaining to a subtlety of sorting

dev.to #perl

It's been a while since I commented on a Weekly Challenge solution, but here we are at week 360. Such a useful number. So divisible, so circular. It deserves twenty minutes.

Task 2: Word Sorter

The task

You are given a sentence. Write a script to order words in the given
sentence alphabetically but keep the words themselves unchanged.

# Example 1 Input: $str = "The quick brown fox"
#           Output: "brown fox quick The"
# Example 2 Input: $str = "Hello    World!   How   are you?"
#           Output: "are Hello How World! you?"
# Example 3 Input: $str = "Hello"
#           Output: "Hello"
# Example 4 Input: $str = "Hello, World! How are you?"
#           Output: "are Hello, How World! you?"
# Example 5 Input: $str = "I have 2 apples and 3 bananas!"
#           Output: "2 3 and apples bananas! have I"

The thoughts

This should be quite simple: split the words, sort them, put them back together. The sort should be case-insensitive.

join " ", sort { lc($a) cmp lc($b) } split(" ", $str);

Creeping doubt #1

Is converting to lowercase with lc the right way to do case-insenstive compares? Not really. Perl has the fc -- fold-case -- function to take care of subtleties in Unicode. We won't see those in simple ASCII text, but for the full rabbit hole, start with the documentation of fc.

Creeping doubt #2

Doing the case conversion inside the sort means that we will invoke that every time there's a string comparison, which will be quite redundant. We could (probably?) speed it up by pre-calculating the conversions once.

The solution

sub sorter($str)
{
    return join " ",
        map { $_->[0] }
        sort { $a->[1] cmp $b->[1] }
        map { [$_, fc($_)] }
        split(" ", $str);
}

This solution uses the idiom of Schwartzian transformation. Every word gets turned into a pair of [original_word, case_folded_word]. That array of pairs gets sorted, and then we select the original words out of the sorted pairs. This is best read bottom-up.

  • split(" ", $str) -- turns the string into an array of words, where words are loosely defined by being white-space separated.
  • map { [$_, fc($_)] } -- every word turns into a pair: the original, and its case-folded variation. The result is a list of array references.
  • sort { $a->[1] cmp $b->[1] } -- sort by the case-folded versions. The result is still a list of array references.
  • map { $_->[0] } -- select the original word from each pair
  • join " " -- Return a single string, where the words are separated by one space.

Does it blend?

A quick benchmark shows that it is indeed faster to pre-calculate the case folding. This example used a text string of about 60 words.

           Rate oneline  pre_lc
oneline 32258/s      --    -45%
pre_lc  58140/s     80%      --

My intuition says that when the strings are much shorter, the overhead of the transform might not offset the gains in the sort, but as is so often true, my intuition is crap. This is the result for a string of five words:

oneline  470588/s      --    -59%
pre_lc  1142857/s    143%      --

100 days of Perl …

Perl on Medium

… or maybe some more ;)

  • 00:00 Introduction

  • 01:30 OSDC Perl, mention last week

  • 03:00 Nikolai Shaplov NATARAJ, one of our guests author of Lingua-StarDict-Writer on GitLab.

  • 04:30 Nikolai explaining his goals about security memory leak in Net::SSLeay

  • 05:58 What we did earlier. (Low hanging fruits.)

  • 07:00 Let's take a look at the repository of Net::SSLeay

  • 08:00 Try understand what happens in the repository?

  • 09:15 A bit of explanation about adopting a module. (co-maintainer, unauthorized uploads)

  • 11:00 PAUSE

  • 15:30 Check the "river" status of the distribution. (reverse dependency)

  • 17:20 You can CC-me in your correspondence.

  • 18:45 Ask people to review your pull-requests.

  • 21:30 Mention the issue with DBIx::Class and how to take over a module.

  • 23:50 A bit about the OSDC Perl page.

  • 24:55 CPAN Dashboard and how to add yourself to it.

  • 27:40 Show the issues I opened asking author if they are interested in setting up GitHub Actions.

  • 29:25 Start working on Dancer-Template-Mason

  • 30:00 clone it

  • 31:15 perl-tester Docker image.

  • 33:30 Installing the dependencies in the Docker container

  • 34:40 Create the GitHub Workflow file. Add to git. Push it out to GitHub.

  • 40:55 First failure in the CI which is unclear.

  • 42:30 Verifying the problem locally.

  • 43:10 Open an issue.

  • 58:25 Can you talk about dzil and Dist::Zilla?

  • 1:02:25 We get back to working in the CI.

  • 1:03:25 Add --notest to make installations run faster.

  • 1:05:30 Add the git configuration to the CI workflow.

  • 1:06:32 Is it safe to use --notest when installing dependencies?

  • 1:11:05 git rebase squashing the commits into one commit

  • 1:13:35 git push --force

  • 1:14:10 Send the pull-request.

Black box test generator version 0.28 released

r/perl

I've published version 0.28 of App::Test::Generator, the black-box test case generator. I focused on tightening SchemaExtractor’s handling of accessor methods and making the generated schemas more honest and testable. I fixed cases where getter/setter and combined getset routines were being missed, added targeted tests to lock in correct detection of getset accessors, and clarified output typing so weak scalar inference no longer masquerades as a real type. I added explicit 'isa' coverage, ensuring that object expectations are captured and that generated tests correctly fail when passed the wrong object type.

https://metacpan.org/pod/App::Test::Generator

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

YAML Aint Quite a Superset of JSON (YAMLAQSJ)

r/perl

Answer

I use xscreensaver and to forbid it:

! in .Xresources
xscreensaver.splash: false
! Set to nothing makes user switching not possible
*.newLoginCommand:

Lightdm supports .d directories, by default they aren’t created on Debian but upstream documents them clearly. In other words: /etc/lightdm/lightdm.conf.d/ is read.

Which means you need to drop a file, /etc/lightdm/lightdm.conf.d/10-local-overrides.conf and add the content:

[Seat:*]
allow-user-switching=false
allow-guest=false

To check your configuration:

lightdm --show-config
Thank you Team PWC for your continuous support and encouragement.
Welcome to the Week #360 of The Weekly Challenge.

(dlxxxvi) 10 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::rdapper - a command-line RDAP client.
    • Version: 1.23 on 2026-02-02, with 21 votes
    • Previous CPAN version: 1.22 was 3 days before
    • Author: GBROWN
  2. Beam::Wire - Lightweight Dependency Injection Container
    • Version: 1.030 on 2026-02-04, with 19 votes
    • Previous CPAN version: 1.029 was 1 day before
    • Author: PREACTION
  3. BerkeleyDB - Perl extension for Berkeley DB version 2, 3, 4, 5 or 6
    • Version: 0.67 on 2026-02-01, with 14 votes
    • Previous CPAN version: 0.66 was 1 year, 3 months, 18 days before
    • Author: PMQS
  4. Data::Alias - Comprehensive set of aliasing operations
    • Version: 1.29 on 2026-02-02, with 19 votes
    • Previous CPAN version: 1.28 was 3 years, 1 month, 12 days before
    • Author: XMATH
  5. Image::ExifTool - Read and write meta information
    • Version: 13.50 on 2026-02-07, with 44 votes
    • Previous CPAN version: 13.44 was 1 month, 22 days before
    • Author: EXIFTOOL
  6. IO::Compress - IO Interface to compressed data files/buffers
    • Version: 2.217 on 2026-02-01, with 19 votes
    • Previous CPAN version: 2.216 was 1 day before
    • Author: PMQS
  7. Perl::Tidy - indent and reformat perl scripts
    • Version: 20260204 on 2026-02-03, with 147 votes
    • Previous CPAN version: 20260109 was 25 days before
    • Author: SHANCOCK
  8. Sisimai - Mail Analyzing Interface for bounce mails.
    • Version: v5.6.0 on 2026-02-02, with 81 votes
    • Previous CPAN version: v5.5.0 was 1 month, 28 days before
    • Author: AKXLIX
  9. SPVM - The SPVM Language
    • Version: 0.990127 on 2026-02-04, with 36 votes
    • Previous CPAN version: 0.990126 was before
    • Author: KIMOTO
  10. Term::Choose - Choose items from a list interactively.
    • Version: 1.780 on 2026-02-04, with 15 votes
    • Previous CPAN version: 1.779 was 2 days before
    • Author: KUERBIS

(dcxxiv) metacpan weekly report - XS::JIT

Niceperl

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

Week's winner: XS::JIT (+5)

Build date: 2026/02/07 20:47:56 GMT


Clicked for first time:


Increasing its reputation:


Dave writes:

During January, I finished working on another tranche of ExtUtils::ParseXS fixups, this time focussing on:

  • adding and rewording warning and error messages, and adding new tests for them;

  • improving test coverage: all XS keywords have tests now;

  • reorganising the test infrastructure: deleting obsolete test files, renaming the t/*.t files to a more consistent format; splitting a large test file; modernising tests;

  • refactoring and improving the length(str) pseudo-parameter implementation.

I also started work on my annual "get './TEST -deparse' working again" campaign. This option runs all the test suite files through a round trip in the deparser before running them. Over the course of the year we invariably accumulate new breakage; sometimes this involves fixing Deparse.pm, and sometimes just back-listing the test file as it is now tickling an already known issue in the deparser.

I also worked on a couple of bugs.

Summary:

  • 0:53 GH #13878 COW speedup lost after e8c6a474
  • 4:05 GH #24110 ExtUtils::ParseXS after 5.51 prevents some XS modules to build
  • 12:14 fix up Deparse breakage
  • 26:12 improve Extutils::ParseXS

Total:

  • 43:24 (HH::MM)

Tony writes:

``` [Hours] [Activity] 2026/01/05 Monday 0.23 #24055 review, research and approve with comment 0.08 #24054 review and approve 0.12 #24052 review and comment 1.13 #24044 review, research and approve with comment 0.37 #24043 review and approve 0.78 #23918 rebase, testing, push and mark ready for review 1.58 #24001 fix related call_sv() issue, testing

0.65 #24001 testing, debugging

4.94

2026/01/06 Tuesday 0.90 #24034 review and comment 1.12 #24024 research and follow-up 1.40 #24001 debug crash in init_debugger() and work up a fix, testing

0.08 #24001 re-check, push for CI

3.50

2026/01/07 Wednesday 0.15 #24034 review updates and approve 0.55 #23641 review and comment 0.23 #23961 review and approve 0.28 #23988 review and approve with comment 0.62 #24001 check CI results and open PR 24060 0.50 #24059 review and comments 0.82 #24024 work on a test and the fix, testing 0.27 #24024 add perldelta, testing, make PR 24061 1.13 #24040 work on a test and a fix, testing, investigate

other possible similar problems

4.55

2026/01/08 Thursday 0.35 #24024 minor fixes, comment, get approval, apply to blead 0.72 #24040 rebase, perldelta, find a simplification, testing and re-push 0.18 #24053 review and approve 0.77 #24063 review, research, testing and comment 1.47 #24040 look at goto too, look for other similar issues and open 24064, fix for goto (PVOP), testing and push for CI 0.32 #24040 check CI results, make PR 24065

0.28 #24050 review and comment

4.09

2026/01/09 Friday

0.20 #24059 review updates and comment

0.20

2026/01/12 Monday 0.32 #24059 review updates and approve 0.35 #24066 review and approve 0.22 #24040 rebase and clean up whitespace, apply to blead 1.00 #23966 rebase, testing (expected issues from the #23885 merge but I guess I got the magic docs right) 1.05 #24062 review up to ā€˜ParseXS: tidy up INCLUDE error messages’ 0.25 #24069 review and comment

0.62 #24071 part review and comment

3.81

2026/01/13 Tuesday 1.70 #24070 research and comment 0.23 #24069 review and comment 0.42 #24071 more review

1.02 #24071 more review, comments

3.37

2026/01/14 Wednesday 0.23 #23918 minor fix 0.18 #24069 review updates and approve 0.32 #24077 review and comments 0.53 #24073 review, research and comment 0.87 #24075 review, research and comment 0.45 #24071 benchmarking and comment

1.47 #24019 debugging, brief comment on work so far

4.05

2026/01/15 Thursday 0.37 #24019 debugging and comment on cause of win32 issues 1.02 #24077 review, follow-up 0.08 #24079 review and approve 0.25 #24076 review and approve 0.73 #24062 more review up to ā€˜ParseXS: refactor: don't set $_ in Param::parse()’ 2.03 #24062 more review to ā€˜ParseXS: refactor: 001-basic.t: add

TODO flag’ and comments

4.48

2026/01/19 Monday 1.12 maint-votes, vote apply/testing one of the commits 0.43 github notifications 0.08 #24079 review updates and comment 0.70 #24075 research and approve 0.57 #24063 research, try to break it, comment 1.43 #24062 more review to ā€˜ParseXS: add basic tests for

PREINIT keyword’

4.33

2026/01/20 Tuesday 2.23 #24078 review, testing, comments 0.85 #24098 review, research and comment 1.00 #24062 more review up to ā€˜ParseXS: 001-basic.t: add more

ellipsis tests’

4.08

2026/01/21 Wednesday 0.82 #23995 research and follow-up 0.25 #22125 follow-up 0.23 #24056 research, comment 0.67 #24103 review, research and approve

1.45 #24062 more review to end, comment

3.42

2026/01/22 Thursday 0.10 #24079 review update and approve 0.08 #24106 review and approve 0.10 #24096 review and approve 0.08 #24094 review and approve 0.82 #24080 review, research and comments 0.08 #24081 review and approve 0.75 #24082 review, testing, comment 1.15 #23918 rebase #23966, testing and apply to blead, start on

string APIs

3.16

2026/01/27 Tuesday 0.35 #23956 fix perldelta issues 1.27 #22125 remove debugging detritus, research and comment 1.57 #24080 debugging into SvOOK and PVIO 0.67 #24080 more debugging, comment 0.25 #24120 review and approve

1.03 #23984 review, research and approve

5.14

2026/01/28 Wednesday 0.37 #24080 follow-up 0.10 #24128 review and apply to blead 0.70 #24105 review, look at changes needed 0.15 #23956 check CI results and apply to blead 0.10 #22125 check CI results and apply to blead 0.13 #4106 rebase PR 23262 and testing 0.53 #24001 rebase PR 24060 and testing 0.57 #24129 review and comments 0.28 #24127 review and approve 0.10 #24124 review and approve

0.20 #24123 review and approve with comment

3.23

2026/01/29 Thursday 0.27 #23262 minor change suggested by xenu, testing, push for CI 0.22 #24060 comment 1.63 #24082 review, testing, comments 0.43 #24130 review, check some side issues, approve 0.12 #24077 review updates and approve 0.08 #24121 review and approve 0.08 #24122 review and comment

0.30 #24119 review and approve

3.13

Which I calculate is 59.48 hours.

Approximately 57 tickets were reviewed or worked on, and 6 patches were applied. ```


Paul writes:

This month I managed to finish off a few refalias-related issues, as well as lend some time to help BooK further progress implementing PPC0014

  • 1 = Clear pad after multivar foreach
    • https://github.com/Perl/perl5/pull/240
  • 3 = Fix B::Concise output for OP_MULTIPARAM
    • https://github.com/Perl/perl5/pull/24066
  • 6 = Implement multivariable foreach on refalias
    • https://github.com/Perl/perl5/pull/24094
  • 1 = SVf_AMAGIC flag tidying (as yet unmerged)
    • https://github.com/Perl/perl5/pull/24129
  • 2.5 = Mentoring BooK towards implementing PPC0014
  • 2 = Various github code reviews

Total: 15.5 hours

My focus for February will now be to try to get both attributes-v2 and magic-v2 branches in a state where they can be reviewed, and at least the first parts merged in time for 5.43.9, and hence 5.44, giving us a good base to build further feature ideas on top of.

2025 was a tough year for The Perl and Raku Foundation (TPRF). Funds were sorely needed. The community grants program had been paused due to budget constraints and we were in danger of needing to pause the Perl 5 core maintenance grants. Fastmail stepped up with a USD 10,000 donation and helped TPRF to continue to support Perl 5 core maintenance. Ricardo Signes explains why Fastmail helped keep this very important work on track.

Perl has served us quite well since Fastmail’s inception. We’ve built up a large code base that has continued to work, grow, and improve over twenty years. We’ve stuck with Perl because Perl stuck with us: it kept working and growing and improving, and very rarely did those improvements require us to stop the world and adapt to onerous changes. We know that kind of stability is, in part, a function of the developers of Perl, whose time is spent figuring out how to make Perl better without also making it worse. The money we give toward those efforts is well-spent, because it keeps the improvements coming and the language reliable.

— Ricardo Signes, Director & Chief Developer Experience Officer, Fastmail

One of the reasons that you don’t hear about Perl in the headlines is its reliability. Upgrading your Perl from one version to the next? That can be a very boring deployment. You code worked before and it continues to “just work” after the upgrade. You don’t need to rant about short deprecation cycles, performance degradation or dependencies which no longer install. The Perl 5 core maintainers take great care to ensure that you don’t have to care very much about upgrading your Perl. Backwards compatibility is top of mind. If your deployment is boring, it’s because a lot of care and attention has been given to this matter by the people who love Perl and love to work on it.

As we moved to secure TPRF’s 2025 budget, we reached out to organizations which rely on Perl. A number of these companies immediately offered to help. Fastmail has already been a supporter of TPRF for quite some time. In addition to this much needed donation, Fastmail has been providing rock solid free email hosting to the foundation for many years.

While Fastmail’s donation has been allocated towards Perl 5 Core maintenance, TPRF is now in the position to re-open the community grants program, funding it with USD 10,000 for 2026. There is also an opportunity to increase the community grants funding if sponsor participation increases. As we begin our 2026 fundraising, we are looking to cast a wider net and bring more sponsor organizations on board to help support healthy Perl and Raku ecosystems.

Maybe your organization will be the one to help us double our community grants budget in 2026. To become a sponsor, contact: olaf@perlfoundation.org

“Perl is my cast-iron pan - reliable, versatile, durable, and continues to be ever so useful.” TPRC 2026 brings together a community that embodies all of these qualities, and we’re looking for sponsors to help make this special gathering possible.

About the Conference

The Perl and Raku Conference 2026 is a community-organized gathering of developers, enthusiasts, and industry professionals. It takes place from June 26-28, 2026, in Greenville, South Carolina. The conference will feature an intimate, single-track format that promises high sponsor visibility. We look forward to approximately 80 participants with some of those staying in town for the shoulder days (June 25-29) and a Monday workshop.

Why Sponsor?

  • Give back to the language and communities which have already given so much to you
  • Connect with the developers and craftspeople who build your tools – the ones that are built to last
  • Help to ensure that The Perl and Raku Foundation can continue to fund Perl 5 core maintenance and Community Grants

Sponsorship Tiers

Platinum Sponsor ($6,000)

  • Only 1 sponsorship is available at this level
  • Premium logo placement on conference website
  • This donation qualifies your organization to be a Bronze Level Sponsor of The Perl and Raku Foundation
  • 5-minute speaking slot during opening ceremony
  • 2 complimentary conference passes
  • Priority choice of rollup banner placement
  • Logo prominently displayed on conference badges
  • First choice of major named sponsorship (Conference Dinner, T-shirts, or Swag Bags)
  • Logo on main stage backdrop and conference banners
  • Social media promotion
  • All benefits of lower tiers

Gold Sponsor ($4,000)

  • Logo on all conference materials
  • One complimentary conference pass
  • Rollup banner on display
  • Choice of named sponsorship (Lunch or Snacks)
  • Logo on backdrop and banners
  • Dedicated social media recognition
  • All benefits of lower tiers

Silver Sponsor ($2,000)

  • Logo on conference website
  • Logo on backdrop and banners
  • Choice of smaller named sponsorship (Beverage Bars)
  • Social media mention
  • All benefits of lower tier

Bronze Sponsor ($1,000)

  • Name/logo on conference website
  • Name/logo on backdrop and banners

All Sponsors Receive

  • Logo/name in Update::Daily conference newsletter sidebar
  • Opportunity to provide materials for conference swag bags
  • Recognition during opening and closing ceremonies
  • Listed on conference website sponsor page
  • Mentioned in conference social media

Named Sponsorship Opportunities

Exclusive naming rights available for:

  • Conference Dinner ($2,000) - Signage on tables and buffet
  • Conference Swag Bags ($1,500) - Logo on bags
  • Conference T-Shirts ($1,500) - Logo on sleeve
  • Lunches ($1,500) - Signage at pickup and on menu tickets
  • Snacks ($1,000) - Signage at snack bar
  • Update::Daily Printing ($200) - Logo on masthead

About The Perl and Raku Foundation

Proceeds beyond conference expenses support The Perl and Raku Foundation, a non-profit organization dedicated to advancing the Perl and Raku programming languages through open source development, education, and community building.

Contact Information

For more information on how to become a sponsor, please contact: olaf@perlfoundation.org

OSDC Perl.

  • 00:00 Introduction to OSDC
  • 01:30 Introducing myself Perl Maven, Perl Weekly
  • 02:10 The earlier issues.
  • 03:10 How to select a project to contribute to?
  • 04:50 Chat on OSDC Zulip
  • 06:45 How to select a Perl project?
  • 09:20 CPAN::Digger
  • 10:10 Modules that don't have a link to their VCS.
  • 13:00 Missing CI - GitHub Actions or GitLab Pipeline and Travis-CI.
  • 14:00 Look at Term-ANSIEncode by Richard Kelsch - How to find the repository of this project?
  • 15:38 Switching top look at Common-CodingTools by mistake.
  • 16:30 How MetaCPAN knows where is the repository?
  • 17:52 Clone the repository.
  • 18:15 Use the szabgab/perl Docker container.
  • 22:10 Run perl Makefile.PL, install dependency, run make and make distdir.
  • 23:40 See the generated META.json file.
  • 24:05 Edit the Makefile.PL
  • 24:55 Explaining my method of cloning first (calling it origin) and forking later and calling that fork.
  • 27:00 Really edit Makefile.PL and add the META_MERGE section and verify the generated META.json file.
  • 29:00 Create a branch locally. Commit the change.
  • 30:10 Create a fork on GitHub.
  • 31:45 Add the fork as a remote repository and push the branch to it.
  • 33:20 Linking to the PR on the OSDC Perl report page.
  • 35:00 Planning to add .gitignore and maybe setting up GitHub Action.
  • 36:00 Start from the main branch, create the .gitignore file.
  • 39:00 Run the tests locally. Set up GitHub Actions to run the tests on every push.
  • 44:00 Editing the GHA configuration file.
  • 48:30 Commit, push to the fork, check the results of GitHub Action in my fork on GitHub.
  • 51:45 Look at the version of the perldocker/perl-tester Docker image.
  • 54:40 Update list of Perl versions in the CI. See the results on GitHub.
  • 55:30 Show the version number of perl.
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::ccdiff - Colored Character Diff
    • Version: 0.35 on 2026-01-25, with 20 votes
    • Previous CPAN version: 0.34 was 1 year, 23 days before
    • Author: HMBRAND
  2. App::rdapper - a command-line RDAP client.
    • Version: 1.22 on 2026-01-29, with 21 votes
    • Previous CPAN version: 1.21 was 1 day before
    • Author: GBROWN
  3. App::SpeedTest - Command line interface to speedtest.net
    • Version: 0.31 on 2026-01-25, with 32 votes
    • Previous CPAN version: 0.30 was 1 year, 18 days before
    • Author: HMBRAND
  4. CPAN::Meta - the distribution metadata for a CPAN dist
    • Version: 2.150012 on 2026-01-25, with 39 votes
    • Previous CPAN version: 2.150011 was 3 days before
    • Author: RJBS
  5. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260129.001 on 2026-01-29, with 25 votes
    • Previous CPAN version: 20260125.001 was 3 days before
    • Author: BRIANDFOY
  6. Cucumber::TagExpressions - A library for parsing and evaluating cucumber tag expressions (filters)
    • Version: 9.0.0 on 2026-01-25, with 17 votes
    • Previous CPAN version: 8.1.0 was 1 month, 29 days before
    • Author: CUKEBOT
  7. Dancer - lightweight yet powerful web application framework
    • Version: 1.3522 on 2026-01-26, with 149 votes
    • Previous CPAN version: 1.3521 was 2 years, 11 months, 18 days before
    • Author: BIGPRESH
  8. Dist::Zilla - distribution builder; installer not included!
    • Version: 6.037 on 2026-01-25, with 188 votes
    • Previous CPAN version: 6.036 was 2 months, 15 days before
    • Author: RJBS
  9. Google::Ads::GoogleAds::Client - Google Ads API Client Library for Perl
    • Version: v30.0.0 on 2026-01-28, with 20 votes
    • Previous CPAN version: v29.0.1 was 3 months, 12 days before
    • Author: CHEVALIER
  10. IO::Compress - IO Interface to compressed data files/buffers
    • Version: 2.216 on 2026-01-30, with 19 votes
    • Previous CPAN version: 2.215
    • Author: PMQS
  11. MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
    • Version: 2.038000 on 2026-01-29, with 27 votes
    • Previous CPAN version: 2.037000 was 22 days before
    • Author: MICKEY
  12. Net::Server - Extensible Perl internet server
    • Version: 2.016 on 2026-01-28, with 34 votes
    • Previous CPAN version: 2.015 was 5 days before
    • Author: BBB
  13. SPVM - The SPVM Language
    • Version: 0.990124 on 2026-01-31, with 36 votes
    • Previous CPAN version: 0.990123
    • Author: KIMOTO
  14. UV - Perl interface to libuv
    • Version: 2.002 on 2026-01-28, with 14 votes
    • Previous CPAN version: 2.001 was 22 days before
    • Author: PEVANS

Perl-related GitHub organizations

Perl Maven

Most projects are started by a single person in a GitHub repository of that person. Later for various reasons people establish GitHub organizations and move the projects there. Sometimes the organization contains a set of sub-projects related to a central project. (e.g. A web framework and its extensions or database access.) Sometimes it is a collection of projects related to a single topic. (e.g. testing or IDE support.) Sometimes it is just a random collection of project where people band together in the hope that no project will be left behind. (e.g. the CPAN Authors organization.)

Organizations make it easier to have multiple maintainers and thus ensuring continuity of project, but it might also mean that none of the members really feel the urge to continue working on something.

In any case, I tried to collect all the Perl-related GitHub organizations.

Hopefully in ABC order...

  • Beyond grep - It is mostly for ack, a better grep developed by Andy Lester. No public members. 4 repositories.

  • Catalyst - Catalyst is a web-framework. Its runtime and various extensions are maintained in this organization. 10 members and 39 repositories.

  • cpan-authors - A place for CPAN authors to collaborate more easily. 4 members and 9 repositories.

  • davorg cpan - Organisation for maintaining Dave Cross's CPAN modules. No public members and 47 repositories.

  • ExifTool - No public members. 3 repositories.

  • Foswiki - The Foswiki and related projects. 13 members and 649 repositories.

  • gitpan - An archive of CPAN modules - 2 members and 5k+ read-only repositories.

  • Kelp framework - a web development framework. 1 member and 12 repositories.

  • MetaCPAN - The source of the MetaCPAN site - 9 member and 56 rpositories.

  • Mojolicious - Some Perl and many JavaScript projects. 5 members and 29 repositories.

  • Moose - Moose,MooseX-*, Moo, etc. 11 members and 69 repositories.

  • Netdisco - Netdisco and SNMP-Info projects. 10 members and 14 repositories.

  • PadreIDE - Padre, the Perl IDE. 13 members and 102 repositories.

  • Paracamelus - No public members. 2 repositories.

  • Perl - Perl 5 itself, Docker images, etc. 20 members, 8 repositories.

  • Perl Actions - GitHub Actions to be used in workflows. 5 members and 9 repositories.

  • Perl Advent Calendar - including the source of perl.com. 3 members and 8 repositories.

  • Perl Bitcoin - Perl Bitcoin Toolchain Collective. 3 members and 7 repositories.

  • Perl Toolchain Gang - ExtUtils::MakeMaker, Module::Build, etc. 27 members and 41 repositories.

  • Perl Tools Team - source of planetperl , perl-ads etc. No public members. 6 repositories.

  • Perl Dancer - Dancer, Dancer2, many plugins. 30 members and 79 repositories.

  • perltidy - Only for Perl::Tidy. No public members. 1 repository.

  • perl5-dbi - DBI, several DBD::* modules, and some related modules. 7 members and 15 repositories.

  • perl.org - also cpan.org and perldoc.perl.org. 3 members and 7 repositories.

  • Perl5 - DBIx-Class and DBIx-Class-Historic. No public members. 2 repositories.

  • perl5-utils - List::MoreUtils, File::ShareDir etc. 2 members and 22 repositories.

  • Perl-Critic - PPI, Perl::Critic and related. 7 members and 5 repositories.

  • perl-ide - Perl Development Environments. 26 members and 13 repositories.

  • perl-pod - Pod::Simple, Test::Pod. 1 member and 4 repositories.

  • PkgConfig - 1 member 1 repository.

  • plack - psgi-specs, Plack and a few middlewares. 5 members and 7 repositories.

  • RexOps - Rex, Rexify and related projects. 1 member and 46 repositories.

  • Sqitch - Sqitch for Sensible database change management and related projects. No public members. 16 repositories.

  • StrawberryPerl - The Perl distribution for MS Windows. 4 members and 10 repositories.

  • Test-More - Test::Builder, Test::Simple, Test2 etc. - 4 members, 27 repositories.

  • The Enlightened Perl Organisation - Task::Kensho and Task::Kensho::*. 1 member and 1 repository.

  • Thunderhorse Framework - a modern web development framework. No public members. 4 repositories.

  • Webmin - Webmin is a web-based system administration tool for Unix-like servers. - 5 repositories.

Companies

These are bot Perl-specific GitHub organizations, but some of the repositories are in Perl.

  • cPanel - Open Source Software provided by cPanel. 1 member and 22 repositories.

  • DuckDuckGo - The search engine. 19 members and 122 repositories.

  • Fastmail - Open-source software developed at Fastmail. 4 members and 38 repositories.

  • RotherOSS - Otobo (OTRS fork). No public members. 47 repositories.

Then there’s Perl

Perl on Medium

Since my native language isn’t English, the German text follows below.

Lock and unlock hash using Hash::Util

Perl Maven

If you don't like the autovivification or simply would like to make sure the code does not accidentally alter a hash the Hash::Util module is for you.

You can lock_hash and later you can unlock_hash if you'd like to make some changes to it.

In this example you can see 3 different actions commented out. Each one would raise an exception if someone tries to call them on a locked hash. After we unlock the hash we can execute those actions again.

I tried this both in perl 5.40 and 5.42.

examples/locking_hash.pl

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

use Hash::Util qw(lock_hash unlock_hash);
use Data::Dumper qw(Dumper);


my %person = (
    fname => "Foo",
    lname => "Bar",
);
lock_hash(%person);

print Dumper \%person;
print "$person{fname} $person{lname}\n";
say "fname exists ", exists $person{fname};
say "language exists ", exists $person{language};

# $person{fname} = "Peti";     # Modification of a read-only value attempted
# delete $person{lname};       # Attempt to delete readonly key 'lname' from a restricted hash
# $person{language} = "Perl";  # Attempt to access disallowed key 'language' in a restricted hash

unlock_hash(%person);

$person{fname} = "Peti";     # Modification of a read-only value attempted
delete $person{lname};       # Attempt to delete readonly key 'lname' from a restricted hash
$person{language} = "Perl";  # Attempt to access disallowed key 'language' in a restricted hash

print Dumper \%person;

$VAR1 = {
          'lname' => 'Bar',
          'fname' => 'Foo'
        };
Foo Bar
fname exists 1
language exists
$VAR1 = {
          'language' => 'Perl',
          'fname' => 'Peti'
        };

My name is Alex. Over the last years I’ve implemented several versions of the Raku’s documentation format (Synopsys 26 / Raku’s Pod) in Perl and JavaScript.

At an early stage, I shared the idea of creating a lightweight version of Raku’s Pod, with Damian Conway, the original author of the Synopsys 26 Documentation specification (S26). He was supportive of the concept and offered several valuable insights that helped shape the vision of what later became Podlite.

Today, Podlite is a small block-based markup language that is easy to read as plain text, simple to parse, and flexible enough to be used everywhere — in code, notes, technical documents, long-form writing, and even full documentation systems.

This article is an introduction for the Perl community — what Podlite is, how it looks, how you can already use it in Perl via a source filter, and what’s coming next.

The Block Structure of Podlite

One of the core ideas behind Podlite is its consistent block-based structure. Every meaningful element of a document — a heading, a paragraph, a list item, a table, a code block, a callout — is represented as a block. This makes documents both readable for humans and predictable for tools.

Podlite supports three interchangeable block styles: delimited, paragraph, and abbreviated.

Abbreviated blocks (=BLOCK)

This is the most compact form. A block starts with = followed by the block name.

=head1 Installation Guide
=item Perl 5.8 or newer
=para This tool automates the process.
  • ends on the next directive or a blank line
  • best used for simple one-line blocks
  • cannot include configuration options (attributes)

Paragraph blocks (=for BLOCK)

Use this form when you want a multi-line block or need attributes.

=for code :lang<perl>
say "Hello from Podlite!";
  • ends when a blank line appears
  • can include complex content
  • allows attributes such as :lang, :id, :caption, :nested, …

Delimited blocks (=begin BLOCK … =end BLOCK)

The most expressive form. Useful for large sections, nested blocks, or structures that require clarity.

=begin nested :notify<important>
Make sure you have administrator privileges.
=end nested
  • explicit start and end markers
  • perfect for code, lists, tables, notifications, markdown, formulas
  • can contain other blocks, including nested ones

These block styles differ in syntax convenience, but all produce the same internal structure.

diagram here showing the three block styles and how they map to the same internal structure

Regardless of which syntax you choose:

  • all three forms represent the same block type
  • attributes apply the same way (:lang, :caption, :id, …)
  • tools and renderers treat them uniformly
  • nested blocks work identically
  • you can freely mix styles inside a document

Example: Comparing POD and Podlite

Let’s see how the same document looks in traditional POD versus Podlite:

POD vs Podlite

Each block has clear boundaries, so you don’t need blank lines between them. This makes your documentation more compact and easier to read. This is one of the reasons Podlite remains compact yet powerful: the syntax stays flexible, while the underlying document model stays clean and consistent.

This Podlite example rendered as on the following screen:

Podlite example

Inside the Podlite Specification 1.0

One important point about Podlite is that it is first and foremost a specification. It does not belong to any particular programming language, platform, or tooling ecosystem. The specification defines the document model, syntax rules, and semantics.

From the Podlite 1.0 specification, notable features include:

  • headings (=head1, =head2, …)
  • lists and definition lists, and including task lists
  • tables (simple and advanced)
  • CSV-backed tables
  • callouts / notifications (=nested :notify<tip|warning|important|note|caution>)
  • table of contents (=toc)
  • includes (=include)
  • embedded data (=data)
  • pictures (=picture and inline P<>)
  • formulas (=formula and inline F<>)
  • user defined blocks and markup codes
  • Markdown integration

The =markdown block is part of the standard block set defined by the Podlite Specification 1.0. This means Markdown is not an add-on or optional plugin — it is a fully integrated, first-class component of the language.

Markdown content becomes part of Podlite’s unified document structure, and its headings merge naturally with Podlite headings inside the TOC and document outline.

Below is a screenshot showing how Markdown inside Perl is rendered in the in-development VS Code extension, demonstrating both the block structure and live preview:

Podlite source, including =markdown block

Using Podlite in Perl via the source filter

To make Podlite directly usable in Perl code, there is a module on CPAN: Podlite — Use Podlite markup language in Perl programs

A minimal example could look like this:

use Podlite; # enable Podlite blocks inside Perl

=head1 Quick Example
=begin markdown
Podlite can live inside your Perl programs.
=end markdown
print "Podlite active\n";

Roadmap: what’s next for Podlite

Podlite continues to grow, and the Specification 1.0 is only the beginning. Several areas are already in active development, and more will evolve with community feedback.

Some of the things currently planned or in progress:

  • CLI tools
    • command-line utilities for converting Podlite to HTML, PDF, man pages, etc.
    • improve pipelines for building documentation sites from Podlite sources
  • VS Code integration
  • Ecosystem growth
    • develop comprehensive documentation and tutorials
    • community-driven block types and conventions

Try Podlite and share feedback

If this resonates with you, I’d be very happy to hear from you:

  • ideas for useful block types
  • suggestions for tools or integrations
  • feedback on the syntax and specification

https://github.com/podlite/podlite-specs/discussions

Even small contributions — a comment, a GitHub star, or trying an early tool — help shape the future of the specification and encourage further development.

Useful links:

Thanks for reading, Alex

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.03 on 2026-01-19, with 56 votes
    • Previous CPAN version: 10.02 was 10 days before
    • Author: UTASHIRO
  2. Beam::Wire - Lightweight Dependency Injection Container
    • Version: 1.028 on 2026-01-21, with 19 votes
    • Previous CPAN version: 1.027 was 1 month, 15 days before
    • Author: PREACTION
  3. CPAN::Meta - the distribution metadata for a CPAN dist
    • Version: 2.150011 on 2026-01-22, with 39 votes
    • Previous CPAN version: 2.150010 was 9 years, 5 months, 4 days before
    • Author: RJBS
  4. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260120.004 on 2026-01-20, with 25 votes
    • Previous CPAN version: 20260120.002
    • Author: BRIANDFOY
  5. DateTime::Format::Natural - Parse informal natural language date/time strings
    • Version: 1.24 on 2026-01-18, with 19 votes
    • Previous CPAN version: 1.23_03 was 5 days before
    • Author: SCHUBIGER
  6. EV - perl interface to libev, a high performance full-featured event loop
    • Version: 4.37 on 2026-01-22, with 50 votes
    • Previous CPAN version: 4.36 was 4 months, 2 days before
    • Author: MLEHMANN
  7. Git::Repository - Perl interface to Git repositories
    • Version: 1.326 on 2026-01-18, with 27 votes
    • Previous CPAN version: 1.325 was 4 years, 7 months, 17 days before
    • Author: BOOK
  8. IO::Async - Asynchronous event-driven programming
    • Version: 0.805 on 2026-01-19, with 80 votes
    • Previous CPAN version: 0.804 was 8 months, 26 days before
    • Author: PEVANS
  9. Mac::PropertyList - work with Mac plists at a low level
    • Version: 1.606 on 2026-01-20, with 13 votes
    • Previous CPAN version: 1.605 was 5 months, 11 days before
    • Author: BRIANDFOY
  10. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20260119 on 2026-01-19, with 44 votes
    • Previous CPAN version: 5.20251220 was 29 days before
    • Author: BINGOS
  11. Net::Server - Extensible Perl internet server
    • Version: 2.015 on 2026-01-22, with 33 votes
    • Previous CPAN version: 2.014 was 2 years, 10 months, 7 days before
    • Author: BBB
  12. Net::SSH::Perl - Perl client Interface to SSH
    • Version: 2.144 on 2026-01-23, with 20 votes
    • Previous CPAN version: 2.144 was 8 days before
    • Author: BDFOY
  13. Release::Checklist - A QA checklist for CPAN releases
    • Version: 0.19 on 2026-01-25, with 16 votes
    • Previous CPAN version: 0.18 was 1 month, 15 days before
    • Author: HMBRAND
  14. Spreadsheet::Read - Meta-Wrapper for reading spreadsheet data
    • Version: 0.95 on 2026-01-25, with 31 votes
    • Previous CPAN version: 0.94 was 1 month, 15 days before
    • Author: HMBRAND
  15. SPVM - The SPVM Language
    • Version: 0.990117 on 2026-01-24, with 36 votes
    • Previous CPAN version: 0.990116
    • Author: KIMOTO
  16. utf8::all - turn on Unicode - all of it
    • Version: 0.026 on 2026-01-18, with 31 votes
    • Previous CPAN version: 0.025 was 1 day before
    • Author: HAYOBAAN

See OSDC Perl

  • 00:00 Working with Peter Nilsson

  • 00:01 Find a module to add GitHub Action to. go to CPAN::Digger recent

  • 00:10 Found Tree-STR

  • 01:20 Bug in CPAN Digger that shows a GitHub link even if it is broken.

  • 01:30 Search for the module name on GitHub.

  • 02:25 Verify that the name of the module author is the owner of the GitHub repository.

  • 03:25 Edit the Makefile.PL.

  • 04:05 Edit the file, fork the repository.

  • 05:40 Send the Pull-Request.

  • 06:30 Back to CPAN Digger recent to find a module without GitHub Actions.

  • 07:20 Add file / Fork repository gives us "unexpected error".

  • 07:45 Direct fork works.

  • 08:00 Create the .github/workflows/ci.yml file.

  • 09:00 Example CI yaml file copy it and edit it.

  • 14:25 Look at a GitLab CI file for a few seconds.

  • 14:58 Commit - change the branch and add a description!

  • 17:31 Check if the GitHub Action works properly.

  • 18:17 There is a warning while the tests are running.

  • 21:20 Opening an issue.

  • 21:48 Opening the PR (on the wrong repository).

  • 22:30 Linking to output of a CI?

  • 23:40 Looking at the file to see the source of the warning.

  • 25:25 Assigning an issue? In an open source project?

  • 27:15 Edit the already created issue.

  • 28:30 USe the Preview!

  • 29:20 Sending the Pull-Request to the project owner.

  • 31:25 Switching to Jonathan

  • 33:10 CPAN Digger recent

  • 34:00 Net-SSH-Perl of BDFOY - Testing a networking module is hard and Jonathan is using Windows.

  • 35:13 Frequency of update of CPAN Digger.

  • 36:00 Looking at our notes to find the GitHub account of the module author LNATION.

  • 38:10 Look at the modules of LNATION on MetaCPAN

  • 38:47 Found JSON::Lines

  • 39:42 Install the dependencies, run the tests, generate test coverage.

  • 40:32 Cygwin?

  • 42:45 Add Github Action copying it from the previous PR.

  • 43:54 META.yml should not be committed as it is a generated file.

  • 48:25 I am looking for sponsors!

  • 48:50 Create a branch that reflects what we do.

  • 51:38 commit the changes

  • 53:10 Fork the project on GitHub and setup git remote locally.

  • 55:05 git push -u fork add-ci

  • 57:44 Sending the Pull-Request.

  • 59:10 The 7 dwarfs and Snowwhite. My hope is to have a 100 people sending these PRs.

  • 1:01:30 Feedback.

  • 1:02:10 Did you think this was useful?

  • 1:02:55 Would you be willing to tell people you know that you did this and you will do it again?

  • 1:03:17 You can put this on your resume. It means you know how to do it.

  • 1:04:16 ... and Zoom suddenly closed the recording...

Announcing the Perl Toolchain Summit 2026!

The organizers have been working behind the scenes since last September, and today I’m happy to announce that the 16th Perl Toolchain Summit will be held in Vienna, Austria, from Thursday April 23rd till Sunday April 26th, 2026.

This post is brought to you by Simplelists, a group email and mailing list service provider, and a recurring sponsor of the Perl Toolchain Summit.

Simplelists logo


Started in 2008 as the Perl QA Hackathon in Oslo, the Perl Toolchain Summit is an annual event that brings together the key developers working on the Perl toolchain. Each year (except for 2020-2022), the event moves from country to country all over Europe, organised by local teams of volunteers. The surplus money from previous summits helps fund the next one.

Since 2023, the organizing team is formally split between a “global” team and a “local” team (although this setup has been informally used before).

The global team is made up of veteran PTS organizers, who deal with invitations, finding sponsors, paying bills and communications. They are Laurent Boivin (ELBEHO), Philippe Bruhat (BOOK), Thibault Duponchelle (CONTRA), Tina Müller (TINITA) and Breno de Oliveira (GARU), supported by Les Mongueurs de Perl’s bank account.

The local team members for this year have organized several events in Vienna (including the Perl QA Hackathon 2010!) and deal with finding the venue, the hotel, the catering and welcoming our attendees in Vienna in April. They are Alexander Hartmaier (ABRAXXA), Thomas Klausner (DOMM), MaroŔ KollÔr (MAROS), Michael Kröll and Helmut Wollmersdorfer (WOLLMERS).

The developers who maintain CPAN and associated tools and services are all volunteers, scattered across the globe. This event is the one time in the year when they can get together.

The summit provides dedicated time to work on the critical systems and tools, with all the right people in the same room. The attendees hammer out solutions to thorny problems and discuss new ideas to keep the toolchain moving forward. This year, about 40 people have been invited, with 35 participants expected to join us in Vienna.

If you want to find out more about the work being done at the Toolchain Summit, and hear the teams and people involved, you can listen to several episodes of The Underbar podcast, which were recorded during the 2025 edition in Leipzig, Germany:

Given the important nature of the attendees’ work and their volunteer status, we try to pay for most expenses (travel, lodging, food, etc.) through sponsorship. If you’re interested in helping sponsor the summit, please get in touch with the global team at pts2026@perltoolchainsummit.org.

Simplelists has been sponsoring the Perl Toolchain Summit for several years now. We are very grateful for their continued support.

Simplelists is proud to sponsor the 2026 Perl Toolchain Summit, as Perl forms the core of our technology stack. We are grateful that we can rely on the robust and comprehensive Perl ecosystem, from the core of Perl itself to a whole myriad of CPAN modules. We are glad that the PTS continues its unsung work, ensuring that Simplelists can continue to rely on these many tools.

Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications in Perl with Google Cloud Run.