Shortcuts: s show h hide n next p prev

Then here is a reminder that you will want to update your account to use a different email address. (There are about 130 of you that get to jump through this hoop now.)

If you need help, email contact@blogs.perl.org as per usual.

RMG: note version.pm CUSTOMIZED special status

My Journey with Devel::ptkdb - Origins

blogs.perl.org

This post is the first in a series that will follow my re-development of the Devel::ptkdb debugger. This post explains the beginnings of my involvement with the Perl Tk debugger.

PWC 373 Task 2: Let's Dance to List Division

dev.to #perl

The task title reminded me of the song Let's Dance to Joy Division. Oddly applicable lyrics for a blog about programming: "But I worked something out last night that changed this little boy's brain, a small piece of advice that took 22 years in the make, and I will break it for you now. Please learn from my mistakes." And who doesn't love a wombat?

Task Description

You are given a list and a non-negative integer, $n. Write a script to divide the given list into $n equal parts. Return -1 if $n is more than the size of the list.

Example 1
Input: @list = ( 1,2,3,4,5), $n = 2
Output: ((1,2,3), (4,5))
  • 5 / 2 = 2 remainder 1. The extra element goes into the first chunk.

Example 2

Input: @list = (1,2,3,4,5,6), $n = 3
Output: ((1,2), (3,4), (5,6))
  • 6 / 3 = 2 remainder 0.

Example 3

Input: @list = (1,2,3), $n = 2
Output: ((1,2), (3))

Example 4

Input: @list = (1,2,3,4,5,6,7,8,9,10), $n = 5
Output: ((1,2), (3,4), (5,6), (7,8), (9,10))

Example 5

Input: @list = (1,2,3), $n = 4
Output: -1

Example 6

Input: @list = (72,57,89,55,36,84,10,95,99,35), $n = 7;
Output: ((72,57), (89,55), (36,84), (10), (95), (99), (35))

Elaboration

There's some simple modulo division here, and then a decision about what to do if it doesn't divide evenly into $n chunks. We could put the remainder into a chunk of its own, ignore the remainder, or we could distribute the leftovers in some way that feels balanced -- here, the specification implies that the bigger divisions should go at the front of the list.

Handling an invalid input (where $n is too big) by returning -1 instead of an array is a code smell. Having a function that returns different types of things is awkward to handle and error-prone. It would be more consistent to either throw an exception, or return an out-of-range value of the same type, such as an empty array or a null reference. But that wanker Kevin with his six months of Javascript experience got promoted to project manager for some reason <cough/>nepotism<cough> and that's the requirement we have.

This task has six examples, and usually we're given five. Is there some significance to this? Example 6 doesn't seem to add any new information beyond what we've already been given. But then we notice that the numbers could be ASCII characters, spelling "H9Y7$T?_c#". I'm pretty sure this is Kevin's password. Watch your back, Kevin.

To the CodeMobile, Robin!

sub listDivision($list, $n)
{
    my $size = @$list;
    return -1 if $n > $size;

    my $chunk = floor($size / $n);
    my $extra = $size % $n;
    my @answer;

    while ( $extra-- ) { push @answer, [ splice(@$list, 0, $chunk + 1) ]; }
    while ( @$list   ) { push @answer, [ splice(@$list, 0, $chunk    ) ]; }
    return \@answer;
}

The input parameters are an array and a number, which forces us to confront the way that Perl passes arguments as a flat list. Here, I've chosen to pass an array reference for $list instead of an array, which accomplishes two things: it removes the flat list problem to make it obvious which parameter is $n, and it's more efficient than passing a copy of the array. I could have also passed the parameters in the other order, but "project manager" Kevin said according to ChatGPT and Claude it had to be in this order, so yeah, that's that then.

Time to be serious. We dispense with the special case of returning -1 (more on that later). Then we calculate the quantities involved, and set up an array for producing the answer, initially empty.

The answer has two segments: a head part where there might be one extra element, and the tail part where the segments are of the calculated chunk size. One while loop ticks off the extra-sized chunks, and the second while loop completes the division.

To grab a group of contiguous elements from a list, the splice function seems like the obvious thing to do. Each splice is surrounded with [] so that the chunks are treated as array references. An alternative would have been to take an array slice, but that would introduce index variables for the range being sliced, which looks and feels more complicated and error-prone.

splice reduces the size of the list every time it's called, so the second while loop can use the size of $list as its condition. However, we are destroying $list as we go, so the calling function needs to be aware that the array it passed in is no longer valid. If it were important to keep the original list, a copy would need to be made either from the caller, or near the beginning of listDivision().

Let's think a moment about how to use this function. When it's called it could return either an array of arrays (references actually), or it could return a scalar -1. Here's how I wanted to write the script to use this function, using -n as a command-line option to get that parameter:

use GetOpt::Long;
my $N = 1;
GetOptions("n:i" => \$N);
my $div = listDivision([@ARGV], $N);
say showAofA($div);

where showAofA() is a function that formats the array of arrays into a parenthesized list of comma-separated lists, as in the examples.

However, $div isn't always a reference; sometimes it's a scalar -1. That throws up an ugly error about trying to use a scalar value as a reference. The way to check what's behind a variable in Perl is to use the ref function. It will give a string identifying the variable type, or, for a scalar, it will give an empty string. In perl, an empty string counts as false. So, to satisfy the requirement, the script needs to test whether ref($div) is empty:

say ( ref($div) ? showAofA($div) : $div );

What I probably should have done is change listDivision so that it consistently returns an array reference, but for the invalid case, throws an error. Variations on try/catch have been available as modules in Perl for decades, but it finally (see what I did there?) became official in version 5.38. That simplifies the usage of the function (if you consider try/catch simpler, which some consider a debatable topic).

try          { say showAofA( listDivision([@ARGV], $N) ); }
catch ( $e ) { say "-1" }

To make the function throw an exception, we only need to change the early return from the function into a die:

