Shortcuts: s show h hide n next p prev

Creating executables with Perl minor issue

r/perl

I'm just writing since maybe this could provide some insight to someone.
Also, maybe could point out what am I doing wrong.

At work I created a Tool, which for its endeavours uses XML::LibXML.
When using it with the latest Strawberry Perl 5.42 I do not have any issues.
Everything is working fine.

Some of our colleagues like the snaky language better and do not like the idea of having Perl on their machine or they are just managers and do not have it,
but whatever 'different strokes for different folks'.

So I focused my attention on pp, I created a working stonealone executable without any effort.
(stonealone: a stand-alone executable, suitable for running on a machine that doesn't have perl installed)

It was working fine on my machine, but one of the colleagues had an issue:
Can't load LibXML.xs.dll ...

After few hours of tinkering, looking through wrong places, experimenting with package creation, sifting through documentation, sifting through the expanded package inside the temp folder, checking .dll-s with EXE/DLL PE Viewer and Editor etc..:

The solution was that I created the package as:

pp -o myExecutable.exe myScript.pl -x --xargs=" -g -f 6021485"
-l C:\DevEnv\perl\v5_42\c\bin\libxml2-2__.dll
-l C:\DevEnv\perl\v5_42\c\bin\zlib1__.dll
-l C:\DevEnv\perl\v5_42\c\bin\libiconv-2__.dll
-l C:\DevEnv\perl\v5_42\c\bin\liblzma-5__.dll

As you can see I added the missing .dll-s to the package. Also you can see that I tried to execute the script with -x and also added arguments to execute the script to determine additional dependencies. (but -x did not solve the problem by itself, btw I think it could even be omitted from the call)

"Using this option, pp may be able to detect the use of modules that can't be determined by static analysis of inputfile. Examples are stuff loaded by run-time loaders like Module::Runtime or "plugin" loaders like Module::Loader."

After these everything is fine for users without Perl installed.

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

Adding Perl Backend to Vuejs App - Part 1: Getting Started

Perl on Medium

I have started learning some frontend with vuejs recently, and as a start, built a to-do app with the tutorial from MDN…

win32/perllib.c: Omit unused formal parameter name

to silence a compiler warning
pp_sys.c: Initialize variable to avoid compiler warning

The MingW compiler thinks this can be used unininitalized
pp_hot.c: Initialize variable to avoid compiler warning

The MingW compiler thinks this can be used unininitalized.
toke.c: Initialize variable to avoid compiler warning

The MingW compiler thinks this can be used unininitalized, even though I
don't think it can.  Just initialize it to 0.
pp_hot.c: Don't use signed char as an array index

The MingW compiler spotted this.  The code prior to these uses already
has made sure these indices are positive, so casting to unsigned works.

Long story short I have written my own custom HTML template system that I am very happy with. However I have done that with manually concatenating HTML tags, and it is a bit messy. There has to be a perl library that will help you build a static HTML document and then output the result. But when I google for a solution I get plenty of options about parsing HTML documents, using templates to generate HTML, or frameworks to generate HTML pages dynamically, but I can't seem to find a perl library that you can generate an HTML document with. Does anybody have any suggestions?

OpenAPI Linter

r/perl

Can't install IPC::ShareLite in a CentOS 7.9 Docker

r/perl

I'm trying to use Docker to create a development environment for an ages-old Perl application that runs under Perl 5.10.1. The application runs under CentOS 5.11, but you can't run a CentOS 5.11 Docker - the kernel is too old - so I opted for the earliest CentOS image I could get my hands on, centos:7.

I've gotten all of the Perl modules from the machine the application is running on installed except for IPC::ShareLite. When I try and install it via cpanm, it fails, and when I look at build.log, I see Can't parse Makefile fragment at Makefile.PL line 58.. Any idea what this Docker image might be missing?

Full output from cpanm:

[root@docker work]# cpanm IPC::ShareLite@0.17 --> Working on IPC::ShareLite Fetching http://www.cpan.org/authors/id/A/AN/ANDYA/IPC-ShareLite-0.17.tar.gz ... OK CPAN::Meta::YAML found a duplicate key 'no_index' in line '' at /usr/pkg/bin/cpanm line 197. Configuring IPC-ShareLite-0.17 ... N/A ! Configure failed for IPC-ShareLite-0.17. See /root/.cpanm/work/1762212229.15/build.log for details.

Full build.log:

``` cpanm (App::cpanminus) 1.7048 on perl 5.010001 built for x86_64-linux Work directory is /root/.cpanm/work/1762211132.15 You have make /usr/bin/make You have LWP 5.837 You have /usr/bin/tar: tar (GNU tar) 1.26 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.

Written by John Gilmore and Jay Fenlason. You have /usr/bin/unzip Searching IPC::ShareLite (== 0.17) on cpanmetadb ... --> Working on IPC::ShareLite Fetching http://www.cpan.org/authors/id/A/AN/ANDYA/IPC-ShareLite-0.17.tar.gz -> OK Unpacking IPC-ShareLite-0.17.tar.gz Entering IPC-ShareLite-0.17 Checking configure dependencies from META.yml Checking if you have ExtUtils::MakeMaker 6.58 ... Yes (7.76) Configuring IPC-ShareLite-0.17 Running Makefile.PL Checking if your kit is complete... Looks good Can't parse Makefile fragment at Makefile.PL line 58. -> N/A -> FAIL Configure failed for IPC-ShareLite-0.17. See /root/.cpanm/work/1762211132.15/build.log for details. ```

CentOS packages installed (in addition to the packages installed with the base image):

libX11-devel libdb-devel readline-devel perl-Test-Tester perl-core libidn-devel openssl-devel libxml2-devel expat-devel tcl tk mysql zip unzip nroff wget bzip2 make less gcc bison byacc

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

When using the perl library Storable to store and retrieve XML::LibXML document objects, I get a segmentation fault. Specifically, once I use the LibXML routine findnodes. My question is: why, and is there a way around it?

For example consider the following code:

use strict;
use warnings;
use XML::LibXML;
use Storable;
use Devel::Size qw/size/;
use Data::Dumper qw/Dumper/;

my $file = "test.xml";
my $store_file = "./dom.xml.store";
my $dom;
if(-e $store_file ){
        $dom = retrieve $store_file;
        print "dom retrieved from storable $store_file\n";
}else{
        $dom = XML::LibXML->load_xml(location => $file);
        print "dom retrieved from xml $file\n";
        store $dom, $store_file;
}
print Dumper $dom;
print "Dom ref(". ref($dom) . "), size(" . size($dom) . ")\n";

#test 
foreach my $title ($dom->findnodes('//title')){
        print $title->to_literal() . "\n";
}

Running this code twice yields the following result:

$~/perl:perl libxml.pl 
dom retrieved from xml test.xml
$VAR1 = bless( do{\(my $o = '93874673292592')}, 'XML::LibXML::Document' );
Dom ref(XML::LibXML::Document), size(72)
Apollo 13
Solaris
Ender's Game
Interstellar
The Martian
$~/perl:perl libxml.pl 
dom retrieved from storable ./dom.xml.store
$VAR1 = bless( do{\(my $o = '93874673292592')}, 'XML::LibXML::Document' );
Dom ref(XML::LibXML::Document), size(72)
Segmentation fault
$~/perl:

The xml file which I named test.xml file is the same file retrieved from the tutorial here. Similar tests were run on my system with unblessed and blessed perl objects, neither of which caused the segmentation fault.

Usual disclaimers: perl version: v5.26.3 Storable version 3.11 LibXML version 2.0132

Perl 🐪 Weekly #745 - Perl IDE Survey

dev.to #perl

Originally published at Perl Weekly 745

Hi there!

First of all, apologies. Apparently last edition included a link the source of the Perl IDE survey and not the actual Perl IDE Survey itself. This week we hope to provide you with the correct link.

The announcement about the London Perl Workshop might have also been a bit premature as it was still unclear if it will happen at all. I am still unclear about the exact situation, but this is an excellent opportunity for you to step up. Check out the web-site of LPW where you can find the names and the contact information of the organizers. Talk to them and offer your help. Any help. That will increase the chances for this to actually take place. We even received a special announcement exclusive to the readers of the Perl Weekly.

I figured I need to update my web site and emphasize that I help companies deal with legacy code, and that made me think: What does 'legacy code' mean? How is it different from 'existing code' or 'code in production'? Is it a term use in a derogative manner? Does it mean 'code that is in use, but where the authors have disappeared'? Does it mean 'code that I am scared to touch'? Maybe 'code that still makes money, but we are unsure how it works, we need to make changes but we are scared to do'?

I'd love to hear (well, read) what do you think about it. I know I could ask the AI overlord, but I am old-school and I prefer human intelligence.

While we are figuring out how to define legacy code I thought I'll organize an online event in which we'll take a CPAN module and add some tests to it. Register here

In any case, have a nice week!

--
Your editor: Gabor Szabo.

Announcements

Perl IDE survey

After a long hiatus the Perl IDE Survey is back to another round. It will take you about 20 seconds to fill it.

Articles

6 Perl One-Liners to Replace Common Linux Utilities

why for/foreach can't use existing vars?

A lesson in scoping?

OpenAPI Linter

OpenAPI has become the standard for designing, building and documenting RESTful APIs. However, ensuring your OpenAPI specifications are both syntactically correct and follow best practices can be challenging. OpenAPI::Linter brings comprehensive validation and linting capabilities directly into your Perl applications and development workflow, helping you catch issues before they impact your API consumers.

Increasing Code coverage with Gemini

Excellent, showing the prompts help a lot!

Enhance your Gemini code assistance with a PRD document

I made a multiple-insert as well as other methods for Mojo::Pg

ANNOUNCE: Perl.Wiki V 1.33 & Mojolicious.Wiki V 1.08

Ron moved to a retirement village and still coding at 75. Nice.

App::Test::Generator 0.12

App::Test::Generator - Generate fuzz and corpus-driven test harnesses. This module takes a formal input/output specification for a routine or method and automatically generates test cases.

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

Welcome to a new week with a couple of fun tasks "Longest Parenthesis" and "Magic Expression". 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 - 345

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

TWC345

Code that is clear, effective and useful and that accurately addresses both issues. The solutions demonstrate good Perl fundamentals with straightforward algorithmic approaches.

Last Peak

This is an excellent example of using Raku's special feature set to solve a problem in a stylish, understandable and effective manner. In addition to solving the problem, Arne uses it to illustrate why Raku is a delight for algorithmic and data-centric programming. It is a brilliant pedagogical move to go from a naive to an idiomatic solution.

I Went to the Mountains

Excellent practical Perl programming is demonstrated in this post, with an emphasis on readable, maintainable code that addresses the issue at hand directly. Bob takes a methodical, deliberate approach that is full of the kind of practical judgment that distinguishes good code from great code. The technical content is very interesting because of the conversational tone and cultural allusions.

Perl Weekly Challenge: Week 345

Excellent approach to problem-solving that combines efficient debugging and logical reasoning. By pointing out edge cases, clearing up early misunderstandings and offering comprehensive explanations, Jaldhar exhibits strong analytical abilities.

The Last Peak

This is a thorough, engineering-focused in-depth analysis that places a premium on robustness, accuracy and beautiful API design. It is not merely a solution post. Jorg approaches the challenges with the rigor of a software engineer building production-grade code, not just solving puzzles.

Perl Weekly Challenge 345

A sophisticated, functionally-focused Perl solution that showcases complex programming methods like closures, iterators and functional composition. He tackles the problems with a thorough knowledge of Perl's functional programming features.

Visiting the Peaks

Brilliantly idiomatic Perl that makes use of sophisticated language features to produce succinct, effective and ingenious solutions. Matthias exhibits a thorough comprehension of Perl's contemporary features and functional programming capabilities.

Teach Them How To Say PWC…

This is a philosophical and pedagogical analysis of the Perl Weekly Challenge itself rather than a solution post. The difficulties serve as a starting point for more in-depth conversations about community, learning and the nature of programming expertise.

Peak at the answers

A simple, effective and useful Perl implementation that uses little code to accurately address both issues. Without superfluous abstraction or flourish, Peter concentrates on the fundamental algorithmic requirements. It is an example of "get the job done" programming.

The Weekly Challenge #345

A comprehensive, expertly designed set of solutions with a focus on robustness, extensive testing and unambiguous documentation. Robbie shows how to develop software in a methodical, quality-focused manner.

Position the Visitor

A highly analytical and mathematically complex method that investigates the problems underlying structure. Beyond simple implementation, Roger explores mathematical properties, algorithmic complexity and sophisticated Raku idioms.

Peak Visitors

A simple, useful implementation that puts accuracy and readability ahead of cunning. Simon is refreshingly honest about their comprehension of the issues and exhibits a methodical approach to problem-solving.

Perl Weekly Challenge: 345

A clear, useful Perl implementation that uses simple, readable code to accurately address both issues. Vinod exhibits solid Perl foundations and a pragmatic approach to problem-solving.

Weekly collections

NICEPERL's lists

Great CPAN modules released last week.

Events

Perl Maven online: Adding tests to legacy Perl code

November 11, 2025

Paris.pm monthly meeting

November 12, 2025

London Perl and Raku Workshop

November 29, 2025

Toronto.pm - online - How SUSE is using Perl

December 6, 2025

Paris.pm monthly meeting

December 10, 2025

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

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

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

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

App::Test::Generator 0.12

r/perl

I'm pleased to announce the release of App::Test::Generator version 0.12, bringing several improvements to automated test generation.

What's New in 0.12:
Enhanced Configuration Options
Smarter Random String Generation
Better Error Reporting
Expanded Testing Capabilities

App::Test::Generator automatically generates comprehensive test harnesses from formal specifications of your functions and methods. It combines:

Random fuzzing based on input types
Deterministic edge cases for constraints
Static corpus tests from Perl or YAML

This black-box testing approach helps catch boundary errors, invalid data handling, and regressions without requiring the manual creation of every test case.

Learn More:

Documentation: https://metacpan.org/pod/App::Test::Generator
Repository: https://github.com/nigelhorne/App-Test-Generator

Happy testing!

submitted by /u/Dangerous-Sense977
[link] [comments]
Thank you Team PWC for your continuous support and encouragement.
Welcome to the Week #346 of The Weekly Challenge.

According to the new source::encoding pragma's documentation,

use source::encoding 'ascii' is automatically enabled within the lexical scope of a use v5.41.0 or higher.

To me, this means that

use v5.42;

is equivalent to

use v5.42;
use source::encoding "ascii";

But that doesn't seem to be the case.

$ perl -e'use v5.42; my $x = "é";'

$ perl -e'use v5.42; use source::encoding "ascii"; my $x = "é";'
Use of non-ASCII character 0xC3 illegal when 'use source::encoding "ascii"' is in effect at -e line 1, near ""ascii";"
Execution of -e aborted due to compilation errors.

Bug or misunderstanding?

OpenAPI::Linter

blogs.perl.org


One more contribution, OpenAPI::Linter to validate and lint OpenAPI Specification. For more information, please follow the link:
https://theweeklychallenge.org/blog/openapi-linter

TLS in perl using IO::Socket API.

r/perl

Hi,

I have the following pieces of code:

#!/usr/bin/perl use strict; use IO::Socket::SSL; my $socket = IO::Socket::SSL->new( LocalAddr => '127.0.0.1', LocalPort => 1234, Listen => 10, SSL_use_cert => 1, SSL_cert_file => 'server.crt', SSL_key_file => 'server.key', SSL_ca_file => 'ca.crt', # SSL_version => 'TLSv1', ) || die "Could not create socket: $@"; my $client = $socket->accept() || die "Could not accept: $@"; print STDERR "Accepted connection\n"; my $buf = ''; my $n = $client->sysread($buf, 1024); print "Message $n '" . $buf . "'\n"; 1; 

And:

#!/usr/bin/perl use strict; use IO::Socket::SSL; my $socket = IO::Socket::SSL->new( PeerAddr => '127.0.0.1', PeerPort => 1234, SSL_use_cert => 1, SSL_cert_file => 'client0.crt', SSL_key_file => 'client0.key', SSL_ca_file => 'ca.crt', # SSL_version => 'TLSv1', ) || die "Could not create socket: $@"; #$socket->connect() || die "Could not connect: $@"; $socket->syswrite("Hello!\n"); $socket->close(); 1; 

The code works when I leave the 'SSL_version' parameter out. It stops working (with an obscure error message, namely

Could not create socket: SSL connect attempt failed error:0A0C0103:SSL routines::internal error at tls_client_1.pl line 6 

) when I put it in. The perldoc page says we're using SSL when left out. I don't want that - I want to use TLS (preferably 1.3). Any thoughts? Any way I could debug this issue a bit closer (attach some meaning to the error)?

Thanks.

Btw the certificates have been created using the following shell script:

#!/bin/sh CANAME='ca'; rm -f $CANAME.* openssl genrsa -out $CANAME.key 4096 openssl req -x509 -new -nodes -key $CANAME.key -sha256 -days 1826 -out $CANAME.crt -subj '/CN=MyOrg Root CA/C=OI/ST=Here/L=There/O=MyOrg' MYCERT=client0 rm -f $MYCERT.* openssl req -new -nodes -out $MYCERT.csr -newkey rsa:4096 -keyout $MYCERT.key -subj '/CN=client0/C=OI/ST=Here/L=There/O=MyOrg' # create a v3 ext file for SAN properties cat > $MYCERT.v3.ext << EOF authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] #DNS.1 = myserver.local #DNS.2 = myserver1.local #IP.1 = 192.168.1.1 #IP.2 = 192.168.2.1 DNS.1=localhost IP.1=127.0.0.1 EOF openssl x509 -req -in $MYCERT.csr -CA $CANAME.crt -CAkey $CANAME.key -CAcreateserial -out $MYCERT.crt -days 730 -sha256 -extfile $MYCERT.v3.ext 
submitted by /u/RedWineAndWomen
[link] [comments]

Increasing Code coverage with Gemini

blogs.perl.org

On my last post I asked Gemini to create a product requirement document to outline a plan to improve the overall state of the ev-calc-pricing application. In this blog entry I will discuss my interaction with Gemini and how it increased code coverage of the ev-calc-pricing application. Below is an example of the prompts:


----
> review PRD.md for @ev-calc-pricing

╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile PRD.md │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ The PRD.md outlines a plan to refactor the ev-calc-pricing application to improve maintainability, data accuracy, and
robustness.

Key issues identified:
* Manual, hardcoded electricity rate data in StateRates.pm.
* Minimal test coverage.
* Unused scripts and lack of input validation.

The plan focuses on four epics:
1. Automated Data Pipeline: To fetch, process, and load electricity rate data automatically.
2. Comprehensive Test Suite: To ensure accuracy and stability of calculations and data loading.
3. Code Refactoring and Cleanup: To remove hardcoded data, unused scripts, and consolidate data files.
4. Enhanced User Experience: To add input validation and better user feedback.

The success metrics include reducing data update time, increasing code coverage to over 80%, and eliminating
calculation-related bugs.

> Lets focus on code coverage
✦ Okay, code coverage. The PRD says EVCalc.pm and StateRates.pm need unit tests. I'll start by reviewing the existing
tests in the t/ directory.
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFolder t │
│ │
│ Listed 2 item(s). │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Okay, two test files: 001_base.t and 002_index_route.t. I'll read 001_base.t first to see what it covers.
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile t/001_base.t │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 001_base.t just loads EVCalc. Now reading 002_index_route.t to check its web interface tests.
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile t/002_index_route.t │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ 002_index_route.t is a simple integration test for the main route. I'll now examine EVCalc.pm to understand the core
logic for testing.
╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile lib/EVCalc.pm │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I've analyzed EVCalc.pm and found the calculation logic is embedded in the post '/' route. To properly test it, I'll
refactor the calculations into a new calculate_costs subroutine. My plan is to move the logic, create a new test file
t/003_calculation.t, and then write unit tests for various scenarios. I'm starting with the refactoring of EVCalc.pm
now.


-------------

And yes Gemini did refactor my code in order to create a test file and test the new function but unfortunately it didn't get it write in the first try.

Here is the refactored code with the test script

And now the correction on the test script .

line of code in the test script :
------------
is( $results{state_rates}->{'Alabama'}->{total_price}, '10.77', 'Correct total price for Alabama' );
------------

Essentially Gemini assumed that the states were abbreviated on StateRates.pm until it attempted a test run and learned that not only the state name was incorrect but also the calculated results. So you see AI just like humans have moments where it forgets what it wrote a few mins ago.

And now for the coverage report:

---------------------------------------
t/001_base.t ......... ok
t/002_index_route.t .. 1/2 [EVCalc:26770] core @2025-11-01 22:13:40> looking for get / in /Library/Perl/5.34/Dancer2/Core/App.pm l. 37
[EVCalc:26770] core @2025-11-01 22:13:40> Entering hook core.app.before_request in (eval 279)[/System/Library/Perl/Extras/5.34/Class/Method/Modifiers.pm:89] l. 1
[EVCalc:26770] core @2025-11-01 22:13:40> Entering hook core.app.after_request in (eval 279)[/System/Library/Perl/Extras/5.34/Class/Method/Modifiers.pm:89] l. 1
[EVCalc:26770] core @2025-11-01 22:13:40> running hook entry Dancer2::Core::App::__ANON__ in (eval 279)[/System/Library/Perl/Extras/5.34/Class/Method/Modifiers.pm:89] l. 1
t/002_index_route.t .. ok
t/003_calculation.t .. ok
All tests successful.
Files=3, Tests=6, 1 wallclock secs ( 0.01 usr 0.00 sys + 0.87 cusr 0.08 csys = 0.96 CPU)
Result: PASS
Reading database from /Users/itcharlie/Desktop/Projects/ev-calc-pricing/cover_db


---------------------- ------ ------ ------ ------ ------ ------
File stmt bran cond sub time total
---------------------- ------ ------ ------ ------ ------ ------
blib/lib/EVCalc.pm 100.0 n/a n/a 100.0 99.9 100.0
blib/lib/StateRates.pm 100.0 n/a n/a 100.0 0.0 100.0
Total 100.0 n/a n/a 100.0 100.0 100.0
---------------------- ------ ------ ------ ------ ------ ------


---------------------------------------


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.

(dlxxii) 15 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::Music::ChordPro - A lyrics and chords formatting program
    • Version: v6.090.0 on 2025-10-31, with 409 votes
    • Previous CPAN version: v6.080.1 was 2 months, 2 days before
    • Author: JV
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.094002 on 2025-10-29, with 773 votes
    • Previous CPAN version: 2.094001 was before
    • Author: OLIVER
  3. App::perlimports - Make implicit imports explicit
    • Version: 0.000058 on 2025-10-28, with 20 votes
    • Previous CPAN version: 0.000057 was 5 months, 28 days before
    • Author: OALDERS
  4. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251026.001 on 2025-10-26, with 25 votes
    • Previous CPAN version: 20251020.002 was 5 days before
    • Author: BRIANDFOY
  5. DBIx::DataModel - UML-based Object-Relational Mapping (ORM) framework
    • Version: 3.14 on 2025-10-28, with 13 votes
    • Previous CPAN version: 3.13 was 2 days before
    • Author: DAMI
  6. HTTP::BrowserDetect - Determine Web browser, version, and platform from an HTTP user agent string
    • Version: 3.45 on 2025-11-01, with 58 votes
    • Previous CPAN version: 3.44 
    • Author: OALDERS
  7. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.621 on 2025-10-30, with 12 votes
    • Previous CPAN version: 0.620 was 14 days before
    • Author: ETHER
  8. Mojo::mysql - Mojolicious and Async MySQL/MariaDB
    • Version: 1.28 on 2025-10-30, with 36 votes
    • Previous CPAN version: 1.27 was 2 years, 3 days before
    • Author: JHTHORSEN
  9. Mouse - Moose minus the antlers
    • Version: v2.6.0 on 2025-10-30, with 63 votes
    • Previous CPAN version: v2.5.11 was 1 year, 2 months, 25 days before
    • Author: SYOHEX
  10. OrePAN2 - Yet another DarkPAN manager.
    • Version: 0.53 on 2025-10-31, with 22 votes
    • Previous CPAN version: 0.52 was 1 year, 8 months, 11 days before
    • Author: OALDERS
  11. Perlanet - command line interface to Perlanet.pm
    • Version: v3.3.4 on 2025-10-29, with 25 votes
    • Previous CPAN version: v3.3.3 was 5 months, 29 days before
    • Author: DAVECROSS
  12. PPI - Parse, Analyze and Manipulate Perl (without perl)
    • Version: 1.284 on 2025-10-28, with 64 votes
    • Previous CPAN version: 1.283 was 5 months, 24 days before
    • Author: OALDERS
  13. Time::Piece - Object Oriented time objects
    • Version: 1.39 on 2025-10-25, with 64 votes
    • Previous CPAN version: 1.38 was 6 days before
    • Author: ESAYM
  14. WebService::Fastly - an interface to most facets of the [Fastly API](https://www.fastly.com/documentation/reference/api/).
    • Version: 13.00 on 2025-10-31, with 18 votes
    • Previous CPAN version: 12.00 was 2 months, 2 days before
    • Author: FASTLY
  15. WWW::Mechanize::Chrome - automate the Chrome browser
    • Version: 0.75 on 2025-10-31, with 22 votes
    • Previous CPAN version: 0.74 was 25 days before
    • Author: CORION

Enhance your Gemini code assistance with a PRD document

blogs.perl.org

In my previous blogpost I briefly discussed the use of Gemini Cli on a Perl dancer application to analyze its codebase. The next step is to generate a product requirement document. Why is this important ? well I had a bad experience with Gemini on another application where I allowed it to roam free "YOLO" mode and it basically started fixing all the problem areas one after another for about an hour or so until my free trial of Google Gemini expired for the day. This resulted into a completely rewritten application that was not able to run due to so many different errors. The cool thing is that I had version control so a good old "git reset --hard Head" cleared up my project and I could start over again.

Ok so back to the product requirement document, this document basically outlines the steps needed to resolve all the recommendations made by Gemini Ai during its code analysis. This means that you now have a clear path for AI to follow and you can essentially continue where you left off just in case you run out of free AI tokens for the day. Also make sure that you have a project that is under version control so you can commit changes as they occur after testing. Here is an example of the PRD.md file from my github repository.


The code is in this gist

insert_multi_p will let you insert multiple rows in Postgres with a single query, like this:


await $db->insert_multi_p(
    'table_name',
    [
       {
          ... anything you'd be able to write in insert_p ...
       },
       {
           ... second row to insert ...
       },
       ... etc ...
    ],
    {
         ...normal pg insert options...
    },
);

Lots of other interesting methods in there, that I use in my projects.

You can use this Role in your postgres object as follows:


my $pg = Mojo::Pg->new($db_string)->database_class(Mojo::Pg::Database->with_roles('+MyApp'));

OpenAPI Linter

The Weekly Challenge
OpenAPI has become the standard for designing, building and documenting RESTful APIs. However, ensuring your OpenAPI specifications are both syntactically correct and follow best practices can be challenging. OpenAPI::Linter brings comprehensive validation and linting capabilities directly into your Perl applications and development workflow, helping you catch issues before they impact your API consumers.

Get at the usual place...
Elsewhere, I've moved house, into a retirement village.
Yes, folks. I'm 75, much to my horror and astonishment.
It was an exhausting process, but I'll settled in now. And still programming!
And not just the wikis. I have various other projects I can get back to now I've moved.
Why move?
Because I downsized. The price difference gives me a little bit of money in the bank.

PWC 345: I Went to the Mountains

dev.to #perl

I found the two tasks this week straight-forward and oddly specific, respectively.

Music: the task titles this week are "Peak Positions" and "Last Visitor", which led me to the refrain "I went to the mountains." It's a reference to Closer to Fine by the Indigo Girls, which references Perl philosophy: "There's more than one answer to these questions pointing me in a crooked line, and the less I seek my source for some definitive, the closer I am to fine."

However, for "Peak Positions", let's go with Ain't No Mountain High Enough by Marvin Gaye; and for "Last Visitor", with it's odd back and forth, how about the venerable Hello, Goodbye by the Beatles.

Task 1: Peak Position

The task

You are given an array of integers, @ints. Find all the peaks in the array. A peak is an element that is strictly greater than its left and right neighbors. Return the indices of all such peak positions.

The thought process

My first thought was to use List::MoreUtils::indexes to test each element, but the edges make it weird. One way or another, they will have to be handled separately. Maybe put a fake element on each end? Do them first and then process the rest? Or test for edges while looping?

My mental model is that the edges of the list fall away into an abyss, so anything outside the list should be below the altitudes given at the edge positions. I suppose it's equally valid to assume that the list is surrounded by huge ice walls (winter is coming).

There are a couple of unspecified anomalies, for which I'm going to take executive decisions:

  • Empty list: return an empty list
  • Single element: that's one peak at index 0
  • Ramp up: (e.g. 7,8,9) the rightmost element is the only peak
  • Ramp down: (e.g. 6,5,4) the left-most element is the only peak
  • Plateau: (e.g., 7,7,7) No peak, return an empty list. This contradicts my decision for a single element (a plateau of one). Do I contradict myself? Very well then, I contradict myself. (I am large, I contain multitudes.)

The code

sub peakPos(@int)
{
    my @peak = ();
    for my ($i, $n) ( indexed @int )
    {
        my $left  = ( $i == 0     ) ? $n-1 : $int[$i-1];
        my $right = ( $i == $#int ) ? $n-1 : $int[$i+1];
        push @peak, $i if ( $n > $left && $n > $right );
    }
    return \@peak;
}

Notes:

  • Once again I chose indexed (anointed as non-experimental in Perl 5.40) for concise and efficient array traversal.
  • Each element has a left neighbor and a right neighbor. For the edges, I'm going to conjure up the missing neighbor and make it less, assuming that outside the list is a bottomless void. You know the one -- the one we scream into while we're on mute during Zoom calls.

Task 2: Last Visitor

The task

You are given an integer array @ints where each element is either a positive integer or -1. We process the array from left to right while maintaining two lists:

  • @seen: stores previously seen positive integers (newest at the front)
  • @ans: stores the answers for each -1

Rules:

  • If $ints[i] is a positive number -> insert it at the front of @seen
    • If $ints[i] is -1:
    • Let $x be how many -1s in a row we’ve seen before this one.
    • If $x < len(@seen) -> append seen[x] to @ans
    • Else -> append -1 to @ans

At the end, return @ans.

The thought process

This task description is highly proscriptive. I'm not sure there's anything better to do here than to translate the text into Perl statements.

sub lastVisitor(@int)
{
    my @seen = ();
    my @ans  = ();

    my $x = 0;  # Count of consecutive -1s
    for ( @int )
    {
        if ( $_ > 0 )
        {
            $x = 0;
            unshift @seen, $_;
        }
        else
        {
            if ( $x < @seen )
            {
                push @ans, $seen[$x];
            }
            else
            {
                push @ans, -1;
            }
            $x++;
        }
    }
    return \@ans;
}

Notes: I don't think there's much to add. There's a couple of basic language features being exploited.

  • for (@int) -- use the implicit $_ variable for array elements to avoid having to think of a name
  • unshift -- put things on the front of a list
  • @seen -- in scalar context gives the size of the array (no need for a length())

The only thing tricky here is incrementing and resetting $x so that it correctly counts the consecutive occurrences of -1. Because there was a possibility of error, I of course made that error, but unit tests straightened me out.

Thank you Team PWC for your continuous support and encouragement.

0xblog — About “Perl” in 2022 (and beyond !)

Perl on Medium

How Perl can still be great … :o

Perl 🐪 Weekly #744 - London Perl Workshop 2025

dev.to #perl

Originally published at Perl Weekly 744

Hi there,

We are excited to announce that The Trampery, located on Old Street in London, will host the London Perl Workshop 2025 on November 29, 2025. Bring your thoughts, your code, your queries and your excitement to this next must-attend Perl community event. To help shape the day, the organisers are already taking suggestions from sponsors and the community. We would like to express our gratitude in advance to all of the sponsors who help make this event possible. Our community thrives because of your support; if you or your organisation are interested in sponsorship opportunities, please review the information on the website. This is your chance to interact, learn, share and develop whether you're an experienced Perl hacker, module author, maintainer or someone who is interested in the language's future developments.

The Perl core team released the development release Perl v5.43.4 concurrently with the announcement of the event. This version provides the most recent advancements in Perl's development and is a member of the blead (development) branch. Please find the changes in the perldelta page.

26th Oct marks the 30th anniversary of the Comprehensive Perl Archive Network (CPAN), which has been driving innovation, teamwork and the Perl ecosystem for 30 years. I can still clearly recall my initial feelings of excitement and apprehension when I uploaded a module to CPAN, knowing that it would be instantly mirrored globally. When CPAN was founded in 1995, it was truly revolutionary. Built before GitHub even existed, it gave Perl a superpower that no other language at the time possessed: a global, searchable, installable archive of reusable code. The people who created the archive as well as the archive itself are what most amaze me. CPAN has always been primarily a human network, with volunteers running PAUSE, tireless testers finding bugs before users ever notice them, authors who ship with care and toolsmiths who make installations run more smoothly each year. To celebrate the occassion, I uploaded v0.67 of BankAccount::Validator::UK.

Enjoy rest of the newsletter.

--
Your editor: Mohammad Sajid Anwar.

Announcements

Development release of Perl v5.43.4

This release focuses on Unicode handling improvements and internationalization support.

London Perl Workshop 2025

It's back again, please join us for an exciting informative one day event.

Dancer2 2.0.1 Released

Dancer2 2.0.1 has been released. It's a small maintenance release that fixes a few broken documentation links.

The Perl IDE - Developer Survey 2025 is now live!

After 12 year hiatus, the Perl IDE Developer Survey has returned! Please do take part in the survey.

Articles

Perl in Jupyter Notebook: A Modern Look for a Classic Language

The article is valuable and motivational, especially for people in the Perl community who feel Perl has had less representation in data science / notebooks / ML. It shows convincingly that the building blocks exist and invites people to experiment.

0xblog — About “Perl”, in 2022

This article is inspiring and helpful, in my opinion. Anyone in the Perl community (or nearby) who wants to be reminded of Perl's modern capabilities and feel that it is still relevant should read it.

A palindromic polyglot program in x86 machine code, Perl, shell, and make

Binary Golf Grand Prix is an annual small file format competition, currently in it's sixth year. The goal is to make the smallest possible file that fits the criteria of the challenge.

Beware of Geeks bearing Grifts

Excellent technical writing - accessible deep knowledge, strong literary craft, authentic developer humor and clearly rooted in the Perl ecosystem.

CPAN

Test2::Plugin::SubtestFilter

Test2::Plugin::SubtestFilter released for Perl tests, which allows filtering test targets by subtest name, similar to --testNamePattern in jest and vitest.

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

Welcome to a new week with a couple of fun tasks "Peak Positions" and "Last Visitor". 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 - 344

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

TWC344

This blog post successfully guides the reader through the process of resolving two programming challenges and is technically sound and well-written. It exhibits sound coding techniques and strong problem-solving abilities. The main strength of the post is its easy-to-understand, step-by-step explanation style, which makes it suitable for programmers of all skill levels.

Form Formation

The post is well structured and easy to follow, introducing the challenge clearly and then solving it step by step. It uses clean, idiomatic Raku, showcasing native language strengths like permutations, MAIN signature validation and concise array/string transformations. The solutions are compact yet readable, demonstrating how expressive Raku can be for problems that would be verbose in other languages.

Pick Up the Pieces

The post provides a clear, correct and well-structured solution using backtracking. It balances readability with reasonable efficiency for small to medium-sized inputs.

Perl Weekly Challenge: Week 344

This is a brief and useful article that emphasizes offering practical solutions with little fanfare. The author demonstrates a get-it-done mentality by using a "one-liner" approach for the first problem and a simple brute-force permutation strategy for the second. The review will draw attention to some crucial scalability and robustness considerations, even though the solutions are functionally correct for the examples provided.

Turning Arrays Into Arrays

The blog post provides clear, concise and idiomatic Perl solutions to the week 344 tasks. The post provides multiple examples for each task, covering various scenarios and edge cases. This helps readers understand the problem's nuances and test their solutions effectively.

Lazyness and too much tasks!

The post is excellent as an educational and practical demonstration of Raku for these algorithmic challenges. It leverages Raku’s expressive features well amd for small to medium inputs, the solutions work effectively.

Perl Weekly Challenge 344

This is a sophisticated and well-engineered set of solutions that demonstrates deep expertise in Perl, particularly with the Perl Data Language (PDL). It provides multiple approaches for each task, showing a thorough understanding of different algorithmic strategies and their trade-offs. The code is professional, robust and well-documented.

Take it to the Limits

This is a superb example of production-quality thinking that goes far beyond typical challenge solutions. Matthias demonstrates exceptional foresight in identifying edge cases and designing scalable, robust algorithms.

A-ray Sunshine!

This technical blog post is incredibly well-written and captivating. It effectively achieves its main objective, which is to guide the reader through a challenging programming problem while elucidating the reasoning behind it, its dead ends and its elegant solution. In technical writing, it's the ideal illustration of "show your work".

Hip, hip, array!

In the great majority of real-world use cases, this solution accurately resolves the issue and is clear, practical and effective. It creates a sophisticated one-liner by utilizing Perl's advantages in handling strings and numbers. The fundamental requirement of the problem—converting between array and numerical representations—is clearly understood by Peter.

The Weekly Challenge #344

For the examples provided, Robbie offers two workable solutions that accurately address the challenge problems. The solutions are straightforward and practical, prioritizing clarity and simplicity over scalability or optimization for edge cases. The code has a clear structure and useful documentation.

All is Array Formation

This blog post goes beyond standard challenge solutions and is incredibly intelligent and sophisticated. In addition to solving the problems, Roger delves into complex computer science ideas and skillfully makes connections between the two seemingly unconnected tasks. The post exhibits expert-level understanding of functional programming paradigms, algorithms and programming language theory.

The one about arrays

This explanation of the Weekly Challenge solutions is clear, easy to understand and useful. Beginners and intermediate developers will find Simon's conversational, tutorial-like style especially approachable. The article emphasizes readability and direct problem-solving over algorithmic optimization, with a focus on concise, practical Perl solutions.

Perl Weekly Challenge: 344

These are clean, practical and clever solutions that demonstrate excellent Perl idioms and pragmatic problem-solving. Vinod favors simplicity and readability while leveraging Perl's unique strengths effectively.

Rakudo

2025.42 Release #186 (2025.10)

Weekly collections

NICEPERL's lists

Great CPAN modules released last week.

Events

Paris.pm monthly meeting

November 12, 2025

London Perl and Raku Workshop

November 29, 2025

Toronto.pm - online - How SUSE is using Perl

December 6, 2025

Paris.pm monthly meeting

December 10, 2025

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

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

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

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

Weekly Challenge: The one about arrays

dev.to #perl

Weekly Challenge 344

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

Challenge, My solutions

Task 1: Array Form Compute

Task

You are given an array of integers, @ints and an integer, $x.

Write a script to add $x to the integer in the array-form.

The array form of an integer is a digit-by-digit representation stored as an array, where the most significant digit is at the 0th index.

My solution

The easiest solution would be to turn the ints array into an integer, add the value and then turn it back into an array. However, I don't think this is what this challenge is about.

So it's back to doing things like we did in primary school math classes. For input from the command line, I take the last argument as x and the rest of the arguments as ints (a list in Python, array in Perl).

I start by making sure that ints only contains a single digit and x is a non-negative integer.

def array_form_compute(ints: list[int], x: int) -> list[int]:
    if any(not isinstance(n, int) or n < 0 or n > 9 for n in ints):
        raise ValueError("All elements in the list must be single digit integers (0-9).")

    if x < 0:
        raise ValueError("The integer x must be a non-negative integer.")

The next step is to handle all but the most significant (first) digit. Working backwards (last digit first), I set the pos variable to determine the position of the digit I am working on. I set i to the value of the integer at the position.

I take the x value and split it using the divmod function. The remainder is the remainder of diving x by 10 (i.e. the last digit), and x is now the integer division which is used in the next iteration.

    for pos in range(len(ints) -1, 0, -1):
        i = ints[pos]
        x, remainder = divmod(x, 10)

This is where primary school math comes into play. If i + remainder is more than one digit (i.e. greater than 9), then the last digit of the sum becomes the new i and the other digits are added to the integer before it. In this case, it is added to the x value.

        add_x, add_i = divmod(i + remainder, 10)
        ints[pos] = add_i
        x += add_x

Lastly I need to handle the most significant digit slightly differently. In this case, where ints[0] + x is greater than or equal to 10, I need to split the digits of the new number to a list of individual digits.

    ints[0] += x
    if ints[0] >= 10:
        digits = map(int, str(ints[0]))
        ints = list(digits) + ints[1:]

Finally, I return the new list, or print the array in Perl.

    return ints

The Perl solution follows the same logic. It doesn't have a built in divmod function, so I created one.

sub divmod($a, $b) {
    my $div = int($a / $b);
    my $mod = $a % $b;
    return ($div, $mod);
}

Examples

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

$ ./ch-1.py 2 7 4 181
[4, 5, 5]

$ ./ch-1.py 9 9 9 1
[1, 0, 0, 0]

$ ./ch-1.py 1 0 0 0 0 9999
[1, 9, 9, 9, 9]

$ ./ch-1.py 0 1000
[1, 0, 0, 0]

Task 2: Array Formation

Task

You are given two list: @source and @target.

Write a script to see if you can build the exact @target by putting these smaller lists from @source together in some order. You cannot break apart or change the order inside any of the smaller lists in @source.

My solution

For input from the command line, I take a JSON string from the first argument and convert that to the source variable. The remaining arguments make up the target value.

This is one challenge that is a lot easier to complete in Python than in Perl. I explain the Python solution.

I start by seeing if a solution is indeed possible. This is done by counting the frequency of all digits in both the source and target lists and seeing if they are the same. If they are not the same, I return False.

def array_formation(source: list[list[int]], target: list[int]) -> bool:
    # Check that a solution is possible
    if Counter(chain.from_iterable(source)) != Counter(target):
        return False

There are a few inbuilt features in the above.

  • itertools.chain.from_iterable is a function that will flatten a list of lists in to a single list.
  • collections.Counter will turn an iterable (in this case a list) and turn it into a dictionary with the value as the key and the frequency as the value.
  • In Python, comparing two dictionaries for equality will compare to see if the key and value are the same. The order of the keys does not matter.

From here, there are two possible approaches to take. One would be to call a recursive function to try all valid starting numbers recursively until we found the one that works. Given the examples (where there is only a few lists in the source value), this seems like an unneeded optimization.

So I took the brute force approach and compute all permutations of the source list. If I find the right one, I return True. If I exhaust all permutations, I return False.

Python has the permutations function from the itertools module. In Perl, the Algorithm::Combinatorics function does the same.

    for perm in permutations(source):
        combined = list(chain.from_iterable(perm))
        if combined == target:
            return True

    return False

The Perl solution follows the same logic. It does not have an inbuilt way to flatten so I wrote my own.

sub flatten_array($list) {
    return map { @$_ } @$list;
}

It also cannot compare an array for equality, so I faked it by joining the lists with spaces and then tested if the two strings are equal.

sub compare_array ( $list1, $list2 ) {
    return join( ' ', @$list1 ) eq join( ' ', @$list2 );
}

To check that a solution is possible, I numerically sort the source and target values to check if they are equal.

sub array_formation( $source, $target ) {
    if (
        not compare_array(
            [ sort { $a <=> $b } flatten_array($source) ],
            [ sort { $a <=> $b } @$target ]
        )
      )
    {
        return 'false';
    }

    my $iter = permutations($source);
    while ( my $perm = $iter->next ) {
        if ( compare_array( [ flatten_array($perm) ], $target ) ) {
            return 'true';
        }
    }

    return 'false';
}

Examples

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

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

$ ./ch-2.py "[[9,1], [5,8], [2]]" 5 8 2 9 1
True

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

$ ./ch-2.py "[[7,4,6]]" 7 4 6
True

(dlxxi) 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::DBBrowser - Browse SQLite/MySQL/PostgreSQL databases and their tables interactively.
    • Version: 2.436 on 2025-10-24, with 18 votes
    • Previous CPAN version: 2.435 was 9 days before
    • Author: KUERBIS
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.093001 on 2025-10-24, with 767 votes
    • Previous CPAN version: 2.093000 was before
    • Author: OLIVER
  3. Bitcoin::Crypto - Bitcoin cryptography in Perl
    • Version: 3.002 on 2025-10-24, with 13 votes
    • Previous CPAN version: 3.001 was 1 year, 29 days before
    • Author: BRTASTIC
  4. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251020.002 on 2025-10-20, with 25 votes
    • Previous CPAN version: 20251019.001 was same day
    • Author: BRIANDFOY
  5. Dancer2 - Lightweight yet powerful web application framework
    • Version: 2.0.1 on 2025-10-22, with 138 votes
    • Previous CPAN version: 2.0.0 was 1 month, 7 days before
    • Author: CROMEDOME
  6. HTTP::Message - HTTP style message (base class)
    • Version: 7.01 on 2025-10-19, with 71 votes
    • Previous CPAN version: 7.00 was 1 year, 12 days before
    • Author: OALDERS
  7. IO::Compress - IO Interface to compressed data files/buffers
    • Version: 2.214 on 2025-10-24, with 17 votes
    • Previous CPAN version: 2.213 was 1 year, 1 month, 27 days before
    • Author: PMQS
  8. LWP - The World-Wide Web library for Perl
    • Version: 6.81 on 2025-10-22, with 209 votes
    • Previous CPAN version: 6.80 was 1 month, 10 days before
    • Author: OALDERS
  9. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20251022 on 2025-10-23, with 44 votes
    • Previous CPAN version: 5.20250923 was 1 month before
    • Author: BINGOS
  10. WWW::Mechanize - Handy web browsing in a Perl object
    • Version: 2.20 on 2025-10-22, with 103 votes
    • Previous CPAN version: 2.19 was 1 year, 1 month, 6 days before
    • Author: OALDERS

When tradition meets innovation — how Perl found its place again in the age of notebooks and deep learning.

I'm running into a weird import error message while trying to create a commandline tool that references packages within a Perl web application. The web application itself is working fine. I can reproduce the issue with an MVE, but I'm mostly interested in understanding what is going on because it makes no sense to me. It's easy to "fix" this MVE by playing around with the imports but this isn't working with the real program, and I'd also prefer to avoid changing the application packages (i.e. the real AllZip.pm).

This is perl 5, version 40, subversion 1 (v5.40.1), running on Windows 11. This was locally compiled with the modules built using cpanm.

AllZip.pm

package AllZip;

use strict;
use warnings;

use IO::Uncompress::Unzip qw(unzip $UnzipError);
use Archive::Zip::SimpleZip qw($SimpleZipError);

1;

test.pl:

package test;

use strict;
use warnings;
use Carp;

use AllZip;     #Line 7

use IO::Compress::Gzip qw(:constants gzip $GzipError);      #Line 9
use IO::Compress::Zip 2.213 qw(:all);       #Line 10 (taken from Archive::Zip::SimpleZip)

print (($GzipError // '') . " is imported.\n");
print (($ZipError // '') . " is imported.\n");

Running this as-is gives the error:

"$GzipError" is not exported by the IO::Compress::Zip module
"gzip" is not exported by the IO::Compress::Zip module
Can't continue after import errors at test.pl line 10.
BEGIN failed--compilation aborted at test.pl line 10.

Which is strange, because I'm not asking for gzip or $GzipError from IO::Compress::Zip.

The print statements are just to verify that the exports are working. If I comment out line 9 I get a syntax error stating that $GzipError isn't declared, which is expected.

The error goes away if I remove line 7. Changing the order of the Zip/GZip use statements results in multiple prototype mismatch errors but otherwise runs to completion (the real program does not).

Does the prior import of IO::Compress::Gzip somehow clobber the :all keyword when IO::Compress::Zip is re-imported?


@ikegami can replicate on Linux, and widdled it down to the following:

$ perl -e'
   use IO::Compress::Zip  qw();
   use IO::Compress::Gzip qw();
   use IO::Compress::Zip  qw( :all );  # Line 4
'
"gzip" is not exported by the IO::Compress::Zip module
"$GzipError" is not exported by the IO::Compress::Zip module
Can't continue after import errors at -e line 4.
BEGIN failed--compilation aborted at -e line 4.

PWC 344, Task 2: Pick Up the Pieces

dev.to #perl

Task 2: Array Formation

The Task

You are given two lists: @source and @target.

Write a script to see if you can build the exact @target by putting these smaller lists from @source together in some order. You cannot break apart or change the order inside any of the smaller lists in @source.

Example 1:

  • Input: @source=([2,3], [1], [4]), @target=(1, 2, 3, 4)
  • Output: true
  • Use in the order: [1], [2,3], [4]

Example 2:

  • Input: @source=([1,3], [2,4]), @target=(1, 2, 3, 4)
  • Output: false

Example 3:

  • Input: @source=([9,1], [5,8], [2]), @target=(5, 8, 2, 9, 1)
  • Output: true
  • Use in the order: [5,8], [2], [9,1]

Example 4:

  • Input: @source=([1], [3]), @target=(1, 2, 3)
  • Output: false
  • Missing number: 2

Example 5:

  • Input: @source=([7,4,6]), @target=(7, 4, 6)
  • Output: true
  • Use in the order: [7, 4, 6]

The Thought Process

The musical selection for our programming journey is the funky disco-adjacent Pick Up the Pieces, by Average White Band. It was a number one hit in 1974, a time when it was still possible for an instrumental tune to make the charts. Fun personal anecdote: in my high school, the English department partnered with a local radio station (KYVA AM 1230 in Gallup, New Mexico) to put on a 15-minute show on Thursday evenings, and "Pick Up the Pieces" was our intro music.

Nostalgia aside, with a small number of lists in @source, it's tempting to just plow through all the possible combinations and see if any work, but factorial complexity is scary.

There's a little bit of ambiguity in the description. Although the examples imply it, it's not clear if we need to use all the substrings in @source, or if we can accept a solution that only uses some of them. I'm going with not necessarilly using all of the lists in @source if we don't need them.

What about reusing them? I'm going to say no to that.

The solution I lean toward is to use a stack of possibilities and backtrack if we can't satisfy the @target.

The Code

Does it blend?

Let's start with the sub-problem of checking if one of the lists in @source is a prefix of @target. I want a predicate function that answers whether a list p is a leading prefix of a list t.

sub isPrefix($p, $t)
{
    return false if @$p > @$t;
    my $match = true;
    for my ($i, $n) ( indexed $p->@* )
    {
        $match &&= ($n == $t->[$i]);
    }
    return $match;
}

Notes:

  • Our arguments are array references, so we'll be de-referencing them a lot.
  • If $p is longer than $t, then it can't possibly be a prefix.
  • Start by assuming that the answer is yes.
  • The indexed builtin in Perl is a convenient way to get variables for the index and the thing at the index in a simple syntax. Love it.
  • For each element in the prefix, $match continues to be true if the same position $t matches. We could bail from the loop as soon as $match becomes false, but with expected short lists, it might be faster to complete the loop than to insert more logic into each execution. No, I'm not going to benchmark for it.

Does it match?

On to the main event. I want to pick lists from @source that match the beginning of @target. Then, I remove that from consideration, both from @source and from the front of @target. Repeat.

If we hit a dead end, I want to be able to backtrack to an earlier point, so I'll stack my possibilities.

sub canMake($source, $target)
{
    my @stack = ( [ [ $source->@* ], [ $target->@*] ] );
    while ( @stack )
    {
        my ($s, $t) = pop(@stack)->@*;

        for my ($i, $p) (indexed $s->@* )
        {
            next unless isPrefix($p, $t);

            my @t = $t->@*;     # Make a copy of remaining target.
            splice(@t, 0, @$p); # Remove prefix from target.

            # Have we completely matched the target?
            if ( @t == 0 )
            {
                return true;
            }

            my @s = $s->@*;     # Make a copy of remaining source.
            splice(@s, $i, 1);  # Remove the segment we used.

            push @stack, [ \@s, \@t ];  # Try again with smaller sets.
        }
    }
    return false;
}

Notes:

  • Although the task description uses arrays, I'm passing in array references.
  • @stack = ( [ ..., ...] ) -- Every element of @stack is a pair: the current set of possible lists, and the current target list. The stack starts with a copy of @source and a copy of @target. There's a lot of references here, and I want to operate on copies, not accidentally change things by going through references.
  • The main loop continues as long as there are things to try on the stack. There will be at least one iteration, because we explicitly pushed one possibility.
  • Take the top thing off the stack, and assign the anonymous references to variables we can use. $s will be a reference to the possible source lists, and $t will be a reference to the remaining target list that we have to match.
  • Oh look, it's indexed again. When I want to remove a list from @source, I'll need to know its position in $s, so this is a convenient way to get it.
  • Weed out candidates that aren't prefixes of @target. Luckily we have that isPrefix function. If none of the remaining lists match $t, then we'll backtrack to whatever was on the stack.
  • If we have a working prefix, we'll want to reduce our data. Make copies, and remove the matching pieces.
  • There are two uses of splice: one to chop off the prefix of $t, and one to surgically remove one element out of $s. It amazes and depresses me that after all these years, I still have to re-read the documentation for splice to remind myself of the order of arguments and what gets returned.
  • If we've whittled $t down to nothing, success! At this point, if we wanted to enforce the requirement to use all of @source, we could also check that the size of $s is down to 1 (not zero, because we haven't cleaned it up yet).
  • Note here that if we wanted to allow reuse of the lists in @source, we could do it by not removing the chosen prefix at this point.
  • Now we're down to a smaller set of possibilities. Push that checkpoint to the top of the stack and continue.
  • If we ever get out of this loop, it means that we never got @target down to zero, so that's a "no" from me, dawg.

We've seen cases where installing a perl module via cpanm fails silently to actually install the module. This is occurring on Debian 12.

For example:

cpanm --installdeps --notest Unicode::Lite

completes without error. But use of this module in a perl script fails due to it not being installed (in any of the standard system/library locations).

If we cd to the appropriate .cpanm directory and run

gmake

gmake install

the modules installs and is useable.

cpanm is executed as the root user. What are we missing?

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

  1. App::DBBrowser - Browse SQLite/MySQL/PostgreSQL databases and their tables interactively.
    • Version: 2.435 on 2025-10-14, with 18 votes
    • Previous CPAN version: 2.434 was 9 days before
    • Author: KUERBIS
  2. App::rdapper - a command-line RDAP client.
    • Version: 1.20 on 2025-10-14, with 21 votes
    • Previous CPAN version: 1.19 was 1 month, 13 days before
    • Author: GBROWN
  3. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251018.003 on 2025-10-19, with 25 votes
    • Previous CPAN version: 20251017.001 was 1 day before
    • Author: BRIANDFOY
  4. Cucumber::TagExpressions - A library for parsing and evaluating cucumber tag expressions (filters)
    • Version: 8.0.0 on 2025-10-14, with 16 votes
    • Previous CPAN version: 6.2.0 was 4 months, 20 days before
    • Author: CUKEBOT
  5. Data::ObjectDriver - Simple, transparent data interface, with caching
    • Version: 0.26 on 2025-10-17, with 16 votes
    • Previous CPAN version: 0.25 was 6 months, 1 day before
    • Author: SIXAPART
  6. Finance::Quote - Get stock and mutual fund quotes from various exchanges
    • Version: 1.67 on 2025-10-18, with 143 votes
    • Previous CPAN version: 1.66_02 was 1 month, 17 days before
    • Author: BPSCHUCK
  7. Google::Ads::GoogleAds::Client - Google Ads API Client Library for Perl
    • Version: v29.0.1 on 2025-10-16, with 20 votes
    • Previous CPAN version: v29.0.0 was 1 day before
    • Author: CHEVALIER
  8. JSON::Schema::Modern - Validate data against a schema using a JSON Schema
    • Version: 0.620 on 2025-10-15, with 12 votes
    • Previous CPAN version: 0.619 was 17 days before
    • Author: ETHER
  9. SPVM - The SPVM Language
    • Version: 0.990105 on 2025-10-16, with 36 votes
    • Previous CPAN version: 0.990104 was 1 day before
    • Author: KIMOTO
  10. Term::Choose - Choose items from a list interactively.
    • Version: 1.777 on 2025-10-15, with 15 votes
    • Previous CPAN version: 1.776 was 18 days before
    • Author: KUERBIS
  11. Time::Piece - Object Oriented time objects
    • Version: 1.38 on 2025-10-18, with 64 votes
    • Previous CPAN version: 1.3701 was 1 month, 23 days before
    • Author: ESAYM
  12. Type::Tiny - tiny, yet Moo(se)-compatible type constraint
    • Version: 2.008004 on 2025-10-17, with 145 votes
    • Previous CPAN version: 2.008003 was 1 month, 15 days before
    • Author: TOBYINK

(dcxvii) metacpan weekly report - DBD::DuckDB

Niceperl

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

Week's winner: DBD::DuckDB (+3)

Build date: 2025/10/19 06:44:20 GMT


Clicked for first time:


Increasing its reputation:

Rewriting a script for the Homebrew package manager taught me how the Go programming language’s design choices align with platform-ready…

Clipadd Cookbook

Perlancar

(A version of this article also appears as App::ClipboardUtils::Manual::HowTo::ClipaddCookbook on CPAN.)

Introduction

clipadd, a CLI included in the App::ClipboardUtils distribution, lets you add items to the desktop clipboard. It is clipboard-manager-agnostic, supporting backends like xclip and Klipper. It also has some convenient features which will be demonstrated in this document.

Adding multiple entries from a text file

% clipadd --split-by '\n---\n' < FILENAME

For example, after adding FAQ entries from this text file:

Question 1
Answer 1
---
Question 2
Answer 2
---
Question 3
Answer 3

then you can setup keyboard shortcuts like Ctrl-Alt-Up and Ctrl-Alt-Down in Klipper to quickly access those FAQ entries to provide quick answers in chats.

Adding ouput from command-line, one line at a time

% clipadd -c COMMAND
% clipadd -c COMMAND -t ; # to see the output on stdout as well

This is convenient because it lets you feed input to a command interactively and immediately get the output as clipboard content.

For example, using with safer:

% clipadd -c safer -t
Foo Bar, Inc.
foo-bar-inc
_

I can paste company names and get a slug name to use in file manager to create directory, etc.

Adding text fragments from a text file as clipboard contents

% clipadd --fragments < FILENAME

This is a variation of the previous recipe. Using fragments allows you to only add certain entries and in custom order. Example content of text file:

FAQS
====

Question 1
# BEGIN clipadd id=2
Answer 1
# END clipadd id=2

Question 2
# BEGIN clipadd id=1
Answer 2
# END clipadd id=1

Question 3
# BEGIN clipadd id=3
Answer 3
# END clipadd id=3

Question 4
Answer 4

See Also

clipadd (a.k.a. add-clipboard-content, a.k.a. ca).

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::Cmd - write command line apps with less suffering
    • Version: 0.338 on 2025-10-03, with 49 votes
    • Previous CPAN version: 0.337 was 9 months, 3 days before
    • Author: RJBS
  2. App::DBBrowser - Browse SQLite/MySQL/PostgreSQL databases and their tables interactively.
    • Version: 2.434 on 2025-10-05, with 17 votes
    • Previous CPAN version: 2.433 was 6 days before
    • Author: KUERBIS
  3. App::MHFS - A Media HTTP File Server. Stream your own music and video library via your browser and standard media players.
    • Version: v0.7.0 on 2025-10-07, with 14 votes
    • Previous CPAN version: v0.6.0 was 11 months, 16 days before
    • Author: GAHAYES
  4. App::Netdisco - An open source web-based network management tool.
    • Version: 2.091001 on 2025-10-09, with 762 votes
    • Previous CPAN version: 2.091000 was 8 days before
    • Author: OLIVER
  5. App::Sqitch - Sensible database change management
    • Version: v1.6.0 on 2025-10-06, with 3041 votes
    • Previous CPAN version: v1.5.2 was 5 months, 6 days before
    • Author: DWHEELER
  6. CGI - Handle Common Gateway Interface requests and responses
    • Version: 4.71 on 2025-10-01, with 46 votes
    • Previous CPAN version: 4.70 was 2 months, 24 days before
    • Author: LEEJO
  7. CPANSA::DB - the CPAN Security Advisory data as a Perl data structure, mostly for CPAN::Audit
    • Version: 20251003.001 on 2025-10-03, with 25 votes
    • Previous CPAN version: 20250807.001 was 1 month, 27 days before
    • Author: BRIANDFOY
  8. DateTime::Format::Natural - Parse informal natural language date/time strings
    • Version: 1.22 on 2025-10-01, with 18 votes
    • Previous CPAN version: 1.21_01 was 1 month, 12 days before
    • Author: SCHUBIGER
  9. Imager - Perl extension for Generating 24 bit Images
    • Version: 1.029 on 2025-10-06, with 68 votes
    • Previous CPAN version: 1.028 was 3 months, 19 days before
    • Author: TONYC
  10. Mojolicious - Real-time web framework
    • Version: 9.42 on 2025-10-01, with 507 votes
    • Previous CPAN version: 9.41 was 2 months, 29 days before
    • Author: SRI
  11. Selenium::Remote::Driver - Perl Client for Selenium Remote Driver
    • Version: 1.50 on 2025-10-06, with 49 votes
    • Previous CPAN version: 1.49 was 2 years, 6 months before
    • Author: TEODESIAN
  12. Specio - Type constraints and coercions for Perl
    • Version: 0.53 on 2025-10-04, with 12 votes
    • Previous CPAN version: 0.52 was 1 month, 26 days before
    • Author: DROLSKY
  13. SPVM - The SPVM Language
    • Version: 0.990102 on 2025-10-10, with 36 votes
    • Previous CPAN version: 0.990101 was before
    • Author: KIMOTO
  14. WWW::Mechanize::Chrome - automate the Chrome browser
    • Version: 0.74 on 2025-10-06, with 22 votes
    • Previous CPAN version: 0.73 was 1 year, 6 months, 7 days before
    • Author: CORION
  15. YAML::Syck - Fast, lightweight YAML loader and dumper
    • Version: 1.36 on 2025-10-10, with 18 votes
    • Previous CPAN version: 1.35 was before
    • Author: TODDR

Episode 6 - CPAN Testers

The Underbar
During the Perl Toolchain Summit 2025 in Leipzig, we interviewed the CPAN Testers team. They told us about the history of the project, its recent problems, and how a new team formed around its (then) lone maintainer. They also told us about their plans for the future.

Dave writes:

Last month I completed rewriting and modernising perlxs.pod, Perl's reference manual for XS. It's now sitting as PR #23795, and will hopefully get merged before too long. (I actually completed the work two days into October, so next month's report will show a few hours.)

From the PR's description:

This branch completely rewrites and modernises the XS reference manual, perlxs.pod.

The new file is about twice the size of the old one.

This branch:

  • deletes some obsolete sections;
  • reorders the existing sections into a more logical order;
  • adds a large new introductory/overview part, which explains all the background needed to understand what XSUBs do, including SVs, the stack, reference counts, magic etc.
  • includes a BNF syntax section
  • modernises: e.g. it uses ANSI parameter syntax throughout
  • has a fully-worked example using T_PTROBJ

SUMMARY:

  • 23:19 modernise perlxs.pod
  • 3:50 rationalise XS typemap file search order

    Total:

    • 27:09 (HH::MM)

Tony writes: ``` [Hours] [Activity] 2025/09/01 Monday 0.48 #23641 testing, comment 0.77 #23659 review and comment 0.20 #23659 review updates and comment 0.83 reply DB.pm discussion 0.25 #23648 try to reproduce and comment

0.47 #23659 review and approve

3.00

2025/09/02 Tuesday 0.60 #23627 follow-up, review and comment 0.53 #23616 research and comment 0.23 #23669 review, look for a similar test, comment 0.43 #23641 testing, follow-up 0.32 #23648 follow-up 0.32 #23667 review, comment 0.57 #23668 review, testing, comment and approve

0.85 #13307/#23661 testing, comment on both

3.85

2025/09/03 Wednesday 0.12 #23668 review updates and reapprove 0.57 #23661 review discussion and consider, request changes 0.18 #23616 review and approve 0.33 #23627 review updates and approve

0.62 #23669 testing and comments

1.82

2025/09/04 Thursday 0.15 #23661 review changes, test results and comment 1.07 #23573 testing, approve with comment 0.13 #23669 review updates and approve 0.52 #23641 review, research and comment 0.15 #23638 check latest changes and approve 0.37 #23680 review and approve 0.17 #23680 review updates and still approved 0.18 #23682 review, check test failures and comment

0.33 #23679 review

3.07

2025/09/05 Friday

0.42 #23680 follow-up

0.42

2025/09/08 Monday 1.07 #23641 review, research, comments 0.08 #23670 review and approve 0.55 #23671 review, research and approve with comment 0.08 #23672 review and approve 0.18 #23678 review and comment 0.22 #23683 review and comment

2.62 test_pl.pod - make a start

4.80

2025/09/09 Tuesday 0.82 #23679 review and comment 1.48 test_pl.pod - more

1.78 test_pl.pod - more

4.08

2025/09/10 Wednesday 1.30 #23690 review, testing and comment 0.15 #23691 review and approve 0.70 #23694 review and approve

1.42 test_pl.pod - mostly done, needs review

3.57

2025/09/11 Thursday 0.48 #23695 review and comment 0.12 #23696 review and approve 0.10 #23697 review and approve 1.48 #23698 review and comments

1.38 test_pl.pod, add and test example, make PR 23700

3.56

2025/09/15 Monday 0.25 #23700 follow-up 1.57 #23690 review updates, testing, research and comment 0.32 #23695 review updates and approve 1.00 #23641 testing, research and comment

0.92 test_pl.pod - some missing stuff, don’t talk about TAP

4.06

2025/09/16 Tuesday 0.42 #23698 review updated PR and approve 0.73 test_pl.pod - minor fixes, add to podcheck 0.28 #23678 review and comment 0.80 #23702 review

0.92 #23702 try to understand line-breaking

3.15

2025/09/17 Wednesday 0.17 #23702 comment 1.50 #23678 try to understand the threads watchdog 1.00 #23678 debugging, testing and comment

0.65 #23715 review and comments

3.32

2025/09/18 Thursday 0.12 #23717 review and approve 0.27 #23718 review and approve 0.42 #23719 review and approve 0.32 #23720 review, research and comment 0.17 #23721 review and approve 0.52 #23714 review, research and comment 0.42 #23720 research and follow-up

1.48 test.pl/test-dist-modules.pl clean up, testing, fixes

3.72

2025/09/22 Monday 0.42 #23720 review updates and approve 0.22 #23714 comment 0.63 #23747 review and comment 0.58 #23731 review and comment 0.52 #23730 review, research and comment 0.72 #23728 review, research and comments 0.12 #23734 review and approve 0.13 #23735 review and approve 0.15 #23736 review and approve with comment 0.33 #23742 review and approve 0.42 #23743 review and approve 0.13 #23749 review and approve

0.12 #23746 review and approve

4.49

2025/09/23 Tuesday 0.70 #23731 review updates and approve 0.25 #23752 review and comment 0.32 #23754 review and approve 0.22 #23747 review update and approve 0.17 #23725 review and briefly comment

0.27 #23752 review update and comment

1.93

2025/09/24 Wednesday 0.82 #23710 review and approve 0.25 #23076 review discussion and change and approve 0.83 #23761 review, research and approve 1.22 #23753 look into CI failure, testing, fixes start a full test 0.28 #23753 clean up and push to PR for CI

0.37 #23757 review and approve

3.77

2025/09/25 Thursday 0.60 github notifications 0.23 #23753 comment and approve 1.05 #23759 review, check cpan, testing, approve with comment 0.17 #23763 review and comment 0.08 #23765 review and approve 0.08 #23766 review and approve 0.08 #23767 review and comment 0.82 #21877 write tests, work on re-work

0.45 #21877 more re-work

3.56

2025/09/29 Monday

3.27 #23641 review, testing

3.27

2025/09/30 Tuesday 1.28 #23782 review and comments 0.35 #23779 review and approve

0.63 #23641 more testing and comment

2.26

Which I calculate is 61.7 hours.

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


Paul writes:

This month I spent mostly tidying up various bits of fallout from last month's OP_MULTIPARAM work towards signatures, and also got the named parameters branch (just-about) ready for review and merge, along with a few other bugfixes.

  • 1 = BBC ticket meta
    • https://github.com/Perl/perl5/issues/23675
  • 2 = Bugfix parse_subsignature() on empty parens
    • https://github.com/Perl/perl5/issues/17689
  • 2 = BBC ticket XS-Parse-Sublike
    • https://github.com/Perl/perl5/issues/23674
  • 5.5 = Improvements to B::Deparse of on signatures
    • https://github.com/Perl/perl5/issues/23699
    • https://github.com/Perl/perl5/pull/23710
  • 1 = BBC ticket Syntax-Keyword-MultiSub
    • https://github.com/Perl/perl5/issues/23712
  • 1 = BBC ticket Future-AsyncAwait
    • https://github.com/Perl/perl5/issues/23711
  • 1 = Continue work on signature-named-params branch
    • https://github.com/leonerd/perl5/tree/signature-named-parameters
  • 4 = COP warnings API additions
    • https://github.com/Perl/perl5/pull/23731
  • 1 = BBC ticket Syntax-Keyword-Try
    • https://github.com/Perl/perl5/issues/23609
  • 1 = Bugfix module ends in ADJUST block
    • https://github.com/Perl/perl5/issues/23758
  • 2 = Modernize attributes.pm to use v5.40
    • https://github.com/Perl/perl5/pull/23769
  • 2 = Bugfix fieldinfo during thread cloning
    • https://github.com/Perl/perl5/issues/23771
  • 1 = Other github code reviews

Total: 24.5 hours

• Analyze existing Perl scripts and understand their functionality
• Convert Perl scripts to Python while maintaining performance and functionality
• Debug and optimize converted Python scripts
• Collaborate with team members to meet project requirements
• Document the conversion process and provide knowledge transfer
________________________________________
Technical Skills:
Perl (5+ years):
• Strong understanding of Perl syntax, modules, and libraries
• Experience with regular expressions, file handling, and data manipulation
• Familiarity with legacy Perl scripts and debugging
Python (2+ years):
• Strong understanding of Python syntax, libraries, and frameworks
• Experience with Python’s re module, file handling, and data manipulation
• Knowledge of Python best practices (PEP 8 standards)
Code Conversion:
• Hands-on experience converting Perl scripts to Python
• Ability to map Perl constructs (scalars, arrays, hashes) to Python equivalents (variables, lists, dictionaries)
• Understanding of differences in error handling, string manipulation, and OOP between Perl and Python
________________________________________
Soft Skills:
• Analytical Thinking: Ability to understand complex Perl scripts before conversion
• Attention to Detail: Ensure converted Python scripts maintain original functionality
• Communication: Document and explain conversion process to stakeholders
• Collaboration: Work closely with developers, testers, and stakeholders

For quite some I wanted to write a small static image gallery so I can share my pictures with friends and family. Of course there are a gazillion tools like this, but, well, sometimes I just want to roll my own.

I took the opportunity during our stay in Schwaz to take a few hours and hack together snig, the (small | static | simple | stupid | ...) image gallery. Here you can see the example gallery (showing some of the pictures I took in Schwaz).

I used the old, well tested technique I call brain coding0, where you start with an empty vim buffer and type some code (Perl, HTML, CSS) until you're happy with the result. It helps to think a bit (aka use your brain) during this process.

According to my timetracker I spend 8h 15min (probably half of it spend fiddling with CSS...).

Installation

I used the new Perl class feature, so you'll need at least Perl 5.40 which was released last year and is included in current Debian.

I prefer cpm to install CPAN modules:

cpm install -g Snig

I haven't provided a Containerfile yet, but if somebody is interested, drop me a line.

You can get the raw source code from Source Hut (as I don't want to support the big LLM vacuum machines formerly known as Git(Hub|Lab)).

Example usage

You need a folder filled with images (eg some-pictures) and some place where you can host a folder and a bunch of HTML files.

ls -la some-pictures/
7156 -rw------- 1 domm domm 7322112 Oct  6 09:14 P1370198.JPG
7188 -rw------- 1 domm domm 7354880 Oct  6 09:14 P1370208.JPG
7204 -rw------- 1 domm domm 7369728 Oct  6 09:14 P1370257.JPG

Then you do

snig.pl --input some-pictures --output /var/web/my-server-net/gallery/2025-10-some-pictures --name "Some nice pictures"

This will:

  • find all jpgs in the folder some-pictures
  • copy them into the output folder
  • generate a thumbnail (for use in the list)
  • generate a preview (for use in the detail page)
  • generate a HTML overview page
  • generate a HTML detail page for each image, linked to the next/prev image
  • generate a zip archive of the images
  • EXIF rotation hints are used to properly orient the previews
  • images are sorted by the EXIF timestamp (per default, you could also use mtime)
ls -la /var/web/my-server-net/gallery/2025-10-some-pictures
-rw-rw-r-- 1 domm domm      1370 Sep 26 21:15 20250914_p1370198.html
-rw-rw-r-- 1 domm domm      1370 Sep 26 21:15 20250914_p1370208.html
-rw-rw-r-- 1 domm domm      1370 Sep 26 21:15 20250915_p1370253.html
-rw-rw-r-- 1 domm domm 171738640 Sep 26 21:12 2025-10-some-pictures.zip
-rw-rw-r-- 1 domm domm      3977 Sep 26 21:15 index.html
-rw-rw-r-- 1 domm domm   7322112 Sep 26 21:12 orig_20250914_P1370198.JPG
-rw-rw-r-- 1 domm domm   7354880 Sep 26 21:12 orig_20250914_P1370208.JPG
-rw-rw-r-- 1 domm domm   7686656 Sep 26 21:12 orig_20250915_P1370253.JPG
-rw-rw-r-- 1 domm domm    106382 Sep 26 21:12 preview_20250914_P1370198.JPG
-rw-rw-r-- 1 domm domm    170346 Sep 26 21:12 preview_20250914_P1370208.JPG
-rw-rw-r-- 1 domm domm    133342 Sep 26 21:12 preview_20250915_P1370253.JPG
-rw-rw-r-- 1 domm domm      1434 Sep 26 21:15 snig.css
-rw-rw-r-- 1 domm domm      5128 Sep 26 21:12 thumbnail_20250914_P1370198.JPG
-rw-rw-r-- 1 domm domm      9495 Sep 26 21:12 thumbnail_20250914_P1370208.JPG
-rw-rw-r-- 1 domm domm      6408 Sep 26 21:12 thumbnail_20250915_P1370253.JPG

You can then take the output folder and rsync it onto a static file server. Or install snig on your web server and do the conversion there..

Again, take a look at the example gallery.

Limitations

For now, snig is very simple and stupid, so quite a few things are still hard coded (like copyright and license). If somebody else wants to use it, I will add some more command line flags and/or a config file. But for now this is not needed, so I did not add it.

Have fun

I had quite some fun hacking snig and also used it as an opportunity to learn the new class syntax (and fresh up on subroutine / method signatures). So not only did I use my brain, I actually learned something new!

Please feel free to give snig a try. Or just use one of the countless other static image gallery generators. Or just write your own!

lobste.rs, hacker news, reddit

Footnotes

0 As opposed to vibe coding.