sub listDivision($list, $n)
{
    my $size = @$list;
    die "N out of range (must be <= $size)" if $n > $size;
    # [ ... ]

That's cleaner, but it slightly complicates the unit testing, because now we have to test for exceptions. The incantation is:

sub runTest
{
    use Test2::V0;
    use Test2::Tools::Exception;
    # [Test cases that should work
    is( listDivision([1,2,3], 1), [[1,2,3]], "One chunk");
    # [ ... ]
    # Test things that throw exceptions
    like ( dies { listDivision( [1,2,3], 4) }, qr/out of range/);

The dies function returns the exception string that results from trying to execute a code block, and like does a pattern match against the expected exception.

And finally, to tidy up a loose end, here's the showAofA() function.

sub showAofA($ref)
{
    return '('. join(',', map { '('.join(',', $_->@*).')' } $ref->@*) .')';
}

Let's take a bunch of punctuation out of that so that we can see the structure:

return ( join( map { join } ) ref )

$ref is a reference to an array of references; hence, $ref->@* is de-referencing it to yield a list of array references.

Each of those array references is then transformed by map. Inside the map {} block, $_ refers to one of the inner arrays, so we de-reference that ($_->@*) to get a list of numbers, which we will join into a comma-separated string. Wrap that with a pair of parentheses, and out of the map comes the inner lists formatted as needed.

Now each of the inner lists is a string. The outer join inserts commas to make it a list of lists, and finally we wrap the whole thing in parentheses to complete the string.

Update .mailmap for Eric Herman

Perl commits on GitHub
Update .mailmap for Eric Herman

I am stuck in a Perl-Script. Regex is verified, but Copy.pm complains: Use of uninitialized value $to in -d at /opt/homebrew/opt/perl/lib/perl5/5.42/File/Copy.pm line 255

What this script is doing, you will see in the comments. I tested also with debugger, and the regex is matching.

Here my attempt:

#!/opt/homebrew/bin/perl

# change Filenames from: Free CCNA | Network Devices | Day 1 | CCNA 200-301 Complete Course [H8W9oMNSuwo]
# to:
# Free CCNA _ Day 01 _ Network Devices _ CCNA 200-301 Complete Course-H8W9oMNSuwo
# run it in shell like follows: 
# ./rename_file03.pl .
# the point is the actual folder to start. Or an other path
# to the folder to start with ...
# change from:
# Free CCNA _ Day 33 Lab _ Configuring IPv6 (Part 3) _ CCNA 200-301 Complete Course-WSBEVFANMmc.mp4
# Free CCNA | Configuring IPv6 (Part 3) | Day 33 Lab | CCNA 200-301 Complete Course [WSBEVFANMmc].webm
# 1 step: remove `| (Day \d+ (Lab)?)` and capture it in `$day` to insert it later
# 2 step: capture extension: `(\.\w+)$`
# 2 step: replace all ` | ` with ` _ ` 
# 3 step: remove `\[([^]+\)]` and capture it in $yt
# 4 step: replace `Free CCNA ` with `\&$day`
# 5 step: aad to the filename `$yt$ext`
# (Free CCNA) | ([^|]+) | (Day \d+( Lab)?) | ([^]]+) (\[[^]\]+)(\..+)

use warnings;
use strict;
use feature 'say';
use File::Find;
use File::Copy;
# use String::Util qw(trim);

my @main_folders = @ARGV; # for example ./command + path/to/folder : ./rename_file.pl foo01/
# my $path = `pwd`; # for example foo01
# chomp($path); # now without \n
my $working_folder;

foreach my $main_folder (@main_folders) {

    $main_folder =~ s,/+$,,;    # remove trailing slashes
    $main_folder =~ s,^\./,,;    # remove ./ at the beginning
    $working_folder = $main_folder ;

    find( \&process, $working_folder );
    }

sub process{
    my $file = $File::Find::name;
 
    return unless /^Free /;
    # return unless $file =~ /^Free CCNA \_/;
    my $new_file_name;
    # return unless $file =~ /^./;
#                   $leading     $title             $day     $course                       $yt         $ext
#                   Free CCNA | Network Devices | Day 1 | CCNA 200-301 Complete Course [H8W9oMNSuwo].txt
#                   Free CCNA | Configuring IPv6 (Part 1) | Day 31 Lab | CCNA 200-301 Complete Course [BdsIahtrWIA].txt
#                   Free CCNA | Configuring IPv6 (Part 2) | Day 32 Lab | CCNA 200-301 Complete Course [Zfhpd7dl6QI].txt
#                   Free CCNA | Configuring OSPF (3) | Day 28 Lab | CCNA 200-301 Complete Course [Goekjm3bK5o].txt
#                   Free CCNA | Configuring Static Routes | Day 11 Lab 1 | CCNA 200-301 Complete Course [XHxOtIav2k8].txt
#                   Free CCNA | Configuring STP (PVST+) | Day 21 Lab | CCNA 200-301 Complete Course [5rpaeJNig2o].txt
    if ($file =~ m/(Free CCNA) | ([\w\s()+&,\/-]+?) | (Day \d+(?: [\w+\s()]+)?) | ([\w\s-]+?) \[([^\]]+)\](\..+)/) {

    my $leading = $1;
    my $title = $2;
    my $day = $3;
    my $course = $4;
    my $yt = $5;
    my $extension = $6;

    (my $day2 = $day) =~ s/(\d+)/sprintf('%02d', $1)/ge;
    $new_file_name = $working_folder . "/" . "$leading _ $day2 _ $title _ $course-$yt$extension";
    say "Here the files to rename:\n";
    say "Old file name\n$file\n";
    say "New file name\n$new_file_name\n";
    } else {
      say "file name not found"
    }

    if ( -e $new_file_name ) {
                    warn "$new_file_name already exists; skipping $file\n";
                    next;
                }
    move ( $file, $new_file_name )
                  or die "Can't rename $file to $new_file_name: $!\n";
                # continue;
}
expand the dual-life synchronisation section

Co-authored-by: Eric Herman <eric@freesa.org>

These both work:

echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne 'print "$_\n" for /(\d)([a-z])/gs'
echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne '@m = /(\d)([a-z])/gs; print for @m'

But this doesn't:

echo 'jg984tj89g02jg09248gj4209jg49' | perl -0lne 'print "$1-->$2\n" for /(\d)([a-z])/gs'

(Basically last command outputs the capture groups over and over again for the last match, not iterating over each match)

Anyone able to explain why?

It would have been nice to control formatting with the last command, it could have been a quick, simple and convenient way of preparing / structuring the data for any next command.


Note: This method is designed for Linux systems where LD_PRELOAD is available.
AddressSanitizer (ASan) is a powerful tool for detecting memory corruption in C/C++ code. When developing Perl XS modules, you can integrate ASan support directly into your Makefile.PL to make debugging seamless.

Add the 'asan-on-linux' Option



First, use GetOptions to provide a dedicated flag for ASan. This allows users to enable memory sanitization explicitly. We also set up a temporary directory to store ASan's detailed log files.

use Getopt::Long;
use File::Path 'mkpath';

GetOptions('asan-on-linux' => \my $asan_on_linux);

my @ccflags;
my @ldflags;
my $asan_logs_dir = ".tmp/asan_logs";

if ($asan_on_linux) {
    push @ccflags, "-fsanitize=address", "-fno-omit-frame-pointer";
    push @ldflags, "-fsanitize=address";
    
    mkpath $asan_logs_dir unless -d $asan_logs_dir;
}

Automate Library Preloading via Makefile Macros



Since the standard perl binary isn't typically compiled with ASan, we must ensure libasan.so is correctly preloaded before the interpreter starts. By using the macro parameter in WriteMakefile, we can automate this process for make test.

use Config;

WriteMakefile(
    NAME              => 'My::Module',
    CCFLAGS           => "$Config{ccflags} " . join(' ', @ccflags),
    LDDLFLAGS         => "$Config{lddlflags} " . join(' ', @ldflags),
    # ...
    macro => {
        $asan_on_linux ? (
            'override FULLPERL' => qq|LD_PRELOAD=\$\$($Config{cc} -print-file-name=libasan.so) ASAN_OPTIONS="log_path=$asan_logs_dir/asan.log:exitcode=0" $^X|
        ) : (),
    },
);

How to Handle Memory Issues



When ASan is enabled, the behavior depends on the type of memory issue:


  • Memory Corruption: Issues like buffer overflows or use-after-free will cause a Segmentation Fault (Segfault) immediately. When this happens, you must fix the code until all tests pass without crashing.
  • Memory Leaks: Unlike corruption, memory leaks do not cause a crash. To find them, you must check the logs after running your tests.


ASan generates a separate log file for each process. To efficiently find both corruption reports and leaks related to your specific module, use the following Perl one-liner (Replace My::Module with your module's name):

perl -00 -ne 'print "--- File: $ARGV ---\n$_\n" if /My::Module/' .tmp/asan_logs/* > .tmp/asan_summary.log


This command uses Perl's "paragraph mode" (-00) to extract the entire stack trace, allowing you to see exactly where the issue (crash or leak) was triggered in your native code.

Appendix: Platform Compatibility

macOS (Untested Hint)



On macOS, you might try DYLD_INSERT_LIBRARIES instead of LD_PRELOAD. However, System Integrity Protection (SIP) often prevents preloading into system binaries like /usr/bin/perl. You would likely need to use a perl installed via perlbrew or plenv.

Windows (Not Supported)



This mechanism is not applicable to Windows. Windows lacks LD_PRELOAD, and memory sanitization requires a fundamentally different configuration, typically involving a specially compiled perl interpreter.


Author: Yuki Kimoto

Introducing Time::Str

blogs.perl.org

Time::Str is a Perl module for parsing and formatting date/time strings across 20+ standard formats. It has an optional C/XS backend, nanosecond precision, and rejects input it cannot parse unambiguously rather than guessing.

use Time::Str qw(str2time str2date time2str);

my $time = str2time('2024-12-24T15:30:45Z');
# 1735052445

my $str = time2str($time, format => 'RFC2822', offset => 60);
# 'Tue, 24 Dec 2024 16:30:45 +0100'

Standards Compliance

Each format is implemented according to its specification: RFC 3339, RFC 2822, RFC 2616, ISO 8601 (calendar dates), ISO 9075, ITU-T X.680 (ASN.1), RFC 5545.

RFC3339      2024-12-24T15:30:45+01:00
RFC2822      Tue, 24 Dec 2024 15:30:45 +0100
RFC2616      Tue, 24 Dec 2024 15:30:45 GMT
ISO8601      20241224T153045.500+0100
ISO9075      2024-12-24 15:30:45 +01:00
ASN1GT       20241224153045Z
CLF          24/Dec/2024:15:30:45 +0100
RFC5545      20241224T153045Z
ECMAScript   Tue Dec 24 2024 15:30:45 GMT+0100

RFC 2822 allows an optional day name and a comment; the regex accepts both. ISO 8601 calendar dates are supported in both basic and extended formats with optional fractional parts on the least significant component. RFC 2616 requires three date formats (IMF-fixdate, RFC 850, and asctime); all three are accepted.

Optional fields are optional. Constrained fields are validated. Day names, when present, are verified against the actual date.

No Guessing

If Time::Str cannot parse the input unambiguously, it croaks rather than returning a wrong answer.

The 01/02/2024 Problem

Is 01/02/2024 January 2nd or February 1st? It depends on who you ask:

  • Date::Parse assumes American (MM/DD). Documents this as a known bug with no workaround.
  • Date::Parse::Modern assumes European (DD/MM). Swaps day and month if the month exceeds 12.
  • Time::ParseDate assumes American by default. A UK option switches to European. Applies heuristics when values exceed 12.

Time::Str requires numeric dates in year-month-day order. Ambiguous formats are rejected. When the month is written as a name or Roman numeral, the order is flexible because the month is unambiguous:

str2date('2024-12-24',     format => 'DateTime');  # Y-M-D
str2date('24 Dec 2024',    format => 'DateTime');  # named month
str2date('Dec 24th, 2024', format => 'DateTime');  # named month
str2date('24.XII.2024',    format => 'DateTime');  # Roman numeral

str2date('12-24-2024',     format => 'DateTime');  # M-D-Y rejected
str2date('24-12-2024',     format => 'DateTime');  # D-M-Y rejected

Two-Digit Years

01/02/03: is that 2003, 1903, or 2001? Existing modules apply different heuristics, and some produce results that depend on today's date. Time::Str's DateTime parser requires a four-digit year. Formats that inherently use two-digit years (like ASN.1 UTCTime) provide a configurable pivot_year parameter with a documented default.

Timezone Abbreviations

IST could be India Standard Time (+05:30), Israel Standard Time (+02:00), or Irish Standard Time (+01:00).

Time::Str captures abbreviations in tz_abbrev without resolving them. str2time requires a UTC designator or numeric offset to produce a timestamp:

my %d = str2date('24 Dec 2024 15:30:45 IST', format => 'RFC2822');
# tz_abbrev => 'IST' -- you decide what it means

str2time('24 Dec 2024 15:30:45 IST', format => 'RFC2822');
# croaks: "Unable to convert: timestamp string without a UTC 
#          designator or numeric offset"

The DateTime Format

The DateTime format is a permissive parser for real-world dates that does not use heuristics. It accepts 12-hour clocks, ordinal suffixes, day names, Roman numeral months, and RFC 9557 timezone annotations:

str2date('Monday, 24th December 2024 at 3:30 PM UTC+01:00',
       format => 'DateTime');
# (year      => 2024, 
#  month     => 12, 
#  day       => 24, 
#  hour      => 15,   
#  minute    => 30,
#  tz_utc    => 'UTC', 
#  tz_offset => 60)

str2date('2024-12-24T15:30:45+01:00[Europe/Stockholm]',
       format => 'DateTime');
# ..., tz_offset => 60, tz_annotation => '[Europe/Stockholm]'

Every accepted date can be parsed deterministically. Ordinal suffixes must match the day number (24th is valid, 24st is rejected). Day names must match the actual date.

Optional C/XS

Time::Str has two backends. The XS backend (C99) is loaded when a compiler is available; otherwise it falls back to Pure Perl. The TIME_STR_PP environment variable forces the Pure Perl path.

say Time::Str::IMPLEMENTATION;  # "XS" or "PP"

Both backends share the same precompiled regexps from Time::Str::Regexp and produce identical results. The C backend implements token extraction and the time2str formatting engine natively.

Benchmarks

str2time: Parsing Performance

Parsing '2012-12-24T12:30:45.123456789+01:00':

                    Rate DT8601 DT3339 D::Parse T::Str T::Moment
DT::F::ISO8601   20935/s     --   -42%     -81%   -98%     -100%
DT::F::RFC3339   36127/s    73%     --     -68%   -97%      -99%
D::Parse        112320/s   437%   211%       --   -90%      -98%
T::Str         1093307/s  5122%  2926%     873%     --      -80%
Time::Moment   5543754/s 26381% 15245%    4836%   407%        --

With XS, str2time is ~10x faster than Date::Parse and ~30x faster than DateTime::Format::RFC3339. My other module Time::Moment is faster, but it's a purpose-built C library for a single format. Time::Str handles 20+ formats at over 1M parses/s.

Across Time::Str's own formats, named-format parsers (RFC3339, RFC4287, W3C) run at ~1M/s, while the permissive DateTime parser (which handles the full grammar) runs at ~500K/s:

             Rate  DateTime   W3C RFC3339 RFC4287
DateTime  503643/s       --  -50%    -52%    -52%
W3C      1005176/s     100%   --     -5%     -5%
RFC3339  1054837/s     109%    5%      --     -0%
RFC4287  1060112/s     110%    5%      1%      --

time2str: Formatting Performance

time2str is implemented in C with its own format-spec interpreter, independent of strftime and locale. RFC 3339 formatting runs at ~2x the speed of scalar gmtime:

                 Rate T::Moment    gmtime   RFC2822   RFC3339
T::Moment   2161089/s        --      -29%      -61%      -68%
gmtime      3060278/s       42%        --      -44%      -54%
RFC2822     5477189/s      153%       79%        --      -18%
RFC3339     6719250/s      211%      120%       23%        --

Light on Dependencies

Requires Perl 5.10.1 or later. Runtime dependencies are Carp and Exporter, both core modules. The XS backend needs a C99 compiler at build time. Without a compiler, the Pure Perl fallback has zero non-core dependencies.

Time::HiRes

str2time returns a floating-point Unix timestamp, the same representation Time::HiRes::time() uses. Fractional seconds are preserved up to nanosecond resolution:

use Time::HiRes qw(time);
use Time::Str   qw(str2time time2str);

# Round-trip a high-resolution timestamp
my $now  = time;             # e.g., 1735052445.123456
my $str  = time2str($now);   # '2024-12-24T15:30:45.123456Z'
my $back = str2time($str);   # 1735052445.123456

# Full nanosecond control with the nanosecond parameter
my ($sec, $us) = Time::HiRes::gettimeofday();
my $str = time2str($sec, nanosecond => $us * 1000, precision => 6);

Parsing truncates; formatting rounds. The nanosecond parameter bypasses rounding for exact output.

DateTime and Time::Moment

str2date returns parsed components that maps directly to Time::Moment and DateTime constructors:

use Time::Str qw(str2date);
use DateTime;
use Time::Moment;

my %d = str2date('2024-12-24T15:30:45.500+01:00');

# Feed directly into Time::Moment
my $tm = Time::Moment->new(
  year       => $d{year},
  month      => $d{month},
  day        => $d{day},
  hour       => $d{hour},
  minute     => $d{minute},
  second     => $d{second},
  nanosecond => $d{nanosecond},
  offset     => $d{tz_offset},
);

# Feed directly into DateTime
my $dt = DateTime->new(
  year       => $d{year},
  month      => $d{month},
  day        => $d{day},
  hour       => $d{hour},
  minute     => $d{minute},
  second     => $d{second},
  nanosecond => $d{nanosecond},
  time_zone  =>
    DateTime::TimeZone->offset_as_string($d{tz_offset} * 60)
);

This decouples parsing from representation. Time::Moment's constructor maps 1:1 with str2date's output: offset takes minutes and nanosecond takes the same integer range.

Tools for Custom Parsers

Time::Str also exposes its building blocks for writing custom parsers.

Time::Str::Regexp

Each format's precompiled regex is individually exportable, with named captures:

use Time::Str::Regexp qw($RFC3339_Rx $RFC2822_Rx $DateTime_Rx);

if ($line =~ $RFC3339_Rx) {
  my $year   = $+{year};
  my $month  = $+{month};
  my $offset = $+{tz_offset};
  # ...
}

All regexes are anchored and use consistent named captures: year, month, day, hour, minute, second, fraction, tz_offset, tz_utc, tz_abbrev, tz_annotation, day_name, meridiem.

Time::Str::Token

Token parsers convert the raw captured strings into semantic values:

use Time::Str::Token qw(parse_month parse_day parse_tz_offset);

parse_month('Dec');        # 12
parse_month('XII');        # 12
parse_month('December');   # 12

parse_day('24th');         # 24
parse_day('1st');          # 1

parse_tz_offset('+05:30'); # 330 (minutes)
parse_tz_offset('0530');   # 330

Time::Str::Calendar

Calendar utilities for validation and conversion:

use Time::Str::Calendar qw( leap_year 
                            valid_ymd
                            ymd_to_dow );

leap_year(2024);            # true
valid_ymd(2024, 2, 29);     # true
valid_ymd(2023, 2, 29);     # false
ymd_to_dow(2024, 12, 24);   # 2 (Tuesday; 1=Mon, 7=Sun)

These three modules can be combined to build parsers for other date formats, using the same validation and calendar logic as the built-in formats.

What's Next: Native C Parsers

Currently, the XS backend uses Perl's regex engine for the initial string match, then switches to C for token extraction, validation, and epoch calculation. The next step is moving the parsers themselves into native C, eliminating the regex overhead entirely and closing the gap with Time::Moment's parsing speed.


Time::Str is available on CPAN and GitHub.

cpanm Time::Str

Revise the description of the rand() function

The wording has not disuaded people from using it for security-related
purposes, so the description needs to be rewritten.

The word "cryptographic" suggests cryptography, and the wording should
spell out examples of security-related applications that it should not
be used for.

It should also emphasize that the output of it is predictable and that
systems which rely on it are easily broken.

This is not some theoretical hand-waving exercise.

This week in PSC (224) | 2026-05-11

blogs.perl.org

All three of us attended further final release preparation. Issue triage continued; a number of small issues came in late, and we merged some of them. We also reverted a late small fix that we had merged recently which turned out to cause problems. Overall we once again left the meeting without open release blockers.

[P5P posting of this summary]

Weekly Challenge: Joining and splitting lists

dev.to #perl

Weekly Challenge 373

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Equal List

Task

You are given two arrays of strings.

Write a script to return true if the two given array represent the same strings otherwise false.

My solution

For input from the command line, I take a string with items concatenated by commas to generate the two lists. This seems to the easiest way to handle this, allowing for empty items as per the fourth example.

def main():
    result = equal_list(sys.argv[1].split(","), sys.argv[2].split(","))
    print("true" if result else "false")

This function is a one liner. I join the items in each list and then compare them to see if they are the same.

def equal_list(arr1: list[str], arr2: list[str]) -> bool:
    return ''.join(arr1) == ''.join(arr2)

The Perl solution has the same functionality.

sub main ( $str1, $str2 ) {
    my @arr1 = split /,/, $str1;
    my @arr2 = split /,/, $str2;

    say join( "", @arr1 ) eq join( "", @arr2 ) ? "true" : "false";
}

Examples

$ ./ch-1.py "a,bc" "ab,c"
false

$ ./ch-1.py "a,bc" "ab,c"
true

$ ./ch-1.py "a,b,c" "a,bc"
true

$ ./ch-1.py "a,bc" "a,c,b"
false

$ ./ch-1.py "ab,c," ",a,bc"
true

$ ./ch-1.py "p,e,r,l" "perl"
true

Task 2: List Division

Task

You are given a list and a non-negative integer.

Write a script to divide the given list into given non-negative integer equal parts. Return -1 if the integer is more than the size of the list.

My solution

For this task, I use the divmod function to calculate the number of items from the list each part needs, and the number of parts that require an extra item. These are stored as the variables item_length and extra_first.

I also have a variable called pos to store the position of the first letter. I have a loop i that runs n times. If i is less than extra_first, I take item_length + 1 items, otherwise item_length times, adding to pos as I go.

def list_division(input_list: list[int], n: int) -> list[list[int]] | None:
    result = []
    pos = 0

    if len(input_list) < n:
        return None

    item_length, extra_first = divmod(len(input_list), n)

    for i in range(n):
        this_length = item_length + 1 if i < extra_first else item_length
        result.append(input_list[pos:pos+this_length])
        pos += this_length

    return result

The Perl solution is similar. It doesn't have the pos variable, as it uses the splice function to remove the necessary number of items from the array. This function returns the items removed.

sub main (@list) {
    # The last value is the 'n' value
    my $n = pop(@list);
    my $length = scalar(@list);

    my @result = ();

    if ( $length < $n ) {
        say -1;
        return;
    }

    my $item_length = int( $length / $n );
    my $extra_first = $length % $n;

    foreach my $i ( 1 .. $n ) {
        my $this_length = $i <= $extra_first ? $item_length + 1 : $item_length;
        push @result, "(" . join( ",", splice( @list, 0, $this_length ) ) . ")";
    }

    say "(" . join( ", ", @result ) . ")";
}

Examples

$ ./ch-2.py 1 2 3 4 5 2
((1,2,3), (4,5))

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

$ ./ch-2.py 1 2 3 2
((1,2), (3))

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

$ ./ch-2.py 1 2 3 4
-1

$ ./ch-2.py 72 57 89 55 36 84 10 95 99 35 7 
((72,57), (89,55), (36,84), (10), (95), (99), (35))
Storable.xs: Avoid signed int overflow when unpacking a list of hook data items

PTS 2026 | Leo Lapworth [blogs.perl.org]

r/perl

Perl Weekly Issue #772 - PTS 2025

r/perl

Perl 🐪 Weekly #772 - PTS 2025

dev.to #perl

Originally published at Perl Weekly 772

Hi there,

The Perl Toolchain Summit 2026 held in Vienna from 23rd - 26th April. I almost forgotton about it, until I read the blog post by Philippe Bruhat. It was refreshing to see the group met and continued the great work. First post event report was shared by Thomas Klausner. The event report gave a detailed insights what happend during the 4-days event. I was hoping to see more such event report from other attendees. Luckily, we had few more to keep you busy by Timothy Legge, Leo Lapworth, Thibault Duponchelle, Shawn Sorichetti, and Paul Johnson. There was even a group photo shared by Paul. I am looking for an update on my personal favourite project MetaCPAN led by Olaf Alders.

Happy to see, Stats::LikeR, which provides R statistical functions. I wish it was available few years ago. I was approached by a research student of an Australian university few years ago asking for help with his Perl script doing R's equivalent function in Perl. Fortunately we did it and paper was accepted in the end. I was surprised by his choice of language for his research paper. He could have easily used R rather than creating equivalent function in Perl. He was well versed with R as well, still he choose Perl, whilst learning the language.

Please watch the recent page on MetaCPAN for such cool modules. Enjoy rest of the newsletter.

--
Your editor: Mohammad Sajid Anwar.

Articles

DBIx::Class::Async - Oracle Database

This post I shared about the proof of support for Oracle in DBIx::Class::Async. It is always assuring the async operations with Oracle database.

Signing CPAN Releases with SigStore

Timothy Legge describes a contemporary way of achieving security in the Perl ecosystem with the implementation of Sigstore to sign CPAN Releases. This post describes how we will transition from using traditional GPG signatures to shorter and easier to obtain certificates, while providing a clear roadmap to assist maintainers (and others) in adopting "keyless" signing and enhancing supply chain security.

DBIx::Class - Schema Class (Part 2)

This is part 2 of the series post about DBIx Schema Class. In this post, I shared how we can configure session on the fly and trap exception globally.

DBIx::Class - Schema Class (Part 3)

In the third part of the series, I discussed the use of DBIx::Class::Schema::Config and how we can securely manage database credentials.

Beautiful Perl feature: low-precedence boolean operators 'and', 'or'

The elegant usefulness of Perl's low-precedence boolean operators (and, or, not) compared to the more common high-precedence operators (&&, ||, !) is further explored by Laurent. The post shows how the low-precedence boolean operator can be used as a "control flow tool" creating readable, idiomatic code using the example of the classic "do or die" convention.

Explain act

In this post, I introduced the workflow automation tool, act. It gives hands-on tutorial on the subject.

Ideas for the CPAN Meta v3 Specification

Improvements to how developers will be able to manage their dependencies and the tools that they use for building them is the goal of several forward-thinking updates proposed by Robert Rothenberg to the CPAN Meta Spec v3. His blog post includes recommendations for enhancements to provide developers with standardised, enhanced requirements for their "develop" phase, as well as improved ways to specify what hardware or operating system a developer's distribution requires to successfully run.

Discussion

This week in PSC (223) | 2026-05-04

A brief report from the Perl Steering Council has provided us with an update about their most recent triage session. Among several small changes and the completion of various CPAN dual-life module updates, one of the major highlights of this update is that there are currently no release blockers.

CPAN

GTC 2.1 go pro

The GTC (Graphics::Toolkit::Color) project has been going well according to Herbert Breunung's progress report on it, including the Go-Pro initiative for professional grade stability. The update on the 2.1 release completed a more efficient API, reducing the amount of work involved in creating colors or generating palettes, and successfully built on a solid foundation for future integration into GUI's and plotting applications.

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 Marc Perry.

The Weekly Challenge - 373

Welcome to a new week with a couple of fun tasks "Equal List" and "List Division". 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 - 372

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

Spaces at Large

Arne Sommer takes a close look at the nuances of whitespace in Raku, especially in relation to how the context of either string or array can affect whitespace. This post provides a practical investigation into how to handle whitespace effectively. Examples of how Raku's syntactical flexibility will allow for clean, expressive code to be written around more complex data structures have been provided.

Perl Weekly Challenge: Week 372

Jaldhar demonstrates the unique strengths of each language, contrasting Perl’s efficient hash-based counting with Raku’s expressive built-ins to solve these algorithmic puzzles.

Regular Sub-Gaps

In this post, Jorg Sommrey provides an in-depth overview of his approaches to each of the two tasks for this week's challenge. He demonstrates that it is possible to write relatively short and very readable code by using List::Util and idiomatic hash slicing. He also shows how these techniques easily handle edge cases such as the case insensitivity of the frequency count of words.

Perl Weekly Challenge 372

Mochan takes a higher-level look at Rearrange Spaces by breaking down an input string into an array and then using the tr/// operator to determine how many elements are in the array before performing some arithmetic to calculate how many spaces need to be added. The x operator and join are both used to construct the output from the individual elements. For the solution to Largest Substring, Mochan uses a hash data structure to remember the first time each character appears in the input string so that he can keep track of the longest substring while going through the input string using an index. He also updates his maximum substring variable each time he sees a character he's previously encountered.

Very Stringish

Matthias Muth offers straightforward, modernly written Perl code using the new v5.40 features of Perl’s builtin::indexed to track the position of all characters in Finding Largest Substring so as to find the maximum length substring in the most efficient manner possible.

Empty Substrings and Empty Spaces

In his blog post, Packy Anderson focuses on the edge cases for each of the challenges and provides solid solutions in Perl, Raku, Python and Elixir. He also explains the logic of his "Rearrange Spaces" solution with exact math for distributing spaces between words, as well as a clever method for handling the -1 requirement for unique characters in his "Largest Substring" solution.

Strings of strings

Peter has given two stylish implementations of the weekly challenge using Perl's native string functions to produce very compact code. For Rearrange Spaces he worked out precisely what gaps were needed to recreate the string using join, and for the Largest Substring solution he had one loop with a hash to keep track of where each character was seen first so that the answer was determined with one cycle through the original string.

The Weekly Challenge - 372: Rearrange Spaces

Reinier presents a straightforward solution with his algorithmic method to achieve a successful outcome on this week's "Rearranging Spaces". This is done in Perl primarily because of its preciseness regarding how many spaces to be distributed across the gaps between the words and determining how many of the combined gaps will result in an even distribution. This post emphasizes on a well-structured plan, such as separating the words from one another using split, and then joining them back together with join and the x operator.

The Weekly Challenge - 372: Largest Substring

Reinier had a methodical solution written in Perl for Weekly Challenge task of finding the largest substring. He used a hash to track the first instance of each character encountered when traversing the string. When he finds two identical characters, he determines their distance by subtracting the first instance's index from the second instance's index, and keeping track of the maximum value found up to that point; if he doesn't find duplicates then he will return -1.

The Weekly Challenge #372

Robbie gives in-depth solutions to the problem, providing excellent input handling as well as clarity in logic. When working with Rearranging Spaces, he uses a regex to identify the count of spaces & words, ensuring the math for gap size calculations & remainders are correct. For example, with regards to one word, he handles it just like the rest (edge cases). In terms of solving the problems of Largest Substring, he uses an array to save the first and last seen indexes of each character as he iterates through the character set of the input string making a distance calculation between these saved locations to determine the largest distance. The solutions are both mathematically correct and easily understood.

Space is the Largest Place

For Rearrange Spaces, Roger considers how to find the gap sizes through integer division and then uses the modulus operator for trailing spaces. He ensures that his logic from each of his implementations remains consistent. In the case of Largest Substring, he uses a "first-seen" hash to improve performance by only traversing through the string one time. He shows us, in his post, an engineering-oriented coding style while also documenting that these algorithmic patterns are transferable to working with dynamic languages.

Distant spaces

In Finding the Largest Substring, Simon created a dictionary in Python and hash in Perl to store the first occurrence of each of the letters in the string. Once this was done, he proceeded through the entire string to compare the current index to the index where the letter was first stored; this enabled him to efficiently track the maximum distance between the first occurrence and the current occurrence. It clearly illustrate that string manipulation and data structures are accomplished using virtually the same logical steps in each of these two programming languages.

Rakudo

2026.18 Star Wars Day

Weekly collections

NICEPERL's lists

Great CPAN modules released last week.

Event reports

Perl Toolchain Summit 2026 - Vienna

According to Timothy Legge, there was an effective meeting; the purpose of this summit was to develop the CPAN Security Group (CPANSec) into a CVE Numbering Authority and improve the security disclosure process for maintainers of CPAN modules. An example of a technical outcome resulting from the summit was the inclusion of signature function support in the distribution of Crypt::OpenSSL::RSA as well as the decision to deprecate Module::Signature in favour of more modern integrity checks.

PTS 2026

Leo Lapworth highlights the 2026 Perl Toolchain Summit by describing some of the major sponsorships that made it possible. He also discusses his own efforts to modernize the MetaCPAN infrastructure and the value of in-person collaboration for solving problems with other core developers.

The Perl Toolchain Summit 2026

In this blog post, Paul Johnson provides his impressions of an intense and productive Perl Toolchain Summit 2026 held in Vienna, and highlights progress made in both Devel::Cover version 2.00 and on integrating with MetaCPAN.

My Perl Toolchain Summit 2026

Thibault’s PTS 2026 report features a heavy lift on Test::Smoke releases and CPAN security hardening. His post offers a deep dive into the technical vetting of YAML payloads and the successful launch of cpm v1.0.

PTS 2026: What Actually Happened

Shawn recaps the PTS 2026 focus on infrastructure, detailing the migration of MetaCPAN services to Kubernetes and enhanced secret management. It’s a grounded look at the high-stakes maintenance work that powers the Perl ecosystem.

Events

Boston Perl Mongers virtual monthly

May 12, 2026

Exploring Perl Modules

May 20, 2026

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.

When you have lots and lots of qcow2

After a pause in April, here is a new article in the Beautiful Perl features series on dev.to: low-precedence boolean operators 'and', 'or'

Thank you Team PWC for your continuous support and encouragement.
Welcome to the Week #373 of The Weekly Challenge.
Thank you Team PWC for your continuous support and encouragement.
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.
Just to give you context, Gabor Szabo, while working on opensource projects recently, he picked up my latest creation DBIx::Class::Async. He noticed, I didn’t have workflow configuration file. He kindly created pull request and submitted: PR #3. Without wasting a moment, I accepted the pull request and merged.
Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. App::cpm - a fast CPAN module installer
    • Version: v1.1.0 on 2026-05-07, with 178 votes
    • Previous CPAN version: v1.0.4 was released the same day
    • Author: SKAJI
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.098004 on 2026-05-08, with 862 votes
    • Previous CPAN version: 2.098003 was released 3 days before
    • Author: OLIVER
  3. App::perlimports - Make implicit imports explicit
    • Version: 0.000060 on 2026-05-06, with 24 votes
    • Previous CPAN version: 0.000059 was released 12 days before
    • Author: OALDERS
  4. App::rdapper - a command-line RDAP client.
    • Version: 1.25 on 2026-05-07, with 21 votes
    • Previous CPAN version: 1.24 was released 2 months, 15 days before
    • Author: GBROWN
  5. Attean - A Semantic Web Framework
    • Version: 0.037 on 2026-05-04, with 19 votes
    • Previous CPAN version: 0.036_01 was released the same day
    • Author: GWILLIAMS
  6. CGI - Handle Common Gateway Interface requests and responses
    • Version: 4.72 on 2026-05-05, with 48 votes
    • Previous CPAN version: 4.71 was released 7 months, 4 days before
    • Author: LEEJO
  7. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260503.001 on 2026-05-04, with 25 votes
    • Previous CPAN version: 20260430.001 was released 3 days before
    • Author: BRIANDFOY
  8. DBIx::Lite - Chained and minimal ORM
    • Version: 0.38 on 2026-05-05, with 30 votes
    • Previous CPAN version: 0.37 was released the same day
    • Author: AAR
  9. Gazelle - a Preforked Plack Handler for performance freaks
    • Version: 0.50 on 2026-05-07, with 26 votes
    • Previous CPAN version: 0.49 was released 6 years, 5 months before
    • Author: KAZEBURO
  10. HTTP::Tinyish - HTTP::Tiny compatible HTTP client wrappers
    • Version: 0.20 on 2026-05-04, with 16 votes
    • Previous CPAN version: 0.19 was released 2 years, 1 month, 26 days before
    • Author: MIYAGAWA
  11. lazy - Lazily install missing Perl modules
    • Version: 1.000002 on 2026-05-09, with 16 votes
    • Previous CPAN version: 1.000001 was released the same day
    • Author: OALDERS
  12. Mojolicious - Real-time web framework
    • Version: 9.45 on 2026-05-05, with 512 votes
    • Previous CPAN version: 9.44 was released the same day
    • Author: SRI
  13. Plack - Perl Superglue for Web frameworks and Web Servers (PSGI toolkit)
    • Version: 1.0054 on 2026-05-05, with 496 votes
    • Previous CPAN version: 1.0053 was released 6 days before
    • Author: MIYAGAWA
  14. Rose::DB::Object - Extensible, high performance object-relational mapper (ORM).
    • Version: 0.823 on 2026-05-04, with 22 votes
    • Previous CPAN version: 0.822 was released 1 year, 3 months, 29 days before
    • Author: JSIRACUSA
  15. Sidef - The Sidef Programming Language - A modern, high-level programming language
    • Version: 26.05 on 2026-05-05, with 123 votes
    • Previous CPAN version: 26.04 was released 1 month, 4 days before
    • Author: TRIZEN
  16. SPVM - The SPVM Language
    • Version: 0.990169 on 2026-05-08, with 36 votes
    • Previous CPAN version: 0.990168 was released 11 days before
    • Author: KIMOTO
  17. Starlet - a simple, high-performance PSGI/Plack HTTP server
    • Version: 0.32 on 2026-05-06, with 18 votes
    • Previous CPAN version: 0.31 was released 9 years, 4 months, 25 days before
    • Author: KAZUHO
  18. Sys::Virt - libvirt Perl API
    • Version: v12.3.0 on 2026-05-06, with 17 votes
    • Previous CPAN version: v12.2.0 was released 1 month, 4 days before
    • Author: DANBERR
  19. Test::MockModule - Override subroutines in a module for unit testing
    • Version: v0.185.0 on 2026-05-07, with 18 votes
    • Previous CPAN version: v0.184.0 was released 1 day before
    • Author: GFRANKS
  20. Test::Most - Most commonly needed test functions and features.
    • Version: 0.42 on 2026-05-07, with 37 votes
    • Previous CPAN version: 0.41 was released 6 days before
    • Author: DCANTRELL
  21. Win32 - Interfaces to some Win32 API Functions
    • Version: 0.60 on 2026-05-05, with 13 votes
    • Previous CPAN version: 0.59_02 was released 1 day before
    • Author: JDB

Beautiful Perl series

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

Today's feature is quite unique in programming languages: the fact that Perl has two different syntaxes for expressing the same boolean operations. Read on to understand why this is clever and beautiful.

Boolean algebra and short-circuit evaluation

The basic operations of Boolean algebra are fundamental in programming; therefore they are present in all programming languages. In the C language, later followed by many other languages, icluding Perl, logical conjunction (the "AND" operator) is written &&, logical disjunction (the "OR" operator) is written ||, and logical negation (the "NOT" operator) is written !. Conjunction has higher precedence than disjunction, so a && b || c && d is parsed as (a && b) || (c && d) and not a && (b || c) && d. The unary negation operator has even higher precedence.

Mathematically speaking, both AND and OR operators are commutative : the left and right operands can be switched without affecting the result. But in programming languages the order of operands is not totally indifferent, because operands have an evaluation cost; therefore the system usually spares the cost of evaluating the right operand whenever it has enough information from the left operand to compute the result of the boolean operation: this is called short-circuit evaluation. For example in the conjunction $x < 9999 && is_prime($x), if $x is a large number, the left condition is false, so the whole expression is necessarily false and there is no need to do an expensive computation to decide if the number is prime. Similarly, when the left operand of a disjunction is true, then the whole expression is true and the right operand need not be evaluated.

Short-circuit evaluation is not only a question of performance: it also has important consequences when operand expressions have side-effects, like changing the value of a global variable or interacting with files, sockets or other elements of the operating system. Because of short-circuiting, the value of the left operand determines if the side-effects of the right operand will happen or not. In languages of C lineage, many common idioms take advantage of this feature for avoiding runtime exceptions: conditions checked in the left operand must be met before operations in the right operand are attempted. For example the left condition might be to check if a file is present before attempting to open it, or check if a number is different from zero before using it as denominator in a division. Here is a C example borrowed from Wikipedia:

bool isFirstCharValidAlpha(const char* p) {
    return p != NULL && isalpha(p[0]); // 1) no unneeded isalpha() execution
                                       //    with p == NULL,
                                       // 2) no SEGFAULT risk
}

Perl expressions are also statements

In languages other than Perl, examples of boolean expressions where operands have side-effects are not frequent, apart from the family of idioms just mentioned. Expressions with side-effects may even be considered inadvisable. Perl is different, because expressions are also statements, as explained in perlsyn:

The only kind of simple statement is an expression evaluated for its side-effects.

Therefore a boolean combination of expressions is also a statement. Likewise, instructions in real life may also be combinations of more atomic instructions:

Add four spoons of sugar and dissolve it into the preparation, or replace it by honey.

The above sentence indeed can be seen as a boolean expression with short-circuit: either you add sugar and then you must dissolve it and there is no need for honey, or you don't use sugar, so there is no need to dissolve anything, and you just have to incorporate the honey.

This way of expressing composite instructions is used everyday in natural language; therefore, expressing programming instructions in a similar way helps to make them easily understandable by humans, often better than sequences of if-then-else constructs, at least when the composite instruction only contains two or three individual clauses. Most programming languages would require the individual clauses to be enclosed in parentheses, which impedes readability.

Boolean expressions in Perl: two sets of operators, same semantics, different precedence

Perl's brilliant solution for improving the readability of composite instructions is to offer another set of boolean operators, written as the English words and, or, not, with exactly the same semantics as the usual &&, || and !, but with lower precedence. Actually, these word versions of boolean operators have the lowest precedence of all in Perl's table of operators, which means that statements between such keywords will be nicely parsed as an individual clauses. Let us look at a simple example:

say "tic", "tac" and say "toe";

The intended result is two lines of output

tictac
toe

and it indeed works that way. The first say is a list operator of very high precedence. Commas after such an operator build a list that will be fed as arguments to say ... but that list stops at the keyword and because of its very low precedence, so it is equivalent to the following parenthesized version:

say("tic", "tac") and say("toe");

Now since we are using parentheses, we might as well write

say("tic", "tac") && say("toe");

with exactly the same result. By contrast, the && version without parentheses

say "tic", "tac" && say "toe"

produces a different output:

toe
tic1

because everything after the first say was treated as an argument list to that say, so an equivalent parenthesized version would be:

say("tic", ("tac" && say("toe")));

The expression "tac" && say "toe" needs to be evaluated first, which is why the output has toe on the first line. The result of that expression is 1 because since the left operand is true, the boolean && returns the value of the right operand say("toe"), which is 1. Then the outer say can do its job, and since it received two arguments "tic" and 1, it prints tic1 on the second line.

This example with say was good for explanations, but is unlikely to be written like this in real programs. More realistic situations involve other list operators, like this very common idiom with open:

open my $fh, '<', $filename
  or die "failed to open '$filename': $!";

Here is another example with mkdir; this also shows that of course several successive boolean connectors can be combined:

-d $dir                                # does this directory exist ?
  or mkdir $dir                        # if not, try to create it
  or die "failed to mkdir '$dir': $!"; # if the creation failed, report the error

Assignment operations

Examples so far were mainly with the or operator. Usage of and is more often combined with assignment operations: a variable takes the value of an expression, and if that value is not empty, then a follow-up operation is performed.

$n_items = $aref && @$aref
  and say "this array contains $n_items items"
  or  say "this array is empty";

This example assumes a variable $aref to be a reference to an array. The first line checks if the reference is indeed defined, and if so, if it refers to a non-empty array. Depending on the result, the appropriate follow-up message is printed.

For this example to work, the $n_items variable must be already declared earlier in the code: unfortunately it wouldn't work here to write my $n_items = ... because the my declaration would only take effect at the end of the whole statement; therefore at the point where the interpreter parses the string "this array contains $n_items items", variable $n_items would not be declared yet and would throw an exception.

This excerpt shows a single expression containing both && and and. Perl's table of operator precedence has been carefully crafted so that the assignment operator = (and its derivatives +=, *=, etc.) has lower precedence than boolean operators in their symbolic syntax &&, || or !, but higher precedence than those operators in their english syntax and, or, not. Therefore the value assigned to $n_items is $aref && @$aref, including the && operator, but it does not include what comes after the and.

The result of a boolean operator is the last operand

The example of the previous section assigns a boolean expression to a variable $n_items whose name indicates that it is not meant to receive a constant true or false but an integer number! This may be surprising for readers accustomed to strongly typed languages like Java or C++, where the result of a boolean expression can only take one of two boolean values.

By contrast, boolean expressions in Perl, like in several other dynamically typed languages (JavaScript, Python, Ruby, etc.), return the the last evaluated value. That value therefore can have a dual purpose: not only can it be tested for truthness (where any value different from undef, 0, "0" or "" means "true"), but it can also be used for its regular scalar value, as a number, string or reference. Many common idioms in Perl and other similar languages take advantage of this feature for writing compact expressions. A more verbose but more explicit version of the assignment above would be:

$n_items = defined $aref ? @$aref > 0 ? @$aref
                                      : 0
                         :              undef;

Real example

To conclude with a real example, here is an excerpt from my module Data::Domain with quite heavy use of idiomatic and / or constructs:

sub _inspect {
  my ($self, $data) = @_;

  looks_like_number($data)
    or return $self->msg(INVALID => $data);

  if (defined $self->{-min}) {
    $data >= $self->{-min}
      or return $self->msg(TOO_SMALL => $self->{-min});
  }
  if (defined $self->{-max}) {
    $data <= $self->{-max}
      or return $self->msg(TOO_BIG => $self->{-max});
  }
  if (defined $self->{-not_in}) {
    grep {$data == $_} @{$self->{-not_in}}
      and return $self->msg(EXCLUSION_SET => $data);
  }

  return;
}

Like always in Perl, there are several ways to do it. Here the stylistic choice was to use if statements for checking the main conditions, but and / or expressions for secondary checks. Another way to write the condition on -min could be:

  defined $self->{-min}
    and $data < $self->{-min}
    and return $self->msg(TOO_SMALL => $self->{-min});

or perhaps

  return $self->msg(TOO_SMALL => $self->{-min})
    if defined $self->{-min} and $data < $self->{-min};

Low precedence and/or in other programming languages

Apart from Perl, dual sets of boolean operators are only found in Ruby and PHP, two programming languages that were heavily influenced by Perl. Apparently their designers considered that this was a good idea! By contrast, a language like Python where the motto is there is only one way to do it did not adopt such a design.

Apart from stylistic preferences, the reason why low-precedence boolean operators in Perl are so effective is that they combine especially well with the other features of the language mentioned above, like the fact that expressions are also instructions, and the fact that boolean expressions return the last evaluated value.

Conclusion

Perl's invention of a double set of operators for a same purpose was a bold step, clearly on a different path than usual endeavors in programming language design that often seek to minimize the set of operators, with features as orthogonal as possible.

Yet Perl's choice integrates particularly well with other technical features of the language and with its general philosophy. Algorithmic steps can be written in a way that closely reflects natural language and natural thinking, without heavy syntactic if-then-else constructs and without verbose parentheses.

About the cover picture

Since the seminal Camel Book, Perl has been associated with the image of a camel (actually a dromedary). Here we have a camel carrying a performing organist ... nice illustration for a beautiful Perl feature. This woodcut print is part of a 16th-century Triumphal Procession series commissioned by the Holy Roman Emperor Maximilian I. The image is borrowed from the Deutsch Fotothek.

One of my modules report 99.999% coverage due to a single // usage which I'm trying to understand. Simplifying things, consider this program:

sub scalar_rhs
{
    my $a;
    my $b = 1;

    $a // $b
}

sub hash_rhs
{
    my $a;
    my %b = ( x => 1 );

    $a // $b{x}
}

die 'scalar failed' unless &scalar_rhs;
die 'hash failed' unless &hash_rhs;

Running:

perl -MDevel::Cover test.pl
cover -report text

Generates:

line  err      %      l  !l&&r !l&&!r   expr
----- --- ------ ------ ------ ------   ----
6     ***     33      0      1      0   $a // $b
15    ***     33      0      0      1   $a // $b{'x'}

How come $b{x} is seen as false by Devel::Cover? How can I make this pass as !l&&r?

Açık kaynak dünyasında bazen en masum görünen modüller bile ciddi güvenlik riskleri taşıyabiliyor. Dün yayınlanan CVE-2026–5081, tam da bu…

Answer

It’s kinda complicated. i3 exposes a scratchpad_state on every node, but it is not relevant for the node you initially check. The window node of the application you are targetting. Today we are scratching an itch.

When I saw this question posted on Reddit I first thought: let’s look at the data. My Workspace on Demand daemon has an IPC event debugger. So I fired it up and went looking at the data, my debugger told me:

I was working on some code that creates a reference to a substring call, and then passes that. I assumed this would be a SCALAR ref, since it seems like it would just be a SCALAR with a string in it? Why does this ref return LVALUE?

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

my $str = "hello";
my $lv = \substr($str, 1, 2);
say ref($lv);          # LVALUE

I did a little dig in perlguts and I do see the LVALUE SVTYPE, so I assume this is intended behavior.

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::ClusterSSH - Cluster administration tool
    • Version: 4.19 on 2026-04-28, with 980 votes
    • Previous CPAN version: 4.18_09 was released 1 month, 7 days before
    • Author: DUNCS
  2. App::cpm - a fast CPAN module installer
    • Version: v1.0.3 on 2026-05-02, with 178 votes
    • Previous CPAN version: v1.0.2 was released the same day
    • Author: SKAJI
  3. App::Music::ChordPro - A lyrics and chords formatting program
    • Version: v6.101.0 on 2026-04-30, with 469 votes
    • Previous CPAN version: v6.100.0 was released 8 days before
    • Author: JV
  4. Cache::FastMmap - Uses an mmap'ed file to act as a shared memory interprocess cache
    • Version: 1.61 on 2026-04-30, with 25 votes
    • Previous CPAN version: 1.60 was released 10 months, 12 days before
    • Author: ROBM
  5. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260430.001 on 2026-04-30, with 25 votes
    • Previous CPAN version: 20260426.001 was released the same day
    • Author: BRIANDFOY
  6. DBD::Pg - DBI PostgreSQL interface
    • Version: 3.20.2 on 2026-05-02, with 103 votes
    • Previous CPAN version: 3.20.1 was released 2 days before
    • Author: TURNSTEP
  7. Encode - character encodings in Perl
    • Version: 3.24 on 2026-04-29, with 65 votes
    • Previous CPAN version: 3.23 was released 2 days before
    • Author: DANKOGAI
  8. MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
    • Version: 2.043000 on 2026-04-29, with 29 votes
    • Previous CPAN version: 2.042000 was released 3 days before
    • Author: MICKEY
  9. Plack - Perl Superglue for Web frameworks and Web Servers (PSGI toolkit)
    • Version: 1.0053 on 2026-04-28, with 496 votes
    • Previous CPAN version: 1.0052 was released 1 day before
    • Author: MIYAGAWA
  10. PPI - Parse, Analyze and Manipulate Perl (without perl)
    • Version: 1.291 on 2026-04-25, with 64 votes
    • Previous CPAN version: 1.290 was released the same day
    • Author: MITHALDU
  11. SPVM - The SPVM Language
    • Version: 0.990168 on 2026-04-27, with 36 votes
    • Previous CPAN version: 0.990167 was released 2 days before
    • Author: KIMOTO
  12. Starman - High-performance preforking PSGI/Plack web server
    • Version: 0.4018 on 2026-04-27, with 297 votes
    • Previous CPAN version: 0.4017 was released 2 years, 7 months, 13 days before
    • Author: MIYAGAWA
  13. Test::MockModule - Override subroutines in a module for unit testing
    • Version: v0.183.0 on 2026-05-01, with 18 votes
    • Previous CPAN version: v0.182.0 was released the same day
    • Author: GFRANKS
  14. Test::Most - Most commonly needed test functions and features.
    • Version: 0.41 on 2026-04-30, with 37 votes
    • Previous CPAN version: 0.40 was released the same day
    • Author: DCANTRELL
  15. Test2::Harness - A new and improved test harness with better Test2 integration.
    • Version: 1.000172 on 2026-04-29, with 28 votes
    • Previous CPAN version: 1.000171 was released 5 days before
    • Author: EXODIST
  16. Text::CSV_XS - Comma-Separated Values manipulation routines
    • Version: 1.62 on 2026-04-29, with 104 votes
    • Previous CPAN version: 1.61 was released 9 months, 2 days before
    • Author: HMBRAND
  17. YAML::LibYAML - Perl YAML Serialization using XS and libyaml
    • Version: v0.906.0 on 2026-04-26, with 60 votes
    • Previous CPAN version: v0.906.0 was released the same day
    • Author: TINITA

TPRC Announces Post Conference Class

Perl Foundation News

TPRC is proud to announce the post-conference class on Monday, June 29. Steven Lembark is presenting: Teaching AI New Tricks: Perly MCP’s for Claude. The class will be from 9am to 4pm in the Palmetto Room at the Conference Hotel. SHORT DESCRIPTION: MCP definitions are not your mother’s API call. They are natural language descriptions meant for the tool to process and integrate into its own workflow. With proper description, the MCP’s are simple to use and can be daisy-chained to produce quite flexible results. Claude’s different models — Haiku, Sonnet, Opus — offer different options for cost, speed, and depth and require different definitions. In the spirit of the Perl Tester’s Notebook, this class covers a very basic tool then expands it for general use, one step at a time, looking at the necessary changes to Perl and the MCP. The result is a lightweight, fast interface that handles a common task easily and can be incorporated with other tools. For a more complete class description, please visit: https://tprc.us/tprc-2026-gsp/class/ Tickets for the class are $120 and are available at: https://perlfoundation.fcsuite.com/erp/donate/list/event?event_date_id=1002

Toronto Perl Mongers / March 2026 Talk

The Perl and Raku Conference YouTube channel

From April 23-26, 2026, the invite-only Perl Toolchain Summit (PTS) brought together about 30 of the ecosystem’s most active maintainers — including four first-timers — in Vienna, Austria for four days of uninterrupted deep-dive collaboration in pair-programming sessions, consensus discussions, and critical infrastructure work. Attendees tackled security tooling and infrastructure, modernization and redesign proposals, several CI and test harness improvements, Perl core optimizations, and metadata/spec updates.

Thanks to all the sponsors’ support (financial, in-kind, and community), this year’s Summit was a success. It produced multiple module releases, consensus on future smoke-testing and CPAN Testers architecture, and a new CPANSec advisory feed that will allow developers to quickly assess any Perl project’s security using either CLI tools or the MetaCPAN website itself. Those advancements benefit all organizations relying on Perl directly or indirectly.

PTS 2026 Key Results & Deliverables

Security

CPANSec took it to another level, getting faster at discovering vulnerabilities (in modules, infrastructure and core) and improving its process:

  • Vulnerability triage;
  • CNA improvements;
  • Meta V3 is moving forward;
  • Deprecated Module::Signature, considered “security theater”.

Testing and Quality Assurance

Testing and QA work included:

  • On the road to Devel::Cover 2.00;
  • Several improvements made to Test::Smoke, with 3 releases: removal of dual PerlIO/stdio testing, making install more robust (and portable);
  • Test::Smoke backend full rewrite to ensure sustainability with new features and better performance;
  • The Test2 family of modules, including the new web user interface, was greatly improved, with many issues fixed and new features implemented;
  • Syncing from backpan.perl.org to fill in CPAN Testers’ backpan;
  • New MCP server mcp.cpantesters.org to browse CPAN Testers reports from your preferred LLM CLI.

Supply Chain and Other Modules

Many CPAN authors and maintainers worked on:

PAUSE

Very hacktive PAUSE table:

  • Implemented new API token access;
  • Security fixes (“rand rand rand rand”, “ABRA time” and “META symlinks”);
  • New dockerized PAUSE;
  • Various pentesting (e.g. reviewing YAML parser);
  • Ongoing work on OAuth/OIDC;
  • Several Pull Requests merged.

Funding

Recent years brought the topic of funding to the front of the stage. In particular to ensure the sustainability of Perl maintenance funds, accelerate some initiatives (e.g. CPAN Security efforts) and finance community events (like this one!).

A lot of things happened on this front during the Perl Toolchain Summit:

  • A strong effort towards funding security work;
  • General discussions about funding of the community.

Group discussions

The Perl Toolchain Summit also provides a lot of opportunity for interaction. Whether they’re corridor discussions, small talk to get to know each other and build trust, discussions around a drink or group discussions (that led in the past to “consensus” or “amendment” papers), it all ends up strengthening the Perl toolchain.

During this PTS in particular, there were a lot of group discussions, probably helped by having a dedicated meeting room.

On the topic of Toolchain

  • META V3
  • CPAN clients

On the topic of AI

  • AI Policies Materials
  • AI Policies Governance
  • Share your AI tooling and tips!

On the topic of Security

  • CRA presentation and Q&A

On the topic of Perl core

  • Perl Ongoing and future features
  • Perl core class/roles implementation
  • Configure
  • UTF-8
  • Plan for Perl Platforms

Podcasts

As in 2025, PTS 2026 was an opportunity to record new episodes for The Underbar. There were over five hours of conversations recorded, about:

  • Configure
  • Vienna.pm
  • PPI
  • the Perl Steering Council
  • Karl Williamson

Why Sponsor Support Matters

Bringing 30–35 experts under one roof enabled unprecedented collaboration with real-time problem solving, saving months of remote coordination and alignment. That kind of accelerated development and knowledge transfer not only brings the community together but fuels the contributors of critical open source projects for the rest of the year so they can renew their shared goals and work in the same direction. Having four first-time attendees gaining direct mentorship is also fundamental to seed future contributions and expand the volunteer base, ensuring the longevity of the Perl ecosystem and toolchain.

The continued support of our sponsors ensures that the Perl Toolchain Summit remains a catalyst for Perl sustainability — translating sponsor investment into tangible improvements in performance, security, and ecosystem features and coherence. We look forward to partnering again to power the next wave of innovation in Perl’s toolchain.

Sponsors

Last week the Perl Toolchain Summit took place in Vienna (the second time, we also hosted the event in 2010). I participated mostly in the role of local orga, helping the international team finding a venue and a hotel, a place for the social event etc.

For the venue, Michael suggested Hauswirtschaft, where Geizhals sometimes hold meetings and events. This turned out to be an excellent choice. Not only did we get the rooms at a reasonable price (at least when compared to some of the more mainstream hotels), but the rooms and the whole venue were very nice and extremely accommodating: We were served vegetarian lunch each day, could bring our own snacks and drinks (the delicious apple juice Hauswirtschaft provided was not enough for some of the very specific Cola needs of some attendees; luckily there's a supermarket right across) and have a Pizza-and-Chartreuse-Party on Saturday (which I have been told ended quite late). Transporting 16 boxes of pizza on my bike trailer was also fun!

I had little time for technical contributions, as I was busy organizing dinners, answering peoples questions about Vienna and generally having a nice time. But I managed to code up a local development environment for PAUSE based on docker compose. Andreas merged it on Sunday, so if you want to have a local PAUSE (for testing and developing new features), you can now do so via a simple docker compose up pause paused. Detailed instructions can be found here and I would appreciate it if people give it a try and report back any problems they have. Having a working local dev setup is IMO crucial for getting meaningful contributions.

Together with Michael I was interviewed by Philippe for his podcast. We talked about the history and future of Vienna.pm, Geizhals, Koha and some other topics. The interview and the whole event motivated me to keep Vienna.pm going and maybe try to host a Perl-and-related-tech-events (again) in the future. We'll see...

To summarize, I really enjoyed the event, hanging around with Perl people & talking about basically everything. It was a nice reminder that this community is exactly my kind of crazy! Looking forward to the next PTS or similar event!

And no post about the PTS is complete without thanking the sponsors (is it ok to thank yourself, as I'm involved with two of the sponsors (Vienna.pm and HSK3)? I say it is...)

I am currently trying to install this module with :

perl -MCPAN -e shell install XML::Parser::Style::Tree

It did not install it, but it installed cpan. Inside cpan, I issued again:

install XML::Parser::Style::Tree

At beginning, the process was going well. Then suddenly I receive these error messages:

Can't locate File/ShareDir/Install.pm in @INC (@INC contains: ./inc /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at Makefile.PL line 7.
BEGIN failed--compilation aborted at Makefile.PL line 7.
Warning: No success on command[/usr/bin/perl Makefile.PL INSTALLDIRS=site]
Warning (usually harmless): 'YAML' not installed, will not store persistent state
  TODDR/XML-Parser-2.58.tar.gz
  /usr/bin/perl Makefile.PL INSTALLDIRS=site -- NOT OK
Running make test
  Make had some problems, won't test
Running make install
  Make had some problems, won't install
Could not read '/home/leopoldo/.cpan/build/XML-Parser-2.58-jE9k8s/META.yml'. Falling back to other methods to determine prerequisites
Failed during this command:
 TODDR/XML-Parser-2.58.tar.gz                 : writemakefile NO '/usr/bin/perl Makefile.PL INSTALLDIRS=site' returned status 512

So, I am open to suggestions on how to solve it.

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::Music::ChordPro - A lyrics and chords formatting program
    • Version: v6.100.0 on 2026-04-21, with 468 votes
    • Previous CPAN version: v6.090.1 was released 3 months, 18 days before
    • Author: JV
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.098002 on 2026-04-20, with 864 votes
    • Previous CPAN version: 2.098001 was released 3 days before
    • Author: OLIVER
  3. App::perlimports - Make implicit imports explicit
    • Version: 0.000059 on 2026-04-24, with 24 votes
    • Previous CPAN version: 0.000058 was released 5 months, 26 days before
    • Author: OALDERS
  4. Bitcoin::Crypto - Bitcoin cryptography in Perl
    • Version: 4.005 on 2026-04-23, with 18 votes
    • Previous CPAN version: 4.004 was released 1 month, 5 days before
    • Author: BRTASTIC
  5. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260419.002 on 2026-04-19, with 25 votes
    • Previous CPAN version: 20260412.001 was released 7 days before
    • Author: BRIANDFOY
  6. CryptX - Cryptographic toolkit
    • Version: 0.088 on 2026-04-23, with 53 votes
    • Previous CPAN version: 0.087_008 was released the same day
    • Author: MIK
  7. DateTime::TimeZone - Time zone object base class and factory
    • Version: 2.68 on 2026-04-23, with 22 votes
    • Previous CPAN version: 2.67 was released 1 month, 17 days before
    • Author: DROLSKY
  8. DBIx::Class::InflateColumn::Serializer - Inflators to serialize data structures for DBIx::Class
    • Version: 0.10 on 2026-04-19, with 13 votes
    • Previous CPAN version: 0.09 was released 9 years, 3 months, 4 days before
    • Author: MRUIZ
  9. Encode - character encodings in Perl
    • Version: 3.22 on 2026-04-25, with 65 votes
    • Previous CPAN version: 3.21 was released 2 years, 1 month, 28 days before
    • Author: DANKOGAI
  10. Google::Ads::GoogleAds::Client - Google Ads API Client Library for Perl
    • Version: v32.0.0 on 2026-04-22, with 20 votes
    • Previous CPAN version: v31.1.0 was released 27 days before
    • Author: CHEVALIER
  11. Log::Any - Bringing loggers and listeners together
    • Version: 1.720 on 2026-04-25, with 69 votes
    • Previous CPAN version: 1.719 was released 1 month, 8 days before
    • Author: PREACTION
  12. MetaCPAN::Client - A comprehensive, DWIM-featured client to the MetaCPAN API
    • Version: 2.041000 on 2026-04-25, with 29 votes
    • Previous CPAN version: 2.040000 was released 1 month, 16 days before
    • Author: MICKEY
  13. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20260420 on 2026-04-20, with 45 votes
    • Previous CPAN version: 5.20260330 was released 21 days before
    • Author: BINGOS
  14. PPI - Parse, Analyze and Manipulate Perl (without perl)
    • Version: 1.290 on 2026-04-25, with 64 votes
    • Previous CPAN version: 1.289 was released the same day
    • Author: MITHALDU
  15. SPVM - The SPVM Language
    • Version: 0.990167 on 2026-04-24, with 36 votes
    • Previous CPAN version: 0.990166 was released the same day
    • Author: KIMOTO
  16. Test2::Harness - A new and improved test harness with better Test2 integration.
    • Version: 1.000171 on 2026-04-23, with 28 votes
    • Previous CPAN version: 1.000170 was released 13 days before
    • Author: EXODIST
  17. YAML::LibYAML - Perl YAML Serialization using XS and libyaml
    • Version: v0.905.0 on 2026-04-24, with 60 votes
    • Previous CPAN version: v0.905.0 was released 1 day before
    • Author: TINITA
  18. YAML::PP - YAML 1.2 Processor
    • Version: v0.40.0 on 2026-04-24, with 27 votes
    • Previous CPAN version: v0.40.0 was released 1 day before
    • Author: TINITA
  19. YAML::Syck - Fast, lightweight YAML loader and dumper
    • Version: 1.45 on 2026-04-23, with 18 votes
    • Previous CPAN version: 1.44 was released 20 days before
    • Author: TODDR

cpan.org email forwarding has been shut down

The Perl NOC

We know this will disappoint many of you, but it was not feasible to keep it running anymore with a reasonable quality.

Several factors led to the decision:

  • Communication has moved on. 25 years ago it was important to provide a consistent way for users to contact CPAN module authors.  Today people use rt.cpan.org, forums, and other channels..

  • Over 99% of mail was spam.  Even two layers of spam filtering let some through, hurting deliverability for our other outbound mail.

  • Modern email requires ARC, DKIM, DMARC, and SPF. Providing these correctly on a forwarding service is hard, so legitimate mail often fails to be delivered.

  • We approached several email providers, but were unable to find one to host the service.

  • The number of active users was small compared to the number of CPAN authors. During a recent extended, unannounced outage, we received only two inquiries.


We will work with the cpan-security team so they keep a way to reach authors.


Bounces will soon report that the MX cpan.org-email-is-gone-use-http-rt.cpan.org cannot be found as a breadcrumb pointing toward alternatives.


cpan.org email was one of the first services we ran for the Perl community; over the years we've added others, some for the wider internet. The perl.org mailing lists have been running for 28 years and continue to operate. We also still help run PAUSE and the CPAN archive system. rt.cpan.org remains available, thanks to The Perl Foundation and Request Tracker.


For most of its 25 years, cpan.org email was widely used, and running it was a pleasure. The last seven or eight became mostly spam fights and deliverability work — a big part of why we're stopping now.


Please don't ask us to reconsider. We recognize this change will affect some users more than others.  We wrestled with this for a long time and are confident that it is the right call. 


Sincerely,


The perl noc volunteers


TL;DR

This is a rant, a developer war story of how to use docker to work around a problem that shouldn’t exist in the first place. Configure your PHP project with a different, lower version, of PHP than you are using yourself. Read how I spent an evening fighting PHP.

The bare minimum

Can someone in PHP land please tell me why composer is unable to create a project on PHP version 8.2 when I’m running PHP version 8.4? I’m creating a PHP app that needs to run on bookworm, aka, Debian 12, which ships PHP 8.2.

Perl · Objective-C · Visual Basic · CoffeeScript · Ruby

TPRC Talk Submission Deadline in 2 days!

Perl Foundation News

There are only 2 days left to submit a talk for TPRC! The cutoff is April 21. If you have an idea for a talk, it is definitely time to get it submitted. We need a wide variety of speakers and topics, so give it a try! Go to https://tprc.us/ to make your submission.

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

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.098001 on 2026-04-16, with 859 votes
    • Previous CPAN version: 2.098000 was released the same day
    • Author: OLIVER
  2. Authen::Passphrase - hashed passwords/passphrases as objects
    • Version: 0.009 on 2026-04-15, with 14 votes
    • Previous CPAN version: 0.008 was released 14 years, 2 months, 11 days before
    • Author: LEONT
  3. Convert::Pheno - A module to interconvert common data models for phenotypic data
    • Version: 0.31 on 2026-04-17, with 15 votes
    • Previous CPAN version: 0.30 was released 2 days before
    • Author: MRUEDA
  4. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20260412.001 on 2026-04-12, with 25 votes
    • Previous CPAN version: 20260405.001 was released 7 days before
    • Author: BRIANDFOY
  5. Finance::Quote - Get stock and mutual fund quotes from various exchanges
    • Version: 1.69 on 2026-04-18, with 149 votes
    • Previous CPAN version: 1.68_02 was released 1 month, 5 days before
    • Author: BPSCHUCK
  6. Imager - Perl extension for Generating 24 bit Images
    • Version: 1.030 on 2026-04-13, with 68 votes
    • Previous CPAN version: 1.029 was released 6 months, 7 days before
    • Author: TONYC
  7. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.638 on 2026-04-18, with 16 votes
    • Previous CPAN version: 0.637 was released 10 days before
    • Author: ETHER
  8. SPVM - The SPVM Language
    • Version: 0.990162 on 2026-04-18, with 36 votes
    • Previous CPAN version: 0.990161 was released the same day
    • Author: KIMOTO
  9. version - Structured version objects
    • Version: 0.9934 on 2026-04-12, with 22 votes
    • Previous CPAN version: 0.9933 was released 1 year, 7 months, 17 days before
    • Author: LEONT

Zsh has regexp-replace, you don’t need sed:

autoload regexp-replace regexp-replace line '^pick' 'f'

Also, instead of hard coding values, use zstyle:

# in your .zshrc zstyle ':xyz:xyz:terminal' terminal "kitty" # in your script/function local myterm zstyle -s ':xyz:xyz:terminal' terminal myterm || myterm="Eterm"