perl -s switch documentation confusion

Perl questions on StackOverflow

Published by Martian2020 on Monday 25 September 2023 00:41

Examples on stackoverflow involving -s switch (e.g. give position of -- like:

perl -s -e 'if ($xyz) { print "$xyz\n" }' -- -xyz

perldoc perlrun:

-s   enables rudimentary switch parsing for switches on the command line
     after the program name but before any filename arguments (or before
     an argument of --). Any switch found there is removed from @ARGV
     and sets the corresponding variable in the Perl program. The
     following program prints "1" if the program is invoked with a -xyz
     switch, and "abc" if it is invoked with -xyz=abc.

         #!/usr/bin/perl -s
         if ($xyz) { print "$xyz\n" }

I'm confused with "before an argument of --", because example above works, -xyz is after --. If written as in docs:

perl -xyz -- -s -e 'if ($xyz) { print "$xyz\n" }' 
Can't open perl script "-s": No such file or directory

Per my understanding how it works I want to write in doc:

after the program name (or after an argument of --) but before any filename arguments

Is my change correct? Maybe sometime before syntax of perlrun was indeed as described in docs but was changed later but docs were updated to reflect that?

Edit 2:

After reading all the answers:

after the program name (or after first occurrence of an argument of -- if the program is specified via -e or -E switches) but before any filename arguments (or before --, first occurrence in case of program name and second in case of the program specified via -e or -E switches)


In response to am answer by zdin (note: I have not found definition of option, switch; seems those are synonyms and both are used as both bash command line arguments and in perl program on shebang line arguments).

echo a-a-a > 1.txt

#!/usr/bin/perl -sp
if ($xyz) { print "$xyz\n" }

#!/usr/bin/perl -s
if ($xyz) { print "$xyz\n" }

I can call *.pl passing 1.txt as argument w/out --:

./ -xyz=a 1.txt 

perl -p ./ -xyz=a 1.txt 


perl -spe 's/a/b/;if ($xyz) { print "$xyz\n" }' -- -xyz=a 1.txt

That shows my reformulation is valid for both running via program name and one-liners.


perl --version

This is perl 5, version 34, subversion 0 (v5.34.0) built for x86_64-linux-gnu-thread-multi

How to composite watermark with Perlmagick?

Perl questions on StackOverflow

Published by w.k on Monday 25 September 2023 00:34

I wrote a script to watermark images. On command line adding watermark works fine:

composite -dissolve 5% -gravity South watermark.png original.jpg new.jpg

Now when I tried to use Perlmagick for watermarking, the composite part does not change anything:

my $i = new Image::Magick;
my $watermark = $i->Read( "watermark.png" );

my $i2 = new Image::Magick;
my $p = $i->Read( "original.jpg" );

$i->Set( Gravity => 'Center' );
$i->Resize( geometry => "600x600" );
$i->Composite( image=>$watermark, compose=>"Dissolve", opacity=>5, gravity=>"South" );

$i->Write( 'jpg:temp_file' );

Such script resizes image, but does not watermark it.

Problem seems to be in the way I provide dissolving degree. On command line I can add percentage to dissolve-attribute, but in API version dissolve is itself attribute. I tried with opacity, but this seems not the right way too.

What is the right way to use dissolve in Perlmagick?

Revert "[perl #89544] Non-eval closures don’t need CvOUTSIDE"

But they do need CvOUTSIDE() for eval-in-package-DB's scope
magic to work correctly.

This also incidentally fixes a TODO Deparse, since the CvOUTSIDE
is now available

Fixes #19370 aka rt89544

This breaks #11286, but I don't think that's fixable without breaking
eval-in-DB's special scope behaviour.

This reverts (most of) commit a0d2bbd5c47035a4f7369e4fddd46b502764d86e.

add TODO tests for 19370

Perl commits on GitHub

Published by tonycoz on Monday 25 September 2023 00:24

add TODO tests for 19370
feature: document feature bundle ':all' and why you don't use it

Fixes #17209
regcomp_debug.c: change a mis-use of ASSUME() to STATIC_ASSERT_STMT()

As mauke points out in #21490 the compiler "knows" all of the
constants here at compile-time, so the ASSUME()s here do nothing.

I suspect the intent here was to ensure that we never overflow the
capacity of the flags parameter, which we can check at compile-time

mauke also suggested using CHAR_BIT instead of 8, but Configure
probes for CHARBITS and the perl core generally uses CHARBITS,
so use that here too.
regdump_intflags: there is no  PL_reg_intflags_name[REG_INTFLAGS_NAME_SIZE]

Yes, this is an old report, from 2014.


I am stuck while running the project which has been created on Perl with Mojolicious module. here is the code of the file from where I am running the project using morbo command

   #!/usr/bin/env perl
    use strict;
    use warnings;
    use FindBin;
    BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
    use Mojolicious::Commands;
    # Start command line interface for application

All modules has been installed successfully and trying to run the project using morbo command. I am getting the error while running the project. Not sure why even each module and files are there. also file is there in the specified path.

Please help me to run this project. The project is in Perl and ep templates for CPAN. Please confirm what I am missing to run the project.

Adding and removing integers #perl

Published by Simon Green on Sunday 24 September 2023 10:06

Weekly Challenge 235

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: Remove One


You are given an array of integers.

Write a script to find out if removing ONLY one integer makes it strictly increasing order.

My solution

When I first read the challenge (which I do on public transport on Monday evenings usually), the approach I was going to take was to remove one item at a time and check if the list is in increasing order.

Then I thought I would be cleaver and wrote code that counted the number of times a value was lower than the previous value. This would provide the correct results for the three examples. If that occurred more than once, then it is false.

However when I started writing this blog post, I realized a floor in my logic. Taking the sequence '8, 9, 1, 2, 3' would have returned true even though you couldn't remove a single value to make an incremental list.

My second attempt was to loop through the list once and see how many times the value is less than the current maximum. If this occurs more than once, it means there is no solution. However, this would fail for the list '8, 1, 2, 3' where it would return false when you could remove the 8 to pass the test.

So in the end, I went back to the original plan. Remove one number from the list, check if it is incrementing. Print true if it, print false if we exhaust all tests.

My final code looks like this

# Loop through each position of the list
for i in range(len(ints)):
    # Make a new list with the integer at that position remove
    new_list = ints.copy()
    del new_list[i]

    # Check if the list is incremental
    if all(new_list[j-1] <= new_list[j] for j in range(1, len(new_list))):
        # It is, tell the user about it

# Oh dear. No solution is possible

Had this being done in the real world, this is where I would talk with colleagues to figure out if this can be optimized more.


$ ./ 0 2 9 4 6

$ ./ 5 1 3 2

$ ./ 2 2 3

Task 2: Duplicate Zeros


You are given an array of integers.

Write a script to duplicate each occurrence of ZERO in the given array and shift the remaining to the right but make sure the size of array remain the same.

My solution

After the previous task, this should be easier. It also shows up short comings of my Python knowledge compared to Perl. So lets start with the Perl solution as it's straight forward. Generate a new list using the map function, and then use the splice function to truncate it.

my @solution = map { $_ ? $_ : ( 0, 0 ) } @ints;
splice( @solution, scalar(@ints) );

The Python solution does the same, but is a little more verbose. There is probably a way to do this more efficiently. After writing this blog post, I'll look at other peoples solutions.

for i in ints:
    # Add the original number
    if i == 0:
        # Add it twice if it is zero

solution = solution[:len(ints)]


$ ./ 1 0 2 3 0 4 5 0
1, 0, 0, 2, 3, 0, 0, 4

$ ./ 1 2 3
1, 2, 3

$ ./ 0 3 0 4 5
0, 0, 3, 0, 0

Is there a way to make auto-encoding file handles use specified Encode flags?

Specifically I want to make STDOUT and STDERR use the Encode::FB_PERLQQ flag so any characters which can not be encoded are output as \x{ABCD} instead of garbage + a nasty warning message.

More specifically, I want to use open ':locale' to auto-detect whatever encoding the environment expects, and modify STDOUT & STDERR to use that encoding but with the flag Encode::FB_PERLQQ in effect. I imagine doing something like

use open ':locale';  # determine what the environment expects
my @layers = PerlIO::get_layers(*STDOUT);
my ($encoding) = ("@layers" =~ /encoding\((.*?)\)/);
binmode(*STDOUT, "something which means $encoding with flags Encode::FB_PERLQQ")

My application is Perl module test cases, which are automatically run on many smoker machines all over the internet, including some Windows hosts using the cp850 character set. If I just make test scripts encode to UTF-8 then on those machines some characters appear as garbage; I would rather see the \x{...} fallback enabled by FB_PERLQQ so the code-point could be determined from the logs.

How can I get perl's strict warnings to recognize switches?

Perl questions on StackOverflow

Published by mikeLundquist on Saturday 23 September 2023 20:39

I have this perl script that uses switches and strict warnings.

#! /usr/bin/perl -s
use strict;
$some = $some . " more";
print "got $some\n";

When I run it at the command line I get these errors.

$ ./ -some=SOME
Variable "$some" is not imported at ./ line 3.
Variable "$some" is not imported at ./ line 3.
Variable "$some" is not imported at ./ line 4.
Global symbol "$some" requires explicit package name (did you forget to declare "my $some"?) at ./ line 3.
Global symbol "$some" requires explicit package name (did you forget to declare "my $some"?) at ./ line 3.
Global symbol "$some" requires explicit package name (did you forget to declare "my $some"?) at ./ line 4.
Execution of ./ aborted due to compilation errors.

What can I do to get perl to recognize that $some is defined because it's passed as a switch?

(cdlxii) 12 great CPAN modules released last week


Published by /u/niceperl on Saturday 23 September 2023 20:22

(cdlxii) 12 great CPAN modules released last week


Published by Unknown on Saturday 23 September 2023 22:21

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.341 on 2023-09-20, with 13 votes
    • Previous CPAN version: 2.340 was 25 days before
    • Author: KUERBIS
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.066000 on 2023-09-19, with 15 votes
    • Previous CPAN version: 2.065002 was 16 days before
    • Author: OLIVER
  3. DBD::SQLite - Self Contained SQLite RDBMS in a DBI Driver
    • Version: 1.74 on 2023-09-19, with 101 votes
    • Previous CPAN version: 1.72 was 10 months, 16 days before
    • Author: ISHIGAKI
  4. Math::BigInt - Pure Perl module to test Math::BigInt with scalars
    • Version: 1.999841 on 2023-09-22, with 12 votes
    • Previous CPAN version: 1.999839 was 2 months, 8 days before
    • Author: PJACKLAM
  5. Minion::Backend::mysql - MySQL backend
    • Version: 1.003 on 2023-09-21, with 13 votes
    • Previous CPAN version: 1.002 was 10 days before
    • Author: PREACTION
  6. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20230920 on 2023-09-20, with 43 votes
    • Previous CPAN version: 5.20230820 was 1 month before
    • Author: BINGOS
  7. Net::Curl - Perl interface for libcurl
    • Version: 0.55 on 2023-09-20, with 17 votes
    • Previous CPAN version: 0.54 was 3 months, 4 days before
    • Author: SYP
  8. Object::Pad - a simple syntax for lexical field-based objects
    • Version: 0.803 on 2023-09-20, with 41 votes
    • Previous CPAN version: 0.802 was 29 days before
    • Author: PEVANS
  9. PerlPowerTools - BSD utilities written in pure Perl
    • Version: 1.039 on 2023-09-22, with 37 votes
    • Previous CPAN version: 1.038 was 26 days before
    • Author: BDFOY
  10. PPI - Parse, Analyze and Manipulate Perl (without perl)
    • Version: 1.277 on 2023-09-22, with 57 votes
    • Previous CPAN version: 1.276 was 1 year, 2 months, 3 days before
    • Author: MITHALDU
  11. SPVM - SPVM Language
    • Version: 0.989044 on 2023-09-20, with 31 votes
    • Previous CPAN version: 0.989042 was 6 days before
    • Author: KIMOTO
  12. Text::CSV_XS - Comma-Separated Values manipulation routines
    • Version: 1.52 on 2023-09-21, with 99 votes
    • Previous CPAN version: 1.51 was 1 month, 14 days before
    • Author: HMBRAND

(dlxvii) metacpan weekly report - Mojo::IOLoop::ReadWriteProcess


Published by Unknown on Saturday 23 September 2023 22:13

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

Week's winner: Mojo::IOLoop::ReadWriteProcess (+3)

Build date: 2023/09/23 20:12:50 GMT

Clicked for first time:

Increasing its reputation:

(dxcv) stackoverflow perl report


Published by Unknown on Saturday 23 September 2023 22:12

These are the five most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2023-09-23 20:11:27 GMT

  1. Return to old behavior for Perl hash randomization - [3/2]
  2. Performance of deep recursion versus tail recursion - [3/0]
  3. How to skip the rest in perl as next in awk? - [2/3]
  4. Perl to set/reset 8th bit on string - [2/2]
  5. Get "Inappropriate ioctl for device" when using Perl - [2/2]

This week in PSC (116)

Published by Perl Steering Council on Saturday 23 September 2023 20:06

There were only two of us this week, and the list is still a bit quiet.

The main topic was stalled PPC work: we have a few PPCs that have been approved and are in the “Implementing” state, but still waiting for an implementor. We’ll send a separate email asking for volunteers on those.

This week in PSC (117)

Published by Perl Steering Council on Saturday 23 September 2023 19:59

Two of us again, here's the summary of our meeting:

  • While implementing PPC 0013, it turned out it was vague in some places, so further discussions and refinements to the PPC document are needed
  • POD extensions - do we keep stealing features from Markdown (like tables, images, language markers)? Do we switch to Markdown? Neither are easy.
  • We’ve disabled the Wiki and enabled Issues on the PPCs repository, to better separate discussions on the form and substance of PPCs
  • PPC 0022 will soon be merged, and moved to “Exploratory” status

From Perl to Rust


Published by /u/ReplacementSlight413 on Saturday 23 September 2023 17:26

A Rust friend is attempting to convert me through this tutorial

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

Ouch! When the small mistakes bite...


Published by /u/singe on Saturday 23 September 2023 16:47

Here's an example of a small error that bit me surprisingly hard recently.

I like to construct print messages. I like a robust approach, so I do like one way that Python handles printing (e.g. print("{}".format(val)) )

I recently made a small mistake in a "say" statement:

say __LINE__. " Current symbols: ". scalar(@$arf)." ==> ".. join(" ;; ", @$arf); 

The code compiles. The Perl checker (-c) didn't catch the error and I was (probably) too tired to see it right away.

Now I'm going to add a check for ".." in my custom syntax checker. ^_^

Here's an old post about a print statement with placeholders. Look at the lovely hack offered by u/tobotic. (Some commenters threw some scorn my way. Yay gnarly programmers. ^_^ )

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

Perl Weekly Challenge #235 - Splicing and Dicing

Published by oldtechaa on Saturday 23 September 2023 05:19

Hi everybody, we've got another two challenges this week, so let's dive into them!

Remove One

The goal is to see if there's any one number that can be removed to make the set sorted in increasing order. Here's the code:

use v5.36;

my $success = 0;
REMOVAL: for my $removal (0 .. $#ARGV) {
    my @modified = @ARGV;
    splice(@modified, $removal, 1);
    for my $scan (1 .. $#modified) {
        if($modified[$scan] <= $modified[$scan - 1]) {
            next REMOVAL;
    $success = 1;

say ($success ? 'true' : 'false');

We have a labelled outer loop for the numbers we choose to remove. $removal is set to the index of each number we attempt to remove, then we copy the array, remove that number, and scan the result to make sure they all are increasing. If they don't, we skip this number and move on.

If we succeed, we set our flag and exit the loops and print the result.

Duplicate Ones

The next one is an array shifting challenge. We want to insert a duplicate of each 0, shifting everything to the right, and popping off the list to keep the length the same.

Here's the code:

use v5.36;

my @ints = @ARGV;
for(my $i = 0; $i <= $#ints; $i++) {
    if($ints[$i] == 0) {
        splice(@ints, $i, 0, 0);

say('(', join(', ', @ints), ')');

This one's also really quite simple. We scan the array, use splice to insert a 0, pop the last number off the end of the array, and skip over the 0 we just inserted. It's that simple!

Both of this week's solutions make use of splice() to insert and remove array elements, something I haven't used a lot before.

Stay tuned for next week's challenge, which should come out Monday!

Learn Perl With FreeCodeCamp


Published by /u/pmz on Saturday 23 September 2023 05:10

Perl Weekly Challenge #235 - Splicing and Dicing #perl

Published by oldtechaa on Saturday 23 September 2023 00:16

Hi everybody, we've got another two challenges this week, so let's dive into them!

Remove One

The goal is to see if there's any one number that can be removed to make the set sorted in increasing order. Here's the code:

use v5.36;

my $success = 0;
REMOVAL: for my $removal (0 .. $#ARGV) {
    my @modified = @ARGV;
    splice(@modified, $removal, 1);
    for my $scan (1 .. $#modified) {
        if($modified[$scan] <= $modified[$scan - 1]) {
            next REMOVAL;
    $success = 1;

say ($success ? 'true' : 'false');

We have a labelled outer loop for the numbers we choose to remove. $removal is set to the index of each number we attempt to remove, then we copy the array, remove that number, and scan the result to make sure they all are increasing. If they don't, we skip this number and move on.

If we succeed, we set our flag and exit the loops and print the result.

Duplicate Ones

The next one is an array shifting challenge. We want to insert a duplicate of each 0, shifting everything to the right, and popping off the list to keep the length the same.

Here's the code:

use v5.36;

my @ints = @ARGV;
for(my $i = 0; $i <= $#ints; $i++) {
    if($ints[$i] == 0) {
        splice(@ints, $i, 0, 0);

say('(', join(', ', @ints), ')');

This one's also really quite simple. We scan the array, use splice to insert a 0, pop the last number off the end of the array, and skip over the 0 we just inserted. It's that simple!

Both of this week's solutions make use of splice() to insert and remove array elements, something I haven't used a lot before.

Stay tuned for next week's challenge, which should come out Monday!

Introducing System::CPU and Benchmark::DKbench 2.2


Published by /u/dkech on Friday 22 September 2023 22:20

I uploaded System::CPU to CPAN, a pure Perl module with no dependencies to get basic CPU info across various platforms. The main function of interest is:

my ($phys_processors, $phys_cpu, $logical_cpu) = System::CPU::get_cpu(); 

i.e. giving you separately processors (sockets, physical cores, logical cores/hyperthreads). You also have get_name, get_arch, get_name and get_ncpu which is almost the same as MCE::Util::get_ncpu (i.e. borrowing code), as that function was the most consistent at getting the number of logical cores.

Anyway, it is what I ended up using for my Benchmark::DKbench CPU benchmark suite, as all the modules I tried were either missing things, had inconcistencies or could not be installed on some systems. The hardware summary from the benchmark suite ends up looking like this:

--------------- Hardware --------------- CPU type: Intel Xeon CPU @ 2.60GHz (x86_64) CPUs: 176 (2 Processors, 88 Cores, 176 Threads) 

And after running the suite single and multi-threaded, the summary looks like this:

DKbench summary (19 benchmarks, 176 threads): Single: 1001 Multi: 86076 Multi/Single perf: 86.01x (63.39 - 125.09) Multi scalability: 48.9% (36% - 71%) 

I've been using this benchmark to evaluate some large cloud instances like the above, so it can scale to hundreds of cores (MCE), but if you want to bench your desktop/laptop give it a try and tell me if I can do something better ;)

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

Maintaining Perl (Tony Cook) August 2023

Perl Foundation News

Published by alh on Friday 22 September 2023 12:13

Tony writes: ``` [Hours] [Activity] 2023/08/01 Tuesday 0.20 look at new coverity hits, briefly discuss with khw 0.27 github notifications 0.87 #21306 review and briefly comment 0.05 #21084 check latest CI results, apply to blead 0.13 #21296 test blead with the fix, close this PR 0.28 coverity look at older hits, one harmless, another false positive (in the context of perl) 0.18 #21181 apply to blead, perldelta 0.42 #21212 comment

1.28 #21313 testing


2023/08/02 Wednesday 0.08 #21306 review new changes and approve 0.37 #21304 comment 3.05 #21313 debugging

2.42 #21313 more debugging, long comment, testing, more comment


2023/08/03 Thursday 0.23 #21000 review and comment 1.18 #21323 review and comment 1.50 #21313 make a more portable change and testing 0.98 #21313 clean up and more testing, psuh to PR 21324 1.20 #21313 debugging remaining test failure - turns out to be

a known bug upstream


2023/08/07 Monday 1.92 #21313 research, minor fix, apply to blead, perldelta 0.27 #21314 apply to blead, check if docs need update 0.77 #21313 re-work patch for remaining bug, pr perl- libwin32/win32#39

1.10 #17452 reproduce, work on a fix, testing


2023/08/08 Tuesday 0.68 github notifications 0.07 #21325 review and trigger CI 0.43 #21333 review, code archaeology: why was SIG localized? ask for a test case 0.23 #21325 add to authors, bump strict version and apply to blead 0.08 #21328 review and approve 0.82 #21334 review and approve with a comment 0.08 #21335 review and approve 0.12 #21336 review and approve 0.10 #21337 review and approve (and watch github flake out) 0.03 #21338 review and approve 0.05 #21339 review and approve 1.55 #20890 debugging, try to understand how this is meant to

work, long comment


2023/08/09 Wednesday 0.75 github notifications 0.22 more github notifications 0.53 #21333 review and approve, comment 0.25 #21331 comment 0.20 #21340 review and comment 0.73 #21341 review, research, comment and approve 0.10 #21342 review and approve 0.08 #21343 review and approve 0.37 #21344 review and approve 0.08 #21345 review and apply (had another approval) 0.18 #21346 review, testing and comment

0.07 #21348 review and approve


2023/08/10 Thursday 0.25 github notifications 1.22 #21340 review modifications, research, comments 0.90 #21347 review and melt brain 0.53 #21332 work up a fix and make PR 21359

1.50 #21350 debugging


2023/08/14 Monday 0.30 #21347 review and approve 0.07 #21355 review and approve 0.90 #21358 review and comment 0.33 #21359 apply to blead, perldelta 0.27 #21361 review and approve

0.10 #21362, #21363, #21364 review and approve


2023/08/15 Tuesday 0.17 #21340 follow up 0.05 #21333 apply to blead 1.20 #21375 review and comments 0.45 #21376 try to reproduce CI failure, reproduce and comment 0.10 #21377 review and approve

0.62 #21340 follow up


2023/08/16 Wednesday 0.38 #21375 follow up comment 0.05 #21376 review after changes and approve 0.35 ppc#25 comments 0.65 #21379 research and comment

0.17 #21330 review and approve


2023/08/17 Thursday 0.23 ppc#25 follow-up comment 0.13 #21385 review and comment 0.25 #21375 re-review and comment

0.07 #21374 review and approve


2023/08/21 Monday 0.22 #21387 follow-up and close 0.20 #21350 research and comment 0.30 #20917 rebase, testing 0.97 #20917 more testing, push for re-CI (don’t pass until corelist update) 0.07 #21379 check latest changes and approve 0.05 #21395 review and approve 0.02 #21407 review and apply to blead

0.12 #21161 rebase, testing


2023/08/23 Wednesday 0.13 #20917 rebase on corelist fix 0.12 #19426 rebase on corelist fix 0.17 #21329 re-check and apply to blead, perldelta 0.13 #21394 review and comment 0.38 #21392 review and approve 0.13 #21391 review and approve 0.40 #21351 review and approve 0.47 #21415 research 2.15 #21415 testing, yet another cop_features fix, more

testing, push candidate for CI


2023/08/24 Thursday 0.95 #21415 testing, polish, make PR 21421 0.63 #21419 review and comments

0.77 #18606 simplify some old work, testing, push for CI


2023/08/28 Monday 0.40 #21431 review, research and comment 0.20 #21419 comment 0.15 #21411 comment 1.52 #21415 re-work 0.72 #21415 more re-work and push 0.28 #21390 review and comments

0.43 #21389 review, comment and approve


2023/08/29 Tuesday 0.10 #21390 review updates and approve 0.62 #21415 updates 0.10 #21420 review and apply to blead 0.37 #21422 review 0.37 #21422 more review, approve

0.80 review coverity results


2023/08/30 Wednesday 0.28 #21419 look over updates 0.15 #21433 review and comment 1.80 #21434 review and approve 0.23 #21428 review, testing and comment

1.63 more review coverity results, push some changes for CI


2023/08/31 Thursday 0.12 #21433 review changes and apply to blead 0.05 #21428 review changes and approve 1.15 #21421 apply to blead, perldelta 0.28 #21435 review and approve 0.10 #21436 review and approve

0.57 #19376 review existing docs and think how to re-work


Which I calculate is 58.59 hours.

Approximately 73 tickets were reviewed or worked on, and 13 patches were applied. ```

Single Color Methods of GTC

Published by lichtkind on Thursday 21 September 2023 21:40

Whohoo release 1.7 (and 1.6) brought a thorough architectural rewrite, new color spaces (HSV, HWB, YIQ), new formats ([named] array, string and css_string), choosable value ranges, closed both open issues, and introduced the named argument API I wrote last time about. And as promised, this post is about the methods: distance, set, add and blend.

Color Properties

Yes GTC gives you color sets, but how do you know a color, from which you calculate the set, has all the right properties? Many of these properties you simply get by converting the values into color spaces like HSL or HWB. So:

$color->values( in => 'HSL', as => hash )->{lightness};

will tell you how bright or dark the color is. At this point you might wish there is an method just to give you the lightness, but on other hand there are around 10 - 14 color spaces and do we really want 36 methods just for one purpose? Plus if you want to just get the cyan value, how I decide its from CMY or CMYK? So even its a bit more to write, its clear what your get when you write:

$color->values( in => 'CMYK', as => hash )->{cyan};
($color->values( 'CMYK' ))[0]; # same thing but shorter

Because every color space (9 supported by next version) was constructed for a different need, we can provide this way a lot of properties. But all these characterise one color. To characterise color relations we have the method distance. Yes its just the Euclidean distance between two point in color space, as Pythagoras knew it. But as mentioned, having the ability to calculate it in different spaces already magnifies its power.

my $d = $color->distance( to => $other_color, in => 'HWB');

But our method has two additional arguments which makes it even more powerful. The argument select selects which dimensions distance observes. If you want in HSL only observe the hue you could say so:

$color->distance( to => $other, in => 'HSL', select => 'hue');

You could even weight the saturation double as much as the lightness:

$color->distance( to => $other, in => 'HSL', select => 'ssl');

The fourth argument, which is also available with the values method, allows you to change the value ranges of each color space dimension. For instance lets calculate very simply distances in RGB but not using the usual 0 .. 255 value ranges, but the normalized ones (0..1):

$color->distance( to => $other, range => 'normal');

This is especially important if you want to compare your distance with an value that is computed on godknowswhat space dimension sizes.

Related Colors

Beside the obvious constructor method new, there are 3 more methods that create an color object, which has a relation to the current object.

The simplest one of then is set. It replaces some values of the current object with the given. Its full power comes from the ability to accept values in all supported color space. This gives us the ability to create an brown with a certain brightness, but immediately output the values in another format.

color('brown')->set( brightness => 70 )->values( 'CMYK' );

In case you wonder, brightness is the name of the third axis in HSB color space, which is just a renamed version of HSV.

While set changes to an absolute value, add performs relative changes. To slightly dim a Pink we just need:

color('pink')->add( lightness => -10 );

The third method is blend which does something similar, but is way more powerful. While add allows changes along the axis of some color space, blend
lets you select an arbitrary point on a line, that is spanned by any two points (colors) in a color space. It takes three named argument from which only the first ('with') is required. It takes a color object or color definition of the second color to blend (or mix) with. The second argument is 'pos', telling the position on the just mentioned line you want to select. The default value for that is 0.5, giving you an 1:1 blend between the two colors. zero would be $self and one the second color, given by the 'with' argument. Your allowed to state even values beyond 0 .. 1. If the resulting color would be outside the defined border of that color space (default is HSL), it will be clamped to nearest values that produce a valid color (circular dimension will be of course rotated). The third argument is our well known buddy 'in', allowing you to choose the color space in which the calculation takes place.

$color->blend( with => 'grey', pos => 0.1); # we fade to gray

The next episode will be about the set creation methods, the heart of the module before I close up this mini series with musings about the internal architecture.

Why I Created Venus #perl

Published by Al Newkirk on Thursday 21 September 2023 15:06

I'm often asked why I created Venus, and I typically give an answer that amounts to "It's complicated" or "Have you looked at language X" which I concede is unsatisfying to most; so in this article, I will attempt to explain in a more precise and concise manner, for the record.

Why I created Venus

If you survey and analyze the features offered across programming languages used in modern software engineering you'll recognize what I call a "baseline feature set for modern software development". In my opinion, this is missing from the Perl programming language. It's achievable but missing in the sense that it's not core and it's not packaged in a way that's easily accessible.

Some examples are support for data encoding, reflection, gradual typing, object orientation, concurrency, error handling, a robust standard library, etc.

Getting to a modern software engineering baseline in Perl, in 2023, means
traversing a vast landscape filled with potential landmines. To do so successfully means having a firm grasp of the language and its idioms, as well as a familiarity with the CPAN and the best-in-class distributions.

Venus was created to alleviate that pain!

Maybe it's never occurred to you that getting to a modern software engineering baseline in Perl is a nearly impossible feat for someone new to programming, or new to Perl, or simply looking to "get shit done".

Venus, with its convention over configuration object-oriented architecture, is meant to feel familiar to engineers coming from other (modern) languages, looking (or needing) to work in Perl. Venus helps to answer questions like, "How do I create an array object that comes preset with methods that allow me to perform common array operations, which can be chained together?", etc.

Venus provides a robust standard library, embodies industry standards, enables object-orientation and reflection, has sophisticated and extendable exception handling, offers a library of abstract behaviors (i.e. roles/traits), and is built atop an intuitive convention over configuration architecture.

In the coming articles, I will further demonstrate the why and how of Venus, using code examples, comparisons, and real-world software challenges.

See for yourself!

Venus on the CPAN

Perl Weekly Challenge 235: Duplicate Zeros

Published by laurent_r on Wednesday 20 September 2023 18:04

These are some answers to the Week 235, Task 2, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on September 24, 2023 at 23:59). This blog post offers some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 2: Duplicate Zeros

You are given an array of integers.

Write a script to duplicate each occurrence of ZERO in the given array and shift the remaining to the right but make sure the size of array remain the same.

Example 1

Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0)
Ouput: (1, 0, 0, 2, 3, 0, 0, 4)

Example 2

Input: @ints = (1, 2, 3)
Ouput: (1, 2, 3)

Example 3

Input: @ints = (0, 3, 0, 4, 5)
Ouput: (0, 0, 3, 0, 0)

We don't really know what should happen if keeping the array size leads to the removal of the zero just added. We will assume the added zero is just chopped off, like this:

Input: @ints = (0, 3, 2, 0, 4)
Ouput: (0, 0, 3, 2, 0)

Duplicate Zeros in Raku

The duplicate-zeros subroutine uses the map function to build a new array in which any zero from the input array is repeated and other values are just copied untouched. After that, the subroutine returns a splice of the resulting array having the size of the input array.

sub duplicate-zeros (@in) {
    my @result = map { $_ == 0 ?? |(0, 0) !! $_ }, @in;
    return @result[0..@in.end];

for <1 0 2 3 0 4 5 0>,  <1 2 3>, <0 3 0 4 5> -> @test {
    printf "%-18s => ", "@test[]";
    say duplicate-zeros @test;

This program displays the following output:

$ raku ./duplicate-zeros.raku
1 0 2 3 0 4 5 0    => (1 0 0 2 3 0 0 4)
1 2 3              => (1 2 3)
0 3 0 4 5          => (0 0 3 0 0)

Duplicate Zeros in Perl

This Perl program does the same thing as the above Raku program. Please refer to the above section for any explanation.

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

sub duplicate_zeros {
    my @result = map { $_ == 0 ? (0, 0) : $_ } @_;
    return @result[0..$#_];

for my $test ([<1 0 2 3 0 4 5 0>], 
    [<1 2 3>], [<0 3 0 4 5>]) {
    printf "%-18s => ", "@$test";
    say join " ", duplicate_zeros @$test;

This program displays the following output:

$ perl ./
1 0 2 3 0 4 5 0    => 1 0 0 2 3 0 0 4
1 2 3              => 1 2 3
0 3 0 4 5          => 0 0 3 0 0

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check and make sure you answer the challenge before 23:59 BST (British summer time) on October 1, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.

PWC 235 Steppin' in a Slide Zone #perl

Published by Bob Lied on Wednesday 20 September 2023 12:47

I always try to find the common theme between the tasks in the weekly challenge, and I will just straight up invent one if I have to. What I see in week 235 is two tasks that are about moving down a list in a quirky way. The blog title? Moving down a list in pairs reminded me of the slide function, and that reminded me of a minor hit from the Moody Blues circa 1978, Steppin' in a Slide Zone.

That invoked a nostalgic digression to listen to the whole album (downloaded in minutes from 45 years ago -- we live in a marvelous age). I am distressed by the number of brain cells that are uselessly calcified with lyrics of obscure songs from a half-century ago, when they could be so much better used storing obscure Perl programming facts.

Task 1: Remove One

You are given an array of integers.
Write a script to find out if removing ONLY one
integer makes it strictly increasing order.

Example 1

Input: @ints = (0, 2, 9, 4, 6)
Output: true

Removing ONLY 9 in the given array makes it strictly increasing order.

Example 2

Input: @ints = (5, 1, 3, 2)
Output: false

Example 3

Input: @ints = (2, 2, 3)
Output: true

Discourse Upon The Topic

I was misled by examples that are too easy. My impulse was to look for the number of times that the sequence descends instead of ascends, and report if that number was more than one. However, that doesn't cover the case where removing an element still leaves the list with a descending step. For instance, the list (10 20 30 18 19 40) has only one downward step, but we need to remove at least two elements to get to sorted. Back to this after an interlude of how to do it wrong.

Even though I started with a bad solution, it illuminated some topics of list iteration, so let's look at ways of finding the descending steps in a sequence. The motion is two-at-a-time, and there are several ways of doing that.

The basic way, similar in many languages, is to move an index from 0 to not quite the end, and compare $ints[$i] and $ints[$i+1]. Counting downward steps is a necessary but insufficient condition, so we're including that.

  sub removeOne(@ints)
      my $rmvCount = 0;
      for ( my $i = 0; $i < $#ints && $rmvCount < 2 ; $i++ )
          $rmvCount++ if $ints[$i+1] < $ints[$i];
      return $rmvCount < 2;

When we're given a list, it's always tempting to manipulate the list as a whole with map and similar functions, which often helps with tricky boundary conditions. We can apply map to pairs of the list by using indexes in the same way as the for loop -- excluding the very last index at the boundary, and mapping each pair of integers to a boolean that says whether the pair is ascending or descending. Then a count of the descending pairs (false) will tell us how many might need to be removed.

sub removeOne(@ints)
      my $rmvCount = grep { $_ == false }
                  map { $ints[$_] < $ints[$_+1] } 0 .. ( $#ints-1 );
      return $rmvCount < 2;

Another very Perl-ish way to process pairs at a time is to shift elements off the array, consuming the array in the process.

my $first = shift @ints; 
while ( defined (my $next = shift @ints ) )
    say "PAIR: ($first, $next)";
    $first = $next;

Perl v5.36 added the ability in for loops to iterate over successive tuples of an array. That's not quite what we want here, because it moves two elements in every iteration, but it's worth a mention.

for my ($first, $second) (1,2,3,4) { say "$first, $second" }
# 1, 2
# 3, 4

Pair-at-a-time list iteration is common enough that there is a module for it: List::MoreUtils::slide applies a block to each pair in sequence, attaching the names $a and $b to the elements for the convenience of a code block. Using slide is probably the most readable version (assuming one knows what slide does).

sub removeOne(@ints)
    use List::MoreUtils qw/slide/;
    my $rmvCount = 0;
    slide { $rmvCount++ if ( $b < $a ) } @ints;
    return $rmvCount < 2;

Both the map and the slide solution suffer from a potential inefficiency that often plagues array operations: they operate on the entire array, even if we could discover the answer in the first elements of the array.

One way we could make slide give up sooner is to throw an exception from the block. Perl has had exception modules available for years, but in 5.36 try/catch/finally became [an experimental] part of the language. Here's a way to break out of slide before it wastes time:

sub removeOne(@ints)
    use List::MoreUtils qw/slide/;
    use feature 'try'; no warnings "experimental::try";
    my $rmvOne = true;
    try {
        my $rmvCount = 0;
        slide { do { die if ++$rmvCount > 1 } if ( $b < $a ) } @ints;
    catch ($e)
        $rmvOne = false;
    return $rmvOne;

But back to actually solving the problem. We still have the sub-problem of finding a descending step in the sequence. Take 10 20 30 24 25 40 as an example. Which elements should we remove to create a sorted list?

When we hit a down step, we have a choice of what to remove: we can either remove the greater elements to the left until we get back in order, or we can remove the lesser elements to the right until we start ascending again. If we can do it by removing one, we might succeed; if we have to remove more in either direction, we fail.

10  ^ 20  ^ 30   V  24  ^ 25  ^ 40
10    20   [30] <== 24    25    40 # Go back
10    20    30 ==> [24   25]    40 # Skip ahead

The tricky part of this solution is the likelihood of off-by-one errors to take care of the out-of-order element being at the beginning or end of @ints. Here's code that literally walks backward and forward from the point of disorder:

sub removeOne(@ints)
    use List::Util qw/min/;

    return true if @ints < 3;

    my $rmvCount = 0;

    # Walk forward until we hit a descending step.
    for ( my $i = 0 ; $i < $#ints && $rmvCount < 2 ; $i++ )
        next if $ints[$i+1] >= $ints[$i];

        # How far backward would we have to go to get back in order?
        my $back = 0;
        for ( my $j = $i ;    $j >= 0 
                           && $ints[$j] > $ints[$i+1]
                           && $back < 3; 
              $j-- )

        # How far ahead would we have to go to get back in order?
        my $ahead = 0;
        for ( my $j = $i+1;    $j <= $#ints 
                            && $ints[$j] <= $ints[$i] 
                            && $ahead < 3;
              $j++ )
        $rmvCount += min($back, $ahead);

    return $rmvCount < 2;

Consider a sequence like ( 1000, 1..999, 2000). It would be a waste of time moving ahead 1000 steps to rediscover order. We never really need to move backward or forward more than two steps to know the answer. An optimization is to include that condition in the back and forth motions.

I use unit testing frameworks to make sure I don't break one boundary condition when I fix another. These are my test cases:

sub runTest
    use Test2::V0;
    no warnings "experimental::builtin";

    is( removeOne(0,2,9,4,6), true,  "Example 1");
    is( removeOne(5,1,3,2  ), false, "Example 2");
    is( removeOne(2,2,3    ), true,  "Example 3");
    is( removeOne(10,1,2,3 ), true,  "First element goes");
    is( removeOne(10,11,1  ), true,  "Last element goes");
    is( removeOne(10,20,30,24,25,40), true, "One high peak");
    is( removeOne(10,20,30,18,25,40), false, "One high, one low");
    is( removeOne(1,2,5,3,4,6,3,4),   false, "Multiple disorders");
    is( removeOne(99, 1000, 1..999, 2000), false, "Long failure");


One note: I use true and false booleans, which were introduced as experimental built-in functions in 5.36. Annoyingly, they emit warnings, so the incantation to put at the top of the file is

use builtin qw/true false/; no warnings "experimental::builtin";

The Test2::V0 testing module re-enables all warnings, so the suppression of warnings has to be repeated after the module is invoked.

Task 2: Duplicate Zeros

You are given an array of integers.
Write a script to duplicate each occurrence of
ZERO in the given array and shift the remaining
to the right, but make sure the size of array
remains the same.

Example 1

Input: @ints = (1, 0, 2, 3, 0, 4, 5, 0)
Output: (1, 0, 0, 2, 3, 0, 0, 4)

Example 2

Input: @ints = (1, 2, 3)
Output: (1, 2, 3)

Example 3

Input: @ints = (0, 3, 0, 4, 5)
Output: (0, 0, 3, 0, 0)

Discourse Upon the Topic

Two approaches come to mind: we could insert all the zeroes where required and then truncate the list to its original length; or we could walk down the list, inserting one zero at a time and lopping off the right-most element each time. The first approach will double the space required for the list. The second will take no extra space, but needs a little more care in bookkeeping.

First, let's try substituting every occurrence of 0 with a pair of zeros:

map { $_ || (0,0) } @ints 

This concise little tidbit exploits two features of Perl. First, 0 is a false value and all other numbers are true-ish. That means that every time $_ is non-zero, it will be true, so the expression will return $_ itself and not evaluate the right side of the || operation. When $_ is zero, the left side is false, and the right side gets evaluated. We've cleverly made the right side be a pair of zeros. Perl does not build an array of arrays from this; it flattens the list.

So now we have a list where every 0 has been doubled. It is too long. We can truncate it by taking a slice that's as long as the original list. To do that, we'll take the result of map as an array and apply an index range to it.

(map { $_ || (0,0) } @ints)[0 .. $#ints]

The other approach would be to walk along the list and modify it explicitly each time we find a zero. Let's do this a couple of ways. First, let's copy input to output and add the zero in the process of copying:

sub dz_A(@ints)
    my $maxLen = @ints;
    my @output;
    while ( @output < $maxLen )
        push @output, shift @ints;
        push @output, 0 if ( $output[-1] == 0 && @output < $maxLen );
    return \@output;

A few Perl notes: in @output < $maxLen, we're exploiting the fact that naming an array in a scalar context returns the length of the array. Instead of tracking an index to move along the input, we're consuming the input with a shift operation. And finally, we can index from the end of @output with -1 to look at the number we just moved, avoiding a temporary variable.

The other strategy I considered for this solution is to modify the list in place. Each time we find a zero, splice an extra zero into the list, and pop off the right end of the list to keep it the same length.

sub dz_B(@ints)
    for (my $i = 0 ; $i <= $#ints; $i++ )
        if ( $ints[$i] == 0 )
            # Insert a zero and advance i past it
            splice(@ints, $i++, 0, 0);
            pop @ints; # Maintain the length;
    return \@ints;

Notice that we used post-increment of $i to move the index ahead to the next value in @ints instead of processing the newly-inserted zero in the next loop iteration.

Final thoughts

If 1978 is ancient history, pretend I referenced Goo Goo Dolls "Slide" from 2002.

PerlGPT Large Language Model, Phase 1

Perl Foundation News

Published by Saif Ahmed on Wednesday 20 September 2023 09:53

A new grant application from John Napiorkowski and Robert Grimes, this time targetting the development of a large language model trained specifically to develop Perl Code. These veteran coders suggest that using natural language to generate Perl code may potentially allow one to rapidly generate new APIs and applications, or at least give a skeleton to flesh out into a more elaborate tool.


John Napiorkowski & Robert Grimes

Amount Requested

The budget for this project is $8,800 USD, to be made in one lump-sum payment upon completion.

This amount is calculated by multiplying the estimated minimum total hours labor (220 hours) by the minimum acceptable hourly rate for an open source Perl project ($40 / hour):

(220 hours) * ($40 / hour) = $8,800 USD

Please note this amount does NOT include the high cost of renting or purchasing the necessary GPU hardware equipment, which will graciously be donated by the group as a service to the Perl community.


This grant proposal is for phase 1 of the development of PerlGPT, a large language model (LLM) comparable to ChatGPT 4.0, and trained on additional Perl-related content only. PerlGPT will be based on Meta's Code Llama (from Llama v2 or newer) language models, with all new components implemented in Perl where possible and released as free-and-open-source software (FOSS), unlike ChatGPT and other proprietary LLM systems.

Code Llama: Open Foundation Models for Code

Code Llama's documentation currently lists the following primarily-supported languages: "Python, C++, Java, PHP, TypeScript, C#, and Bash". One of the outcome of the PerlGPT project will be to effectively add Perl to this list. (PerlGPT may ultimately be released under an alternative name, such as "Perllama".)

Phase 1 consists of training a 13B input language model using Perl-related stimulus/response pairs curated from Perl Monks, Stack Overflow, GitLab, GitHub, and other public Perl-specific data sources. Phase 1 will deliver an LLM capable of generating pure-Perl source code in collaboration with a Perl programmer, similar to Microsoft Bing and GitHub Copilot.

As with the Perl TensorFlow grants, PerlGPT "is a long-term multi-phase grant series, aimed at radically changing the perception of Perl in the modern software development and AI industries."

(This grant proposal has been simplified and re-submitted, per the request of TPF's grant committee.)

Benefits to the Perl Community

Phase 1 implements PerlGPT v1.0 and benefits the Perl community by enabling the creation of new pure-Perl libraries and applications on CPAN.

PerlGPT v1.0 is trained on pure-Perl source code examples and high-quality POD documentation from CPAN, GitLab, GitHub, and Bitbucket. PerlGPT is further trained on plain-English technical discussions pertaining to their respective feature set, gathered from Perl Monks and Stack Overflow.

For example, a programmer may want to create a new Perl API for some 3rd-party web platform such as the Amazon cloud. The programmer can write a plain-English description of their desired API features and functionality for accessing the Amazon cloud. They can also specify design decisions such as whether or not to utilize an MVC framework like Catalyst or Mojolicious, and they can even start stubbing out some Perl classes and subroutines with comments included where source code should be added.

In this example, PerlGPT v1.0 will work with the programmer to iteratively implement their desired Amazon cloud API in pure Perl, including a full-coverage test suite and POD documentation, etc. Once the API is working well enough for public release, the PerlGPT v1.0 LLM can even help the programmer execute the correct Dist::Zilla commands to build and upload the software to CPAN. Finally, many new independent Perl projects can be created with access to the Amazon cloud, thanks to the Perl API created and uploaded to CPAN with the help of PerlGPT v1.0!

These same benefits apply to any other non-Amazon API which somebody may want to create in Perl, or to any pure-Perl library or application that a programmer can think up. The sky is the limit! PerlGPT v1.0 dramatically increases the effectiveness and efficiency of creating new pure-Perl software.


  • An implementation of the PerlGPT v1.0 13B large language model based on the Code Llama language model, configured and built using Dist::Zilla. (100 hours labor)
    • A comprehensive Perl test suite with automatically-provable coverage for 100% of the PerlGPT v1.0 LLM, using Test2 from CPAN. (45 hours labor)
  • A carefully-written and explanatory collection of documentation with coverage for 100% of the PerlGPT v1.0 LLM, using normal POD fully compatible with CPAN. (20 hours labor)
  • A small collection of user-friendly example Perl applications, using PerlGPT v1.0 LLM components to effectively showcase this project. (30 hours labor)
  • A public GitLab repository with all source code and components of the PerlGPT v1.0 LLM, including unstable or experimental components. (5 hours labor)
  • A public CPAN distribution with all stable source code and components of the PerlGPT v1.0 LLM. (5 hours labor)
  • A public Docker repository with images containing all stable source code and components of the PerlGPT v1.0 LLM, along with all dependencies, ready to run out-of-the-box. (15 hours labor)
  • The PerlGPT v1.0 LLM design does NOT yet support anything other than pure Perl source code. These features will be addressed in future grant proposals.
  • This grant proposal specifically does NOT include PerlGPT phase 2 or beyond, such as XS or C or Perl internals, which is far beyond the scope of a single grant and will be addressed in future proposals.

Project details

We will generate the PerlGPT language model by training a Llama foundational language model. This training will be done using a combination of both manually-curated and automatically-selected stimulus/response pairs, collected from public websites and data sources. We will not utilize any proprietary data or stimulus/response training sets taken from other proprietary language models, such as OpenAI's ChatGPT, etc.

Most of the technical details of how to train the PerlGPT language model can be found in the following papers:

Training Language Models to Follow Instructions with Human Feedback, 3-4-2022

Teaching Large Language Models to Self-Debug, 4-11-2023

LLaMA: Open and Efficient Foundation Language Models, 2-27-2023

Project Schedule

Total development time is estimated at 3 to 6 months, with the normal disclaimer about the difficulty of predicting software project durations.

During the first work cycle of approximately 1 to 2 months, curate and implement the initial PerlGPT v1.0 training data set.

During the second work cycle, run the LLM training procedure and implement the Perl test suite. (The training may take a particularly long time on our currently-available GPU hardware, due to limitations in available grant funding for renting very expensive high-end GPU hardware.)

During the third work cycle, write the Perl documentation and implement the Perl example applications.

If a fourth work cycle is required, continue until the public releases on CPAN and DockerHub are complete.

Completeness Criteria

This grant is deemed complete when all the above-listed deliverables are reviewed and accepted by the official TPF-assigned grant manager.


We are both professional CPAN authors, with a current total of 98 CPAN distributions between the two of us.


John is the maintainer of Catalyst:

Catalyst Runtime

The Perl Foundation sponsored the Perl TensorFlow API phase 1, and we recently worked with our colleagues Will Braswell and Zaki Mughal to successfully utilize and showcase Perl TensorFlow in the new ChatGPU Navi AI system:

Introduction to TensorFlow in Perl

We both live in the Austin, Texas area.


Schwern wrote a little gem.

Some time ago I wanted to import a few CSV files in one SQLite database file and I initially tried to do it with Perl. It was sloooooow.

Then I looked for alternatives and found out .import from the command-line client sqlite3. This is reasonably fast, so I used it straight away and forgot about it.

Until I came to read Schwern’s little gem, hinting to turn AutoCommit off. That hit the nail so good that one single hit sufficed.

So here’s an example:

#!/usr/bin/env perl
use v5.24;
use warnings;
use experimental 'signatures';

use DBI;
use Text::CSV_XS;

my $csv_file = shift // help_then_die('no CSV file');
my $sqlite_file = shift // help_then_die('no SQLite file');
my $sqlite_table = shift // help_then_die('no SQLite table name');

my $csv_it = csv_it($csv_file);
my $fields = $csv_it->();

my $dbh = DBI->connect("dbi:SQLite:$sqlite_file", '', '',
   { RaiseError => 1, AutoCommit => $ENV{AUTOCOMMIT}, }

say scalar(localtime);
$dbh->do(sqlite_create_query($dbh, $sqlite_table, $fields));
$dbh->commit unless $ENV{AUTOCOMMIT};

my $sth = $dbh->prepare(sqlite_insert_query($dbh, $sqlite_table, $fields));
while (my $row = $csv_it->()) {
$dbh->commit unless $ENV{AUTOCOMMIT};
say scalar(localtime);

sub sqlite_create_query ($dbh, $table, $fields) {
   my $q_table = $dbh->quote_identifier($table);
   my $fields_def = join ",\n", map { "  $_ TEXT" } $fields->@*;
   return "CREATE TABLE IF NOT EXISTS $q_table (\n$fields_def\n)";

sub sqlite_insert_query ($dbh, $table, $fields) {
   my $q_table = $dbh->quote_identifier($table);
   my $fields_def = join ', ', $fields->@*;
   my $pholds_def = join ', ', ('?') x scalar($fields->@*);
   return "INSERT INTO $q_table ($fields_def) VALUES ($pholds_def)";

sub csv_it ($path, %args) {
   my $csv = Text::CSV_XS->new(
         sep_char => ',',
   ) or die Text::CSV_XS->error_diag;
   open my $fh, '<:encoding(UTF-8)', $path
      or die "open('$path'): $!\n";
   return sub { return $csv->getline($fh) };

sub help_then_die ($msg) {
   say {*STDERR} "$0 <csv-file> <sqlite-file> <sqlite-table>\n";
   die $msg, "\n";

Test time:

$ rm -f local/prova.db; time AUTOCOMMIT=1 perl csv2sqlite local/somedata.csv local/prova.db whatever
Tue Sep 19 23:08:39 2023
Tue Sep 19 23:09:30 2023

real	0m50.788s
user	0m0.134s
sys	0m6.149s

$ rm -f local/prova.db; time AUTOCOMMIT=0 perl csv2sqlite local/somedata.csv local/prova.db whatever
Tue Sep 19 23:10:21 2023
Tue Sep 19 23:10:21 2023

real	0m0.174s
user	0m0.118s
sys	0m0.023s

This is what I call a speed improvement!


5 years ago, I shared how we had recently started using Perl::Critic, specifically with Test::Perl::Critic::Progressive, to gradually…

5 years ago, I shared how we had recently started using Perl::Critic, specifically with Test::Perl::Critic::Progressive, to gradually…

Perl Weekly #634 - Perl v5.39.1 #perl

Published by Gabor Szabo on Monday 18 September 2023 04:17

Originally published at Perl Weekly 634

Hi there,

Only recently we had a big bang release of Perl v5.38 with experimental class feature. Now in a quick succession we have another release Perl v5.39.1. Thanks to the entire team responsible for the release. These heroes work behind the scene for days/months for the improvement of the language. Yet, I rarely see anyone giving them credit on public platform. We should not just mention them in the pod but instead celebrate each one of them more on various public platforms. Having said, we need volunteer for the job. Do we have volunteer for the task?

Few days ago, I had an email from someone senior with lots of experience with Perl saying "2023 is the year the language died for him". I wonder how can someone just gave up on the language you loved all your life. For me personally, Perl will remain my core strength and I will continue to improve my knowledge with every release. It is OK if you learn some new languages to be in the job market but please keep Perl your first choice.

Yesterday, when I was done with Asia Cup 2023 final cricket match between India and Sri Lanka, I watched this documentary, The Great Hack, on Netflix. It reminded me data is the new oil now a days. Perl is known to be good at data processing, so why are we behind others in this field?

By the way, India won the final for the 8th time. I am so proud of Team India. I am now looking forward to the World Cup 2023 to be held in few months time in India.

Enjoy rest of the newsletter.

Your editor: Mohammad S. Anwar.


Fun with dates

The day-of-week for any day in the year range 1-5000000 Julian. (Doesn't do BC yet; I need to make some changes to the algorithm first.) It also does conversion between Gregorian and Julian.


Of Go, C, Perl and fastq file conversion Vol III : pledging allegiance to the flag

Continue with the multipart blogs, here the discussion is about regex engine maps to a finite state automaton, we should be able to rewrite the parser without regular expressions, using flags to keep track of the part of the record we are at.

Of Go, C, Perl and fastq file conversion Vol IV : gone in 60 seconds (or less)

In the final part of this series, we will test the performance of the four parsers, in a scenario emulating the batch analysis of sequencing data.

Get more from you constants with constant::more

Do you play with constants in Perl often then do check this post, you would love it.


CGI::Tiny & Dispatch::Fu - nearly a perfect match

CGI::Tiny is a very nice, Perlish way to construct CGI scripts these days. It is perfectly suited as a replacement to and is quite at home in a shared hosting environment.

The Weekly Challenge

The Weekly Challenge by Mohammad Anwar will help you step out of your comfort-zone. You can even win prize money of $50 Amazon voucher by participating in the weekly challenge. We pick one winner at the end of the month from among all of the contributors during the month. The monthly prize is kindly sponsored by Peter Sergeant of PerlCareers.

The Weekly Challenge - 235

Welcome to a new week with a couple of fun tasks: "Remove One" and "Duplicate Zeros". If you are new to the weekly challenge, why not join us and have fun every week? For more information, please read the FAQ.

RECAP - The Weekly Challenge - 234

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


Unequally Common

Sharing is Caring

Same Circus, Different Clowns

Back By Lack of Demand

Perl Weekly Challenge 234: Common Characters


nested loops

Perl Weekly Challenge 234

More Frequent Frequencies

Common, but Unequal, Triplet Characters

Duplicates and triplets

The Weekly Challenge #234

Triplets with Character

PWC 234


2023.37 Issuing

Weekly collections

NICEPERL's lists

Great CPAN modules released last week;
StackOverflow Perl report.

Perl Jobs by Perl Careers

Modern Perl and positive team vibes. UK Remote Perl role

If you’re a Modern Perl developer in the UK with TypeScript or Node and you’re searching for a team of dynamos, we’ve found the perfect place for you. This award-winning company may be newer, but the combined experience of their people is impressive. No doubt this is one of the many reasons their AI recruitment marketing business has taken off!

UK Remote Perl Programmer for Leading Enterprise Tech Publication

Our client is a global leader in the enterprise technology publishing industry, providing audiences worldwide with stimulating perspectives and unique news on enterprise tech that matters today and tomorrow. They are seeking a talented Perl programmer to manage the full life-cycle of software projects on a remote basis.

Perl Programmer Opportunity - Join a Prominent Tech Publishing Powerhouse in the Philippines

Our UK-based client is a global leader in the enterprise technology publishing industry, providing audiences worldwide with stimulating perspectives and unique news on enterprise tech that matters today and tomorrow. They are currently seeking a passionate and exceptional Perl programmer based in the Philippines to join their team.

Adventure! Senior Perl roles in Malaysia, Dubai and Malta

Clever folks know that if you’re lucky, you can earn a living and have an adventure at the same time. Enter our international client: online trading is their game, and they’re looking for solid Perl people with passion, drive, and an appreciation for new experiences.

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.

Perl CGI vs. Plack: The Evolution of Web Application Development

Perl on Medium

Published by Grosu Alexandra Elena on Sunday 17 September 2023 20:31

Perl is one of the oldest and most widely used languages for web application development.

Perl Web Applications: Catalyst vs. Dancer2 — A Comparative Analysis

Perl on Medium

Published by Grosu Alexandra Elena on Sunday 17 September 2023 13:46

Perl is a versatile and powerful programming language that has been used for web development for decades. Perl offers many frameworks and…

(cdlxi) 11 great CPAN modules released last week


Published by Unknown on Sunday 17 September 2023 08:47

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

  1. CBOR::XS - Concise Binary Object Representation (CBOR, RFC7049)
    • Version: 1.87 on 2023-09-10, with 13 votes
    • Previous CPAN version: 1.86 was 1 year, 10 months, 6 days before
    • Author: MLEHMANN
  2. MCE - Many-Core Engine for Perl providing parallel processing capabilities
    • Version: 1.889 on 2023-09-13, with 102 votes
    • Previous CPAN version: 1.888 was 2 months, 22 days before
    • Author: MARIOROY
  3. MCE::Shared - MCE extension for sharing data supporting threads and processes
    • Version: 1.886 on 2023-09-13, with 15 votes
    • Previous CPAN version: 1.885 was 3 months, 4 days before
    • Author: MARIOROY
  4. Minion::Backend::mysql - MySQL backend
    • Version: 1.002 on 2023-09-11, with 13 votes
    • Previous CPAN version: 1.001 was 11 months, 6 days before
    • Author: PREACTION
  5. Mojolicious - Real-time web framework
    • Version: 9.34 on 2023-09-11, with 490 votes
    • Previous CPAN version: 9.33 was 2 months, 27 days before
    • Author: SRI
  6. Perl::Tidy - indent and reformat perl scripts
    • Version: 20230912 on 2023-09-12, with 136 votes
    • Previous CPAN version: 20230909 was 4 days before
    • Author: SHANCOCK
  7. SPVM - SPVM Language
    • Version: 0.989042 on 2023-09-14, with 31 votes
    • Previous CPAN version: 0.989041 was 5 days before
    • Author: KIMOTO
  8. Starman - High-performance preforking PSGI/Plack web server
    • Version: 0.4017 on 2023-09-13, with 114 votes
    • Previous CPAN version: 0.4016 was 1 year before
    • Author: MIYAGAWA
  9. Teng - very simple DBI wrapper/ORMapper
    • Version: 0.34 on 2023-09-14, with 26 votes
    • Previous CPAN version: 0.33 was 1 year, 2 months, 23 days before
    • Author: ANATOFUZ
  10. Test2::Suite - Distribution with a rich set of tools built upon the Test2 framework.
    • Version: 0.000156 on 2023-09-13, with 44 votes
    • Previous CPAN version: 0.000155 was 4 months, 15 days before
    • Author: EXODIST
  11. version - Structured version objects
    • Version: 0.9930 on 2023-09-11, with 21 votes
    • Previous CPAN version: 0.9929 was 2 years, 4 months, 25 days before
    • Author: LEONT

The Perl and Koha Conference

Perl Foundation News

Published by Amber Deuel on Thursday 14 September 2023 18:16

The first ever Perl and Koha conference was held in Helsinki, Finland this year. It featured three main days of Perl and Koha presentations and two days of workshops. Workshops included a Perl training session, a masterclass for new Koha developers, Koha improvement initiatives, discussions on the future of Perl as a language, and more.

Koha is the first free open source software library automation package. In use worldwide its development is steered by a growing community of users. Koha is a framework developed in Perl with modules stored on CPAN. Koha allows end users to borrow books from within district and national library systems. A large number of attendees were Koha front end users that are primarily made up of librarians. Perl community members made up an estimated third of attendees. While the connection between these two communities may not be obvious, they benefit from working together.

I was graciously given time to interview two attendees, Salve and Julien, they say there was room for cross interaction between Koha and Perl during talks and workshops, and speakers from both gave talks about mentoring that were attended by members from both communities. Community members also interacted during lightning talks and social events, such as the reception. The reception was held in the National Library in Helsinki and was impressive to the attendees.

Most of the people involved with Koha are librarians looking to make their lives better at work. In the eyes of some attendees, coding is something you do to reach a goal and Perl is well matched with Koha because of this. Koha also has a strong community, similar to our Perl community. Open source projects like Koha can save schools and public libraries thousands of dollars.

Finally, both of the interviewees found the opening talks especially moving. Olga Dibrova, The Ukrainian ambassador to Finland, was a surprise speaker at the opening. She spoke about the devastating impact the Russian invasion has caused on Ukrainian libraries and the urgency to rebuild those structures once it can be safely done. Perl/Koha conference organizer Andrii, also supports Ukrainian libraries and has created a project to help rebuild not only structures, but also the book collections that have been burned during the war. For more information about the Ukrainian Libraries help and post-war restoration initiative, visit .

Next year the conference will be held in Montreal, Canada.

Maintaining Perl 5 Core (Dave Mitchell): June - August 2023

Perl Foundation News

Published by alh on Thursday 14 September 2023 08:37

Dave writes:

This is my monthly report on work done during June-August 2023 covered by my TPF perl core maintenance grant.

I fixed a performance regression bug related to my 'multiconcat' optimisation work from about 5 years ago.

Other than that, I restarted my work on my "make stack reference counted" branch, got it into a working state, and merged it into blead. See below for a detailed explanation.


  • 11:02 GH #21360: Severe regex/concatenation performance regression
  • 49:45 make stack reference counted
  • 18:13 process p5p mailbox

TOTAL: * 79:00 (HH::MM)

Understanding the "stack not reference counted" issue.

I've been asked to include an explanation as to why "making the perl stack reference counted" is a Good Thing, and why it's burning up so many hours in TPF funding.

Internally, perl is mainly based around Scalar Value (SV) structures, which hold a single value. Entities such as $x or $a[0] are all SVs. These SVs include a reference count (RC) field which, when it reaches zero, triggers the freeing of the SV. For the basics, consider the following code:

sub f {
    my $x = ...;
    my $y = ...;
    return \$y;
my $ref = f();

On return from the function, the SV associated with $x is freed in a timely manner. This is because its RC starts as 1, and is reduced to 0 on scope exit. Conversely, the SV bound to $y has its RC increased to 2 by a reference being taken to it, then back down to 1 when $y goes out of scope. So it lives on, accessible as $$ref. This is all good.

Now, perl is a stack-based engine. Internally this means that it has a stack of pointers to SVs, and such pointers are pushed on and popped off as perl executes ops. For example, the action of perl's '+' operator is to:

  • pop two SV pointers off the argument stack;
  • add together the numeric values of those two SVs;
  • store the result in another SV;
  • push a pointer to that new SV onto the stack.

For brevity's sake, I shall in future refer to "pushing an SV" where I mean "pushing a pointer to an SV onto the argument stack".

Now we come to the issue. As a "premature optimisation", perl doesn't increase an SV's RC when pushing onto the stack, nor decrease it when popping. This has the obvious danger that an SV could be be freed while still on the stack, and thus something like an add operator could access a freed SV (and thus undef value), or even worse, the SV could have been reallocated in the meantime and have a completely unrelated value.

Related to this, the @_ argument array doesn't normally reference-count its contents. For normal arrays, the expression $a[0] = "abc" will create an SV, which has the value "abc", and which has a RC of 1 to account for the pointer to the SV which is stored in the array. When the array is freed, the RC of each SV in the array is decremented, and so the elements of the array are typically freed too. @_ doesn't do this. Instead, when a function is called, the arguments are pushed onto the stack (without the RC being bumped), then the list of SV pointers are moved from the stack into @_, again without the RCs being adjusted.

Thus items in @_ are in danger of being prematurely freed.

Here is a classic example of the bug. Examine this code carefully:

@a = qw(aaa bbb);

sub f {
    # on entry, $_[0] is an alias of $a[0],
    #           $_[1] is an alias of $a[1],
    print "@_\n"; # correctly prints "aaa bbb"

    @a = (); # this prematurely frees $_[0] and $_[1]

    # this causes the two just-freed SVs to be reallocated
    my $x = 'xxx:yyy'; my @x = split /:/, $x;

    # but the two reallocated SVs are still referenced by @_
    print "@_\n"; # incorrectly prints "xxx yyy"

This may sound horrendous, and in a way it is. Put in practice, this doesn't happen as often as you might expect. There is usually something else keeping the elements of @_ alive, so the bug is rarely encountered in day-to-day code. But when it does, it can be difficult to track down.

Also, it sabotages code-fuzzers. From time to time, volunteers run jobs which create perl "programs" out of small random fragments and attempt to run them. If one crashes (in the sense of a SEGV or ASAN error), then that indicates a bug in the perl interpreter itself. However, we stopped accepting such bug reports, becuase the vast majority of them turned out to be variants on "stack not refcounted", but it was taking some time to analyse each report and reach that conclusion.

So fixing this bug would be a Good Thing. However, it turns out that fixing it is rather hard. This design flaw has been in the heart of the perl core for 25+ years, and there's about 30,000 lines of C code directly related to implementing all the stack operators (basically just about every op in perl works from the stack).

In particular, it's an all-or-nothing situation: you can't have half the ops adjusting reference counts when pushing/popping while the other half leave them unadjusted.

The way I eventually worked out how to achieve this was by initially wrapping nearly every op function (around 300 of them) with code that adjusts the reference counts of all its arguments on the stack, calls the "real" function, then adjusts any return values in the stack.

This allowed a "big switch" to be turned on in one go that activated reference counting across the entirety of the perl core.

Then in relative leisure, each individual function can be re-written to work directly on an RC stack and not require slow wrapping.

The initial wrapping work, involving around 70 commits, was merged into blead on 16th August. from that point it is now possible to build a perl with the PERL_RC_STACK configuration option which will now run safely, fixing at least least 70 issue tickets and allowing fuzzers to be be used again, while running approximately 30% slower (based on approximate time to run the test suite).

A second set of commits, merged on 4th Sept, unwrapped many of the common and/or easy ops, leaving around 140 out of 314 still to unwrap. At a very rough glance this is now around 10% slower than "vanilla" blead. I haven't done any proper benchmarking yet, though - I plan to do that after I've unwrapped all the hot ops.

Note that none of this work (or at least, very little) currently affects a default build of the perl interpreter: it is only when perl is built with the PERL_RC_STACK option that reference-counting is enabled. Without that, perl behaves and performs just as before (although many of the ops have now been rewritten to use a new API to manipulate the stack: which in theory should behave in a non-changed way on non-PERL_RC_STACK builds).

It is intended that eventually, PERL_RC_STACK will become the default, and then the only, build option.

There is still much work to be done, including

  • unwrapping more ops,
  • fixing some common CPAN distributions (and/or perl core) where they don't work under PERL_RC_STACK builds (note that most already do).
  • optimising some of the hot ops
  • making common XS code not needing the slowdown of wrapping,

Perl: Beyond the Command Line — Perl in Diverse Domains

Perl on Medium

Published by Grosu Alexandra Elena on Wednesday 13 September 2023 23:59

Perl, a versatile and powerful programming language, extends far beyond its reputation as a command-line tool. While Perl has long been…

Skull with the Decktet

Personal blog of Flavio Poletti (Perl & Raku)

Published on Tuesday 12 September 2023 06:00


Playing Skull with the Decktet is pretty straightforward.

If you happen to have a deck of the Decktet, you can easily play Skull too:

  • use the “Aces” as skulls
  • use the “Kings” as point counters
  • use any triple of numbered cards as roses (e.g. first player takes all twos, second player all threes, and so on).

That’s it! It even supports up to 6 players like the original game.

It’s also possible to use a regular deck of cards, although it can be challenging to go beyond 4 players (still possible but a little “abstract”).


What's the Similar Frequency, Kenneth?

RabbitFarm Perl

Published on Thursday 07 September 2023 17:08

The examples used here are from the weekly challenge problem statement and demonstrate the working solution.

Part 1

You are given an array of words made up of alphabets only. Write a script to find the number of pairs of similar words. Two words are similar if they consist of the same characters.


use v5.38;
use boolean;

sub is_similar{
    my($s0, $s1) = @_;
    my(%h0, %h1);
    do { $h0{$_} = undef } for split //, $s0; 
    do { $h1{$_} = undef } for split //, $s1; 
    return false if keys %h0 != keys %h1;
    do { return false if !exists $h1{$_} } for keys %h0;
    return true;

sub similar_words_pairs_count{
    my @words = @_;
    my @similar;
        my $word_index = $_;
        my @similar_temp = grep { $words[$word_index] ne $words[$_] && 
                                  is_similar $words[$word_index], $words[$_] } $word_index + 1 .. @words - 1;
        push @similar, @words[@similar_temp] if @similar_temp > 0;
    } for 0 .. @words - 1;
    return @similar + 0;

    say similar_words_pairs_count qw/aba aabb abcd bac aabc/;
    say similar_words_pairs_count qw/aabb ab ba/;
    say similar_words_pairs_count qw/nba cba dba/;

Sample Run

$ perl perl/ 


The core of this problem is to count up the number of pairs of similar words. A clearly good use of grep, but how to do that exactly? Well, here we define a subroutine is_similar that returns a true/false value depending on if the words meet the definition of similar given in the problem. That's done by expanding the words into arrays of characters, stuffing those characters into hash key slots in order to force uniqueness, and then seeing if the two key sets are equal.

Once we have the logic to determine similarity worked out we can then use it in grep and count up the results.

Part 2

You are given an array of integers. Write a script to sort the given array in increasing order based on the frequency of the values. If multiple values have the same frequency then sort them in decreasing order.


use v5.38;
sub frequency_sort{
    my(@numbers) = @_;
    my %frequency;
    do{$frequency{$_}++} for @numbers;
    my $frequency_sorter = sub{
        my $c = $frequency{$a} <=> $frequency{$b};
        return $c unless !$c;
        return $b <=> $a;

    return sort $frequency_sorter @numbers;

    say join q/, /, frequency_sort 1, 1, 2, 2, 2, 3;
    say join q/, /, frequency_sort 2, 3, 1, 3, 2;
    say join q/, /, frequency_sort -1, 1, -6, 4, 5, -6, 1, 4, 1

Sample Run

$ perl perl/ 
3, 1, 1, 2, 2, 2
1, 3, 3, 2, 2
5, -1, 4, 4, -6, -6, 1, 1, 1


This problem ended up being a bit more complex than it seemed after the first reading. Perl makes this sort of complexity easy to manage though! sort can take a custom sorting subroutine as an argument. That is what is done here, with the requirements of the frequency sort for this problem implemented within the subroutine referenced by $frequency_sorter. This is written as an anonymous subroutine in order to obtain a closure around %frequency. Finally, observe that we can use the scalar reference directly with sort. sort is flexible enough to know how to use the reference.


Challenge 233

What's the Frequency, Kenneth?

MIME Header X-Unsent

Personal blog of Flavio Poletti (Perl & Raku)

Published on Thursday 07 September 2023 06:00


I discovered about X-Unsent.

I like automating repetitive tasks with small command-line programs because it’s fun and spares me a lot of errors, mostly in the form of things I forget. So it’s no wonder that after the thirdAHEMthirtiest email with the same shape, I thought about automating the generation of those emails too.

For reasons that I’m not willing to confeAHEMdisclose, I’m not sending those email straight away but through the Outlook client. Only fact is, when I generate an email in a valid, standards-compliant way using Perl (via module MIME::Entity, in particular), opening it with a double click makes it appear like I received it, so to actually send it I have to either reply or forward.


This time I decided that enough is enough and give another spin to the search wheel. Which, to be honest, seems like it’s been reset to the nineties, considering the quality of the results, or even worse, considering that there was not that much advertising at the time yet.

But I’m digressing.

This time I got lucky with this result (I can’t remember my actual query): EML files no longer opening as a draft e-mail to send.

Oh-oh! So it was at least possible in the past!

I find the first reply… curious: you can revert back. Well, that’s lateral thinking at its finest.

Sarcasm apart, the original sender was kind enough to also provide a solution that still seems to work in the Outlook I have in Windows: set a custom header X-Unsent to 1:

X-Unsent: 1

When this like appears in the email’s headers in the file, double-clicking on it opens the email in draft mode, complete with a shiny Send button.

Thanks Ralph Taylor!

On Craft

Personal blog of Flavio Poletti (Perl & Raku)

Published on Wednesday 06 September 2023 06:00

Go read On Craft.

common per-host colors

rjbs forgot what he was saying

Published by Ricardo Signes on Saturday 02 September 2023 16:12

I found a note to myself that I should post about my per-host colors. I don’t know whether it’s of general interest to whoever reads this thing, but I guess I thought that once, so here we go.

I work on a bunch of different hosts, from my laptop to my Raspberry Pis to work systems, and others. At work, hosts have different color prompts by datacenter, and I thought this was a good way to remind myself where I was running my commands.

First, I made a little shell program called .sh/host-color:

HOSTNAME=`hostname -s`
if [ -z "$HOSTNAME" ]; then
  RJBS_HOST_COLOR=247 # no hostname! dim unto death
elif [ "$HOSTNAME" = "dinah" ]; then
  RJBS_HOST_COLOR=141 # lovely lavendar
elif [ "$HOSTNAME" = "snowdrop" ]; then
  RJBS_HOST_COLOR=81  # an icey blue
elif [ "$HOSTNAME" = "snark" ]; then
  RJBS_HOST_COLOR=202 # orange you glad I picked this color?
elif [ "$HOSTNAME" = "wabe" ]; then
  RJBS_HOST_COLOR=66  # the color of moss on your sundial

# ... lots of options elided

elif [ -e "/etc/listbox-version" ]; then
  RJBS_HOST_COLOR=46  # any Listbox host, Listbox green
  RJBS_HOST_COLOR=201 # bright pink; where ARE we??

Then it’s easy to use that variable in a bunch of places to remind yourself of context. The most important for me are tmux config and shell prompt. That way, I can see when I’ve ssh’d into host A from a tmux on host B, like this:

shell on wabe, and tmux on snowdrop

In my .zshrc:

export PS1="%{^[[1m%}%F{$RJBS_HOST_COLOR}%m%f:%~%(!.%F{red}#.%F{46}$)%f%{^[[0m%} "

In my .tmux.conf:

set -g status-right \
  " #[fg=colour238]#[bg=colour0]▛#[fg=colour$RJBS_HOST_COLOR] #h "

…and that’s that!

either the Nanoleaf touch API is broken, or I am

rjbs forgot what he was saying

Published by Ricardo Signes on Friday 01 September 2023 14:21

When I bought my Nanoleaf panels, which I wrote about in my previous two posts, I didn’t realize that they’re not just programmable lights. They’re also touch sensors. Or so they claim! The truth is, I haven’t been able to use the touch interface reliably. This post will recount my efforts.

I should say up front: I haven’t really tried to use the default touch programming. That is: I haven’t gone into the Nanoleaf iOS app to set events onto touch events. I know that isn’t what I want to do long term, and I didn’t have any good ideas about how to use it for diagnostic purposes. I do know that the touch sensors seem to work to some extent, because when touched, the panels brighten.

server-sent events

Anyway, here’s the deal: There’s an HTTP endpoint in the Nanoleaf Shapes API that provides you Server-sent events providing updates on the device’s status. I don’t like server-sent events. It’s fine, I know how they work, and they’re not terrible. It’s just that I don’t like reading the spec. This is a me problem, not a server-sent events problem, but there it is. Anyway, your client needs to GET /api/v1/{your-auth-token}/events?id=1,2,3,4 and read chunks. The id parameter doesn’t have to be exactly that. It’s a comma-separated list of event types. What are the event types? Well, at first, it depends on which part of the documentation you believe.

Section 3.5.1 says:

For example if a client wished to register for the state (id=1), layout (id=2) and touch (id=3) events, it would sent the following request:

Section 3.5.2 gives a table with the following ids:

  • State: 1
  • Layout: 2
  • Effects: 3
  • Touch: 4

In the end, I don’t think this is actually a contraction, just a terrible choice. Here’s why…

Server-sent-events are sequences of key/value lines separated by blank lines. So, you might get this:

id: 1
data: {"events":[{"attr":1,"value":false}]}

id: 3
data: {"events":[{"attr":1,"value":"Beatdrop"}]}

That’s two events. The id value is meant to let you synchronize with the server. When you connect, you’re told the last event id, and then each subsequent event tells you its id, and you can keep up to date with the event stream. In the Nanoleaf API, that’s all thrown out the window. The id field, here, is actually event type id. It tells you what kind of event is described by the JSON in the data. Why abuse the id field for this instead of putting it in the JSON? I don’t know.

Anyway, it could make sense that the id query parameters were for one kind of type and the event ids were a different id type. It doesn’t appear to be the case, though. If I want effect events, I subscribe with the id parameter set to 3, not … well, they didn’t give a value for effects in the parameter type definition. It seems to just be an error. Now we know, and we’ll trust §3.5.2 over §3.5.1.

Back to the events! Being able to get notified when the layout, state, or active effect changes sounds like it could be useful for some things, but I had no need. I wanted to know about touch events. Why? I don’t know, it just sounded neat.

server-sent touch events

A touch event, like every other event, is provided as JSON in the data attribute of the server-sent event. Here’s an example:

id: 4
data: {"events":[{"panelId":-1,"gesture":5}]}

id: 4
data: {"events":[{"panelId":-1,"gesture":4}]}

The gesture key is another numeric id, with the following definitions:

  • 0: single tap
  • 1: double tap
  • 2: swipe up
  • 3: swipe down
  • 4: swipe left
  • 5: swipe right

When you get a tap, the panelId is the panel id of the tapped panel. When you get a swipe, the panel id is -1, because a swipe is defined as swiping across two or more panels.

I have never seen the server-sent events provide a tap event. Also, I find their reporting of swipe events very unreliable. They’re reported with a large delay, and often not reported at all. I’d say the other event types have delays also, but I find it less of a problem that there’s a 700ms delay between power off and power off event than that there’s a 700ms delay between touching the device and seeing the touch event.

This was not going to be useful. Fortunately, there’s a touch stream, where you can get “fine resolution, low latency” touch data streamed to you.

the touch stream

It works like this. You still have to start up your event stream connection, even though you won’t be reacting to the events. It’s just a way to tie the duration of the streaming to something else. When you make the request, though, provide the HTTP header TouchEventsPort. This tells the Nanoleaf controller where to stream the events. It will send datagrams to the requesting IP at that port, and it will send them in real time. Sound great? Well, in my experience, it isn’t.

First, I had some frustration setting up the whole program, all of which was my fault. I have a weird mental block about quickly writing UDP listeners with IO::Async, and I don’t know why. Fortunately, I recognized that I was hitting that problem and switched to plain old Socket, which worked great, except I needed to initiate the long-running HTTP request with curl. Silly, but fine. None of this is why I found the end result unsatisfying.

The first problem is the binary format of the datagram. Why aren’t the datagrams JSON? My guess is that the onboard processor isn’t up to real time encoding of arbitrary multi-panel touch events into JSON, and I can respect that. Who doesn’t enjoy writing a little binary data parser once in a while, right? The problem for me came first from the documentation. Again!

The documentation says the format of the datagrams is as follows:

  <(touchType = 3bits |
touchStrength = 4bits)1 = 1B>

 <(touchType = 3bits | touchStrength = 4bits)2 =

 <(touchType = 3bits | touchStrength = 4bits)3 =

 <(touchType = 3bits | touchStrength = 4bits)4 =
 <(touchType = 3bits | touchStrength = 4bits)_n
= 1B>

First off: what? The first line seems like it might make sense: three bits for “touch type”, then four bits for “touch strength”, then a set bit. Repeat. But then the second byte replaces the 1, which I took for “a set bit” with a 2. You can’t have 7 bits, then a 2, and have it make one byte. What??

This is okay, because the documentation continues, contradicting itself but providing much more useful information.

The first 2 Bytes represents the number of panels that are currently undergoing a touch event. After that follows nPanels number of 5B packets, each packet representing touch data for that panel.

The first 2B of the packet represents the panelId of the panel that is currently undergoing a touch event. The next 1 byte is a combination of the Touch Type and Touch Strength:

[ diagram ]

The last 2 bytes represent the panelId of the panel swiped from only in case of a swipe event. This value is otherwise set to 0xFF

Okay! Now we’re getting somewhere. We get (2 + 5n) bytes, where n is the number of touched panels. The first two bytes provide n. Great!

Now we just need to know how to interpret the per-panel touch type and strength, helpfully given in a diagram. Here it is:

mostly-worthless diagram


It looks to me like this is another unfortunate problem with Nanoleaf’s API site renderer. The table header is probably meant to have markers for “this header spans n columns”, but it doesn’t make it into the HTML. So, which bits are part of which field? Hard to say. The good news was that I did receive datagrams, so all I had to do was inspect the packets, right? This was pretty easy, basically a pretty printer plus this:

my $sock = IO::Async::Socket->new(
  on_recv => sub ($self, $dgram, $addr) {
    state $counter = 1;
    Nib::TouchUtil->dump_dgram($dgram, $counter++); # <-- pretty printer

A couple events get dumped like this:

much better diagram

I got everything working, it seems, but it’s really not satisfactory. First off, I can tap as much as I want, I get “hover” events. I can get a swipe (as you can see in the diagram), but basically never a tap. I hoped that this was going to turn out to be a misunderstanding of that confusing packet definition, but I don’t think it is. You can tell an event is a swipe because the last two bytes aren’t 0xFF. Given that, the type/strength byte needs to have an 100 in it to represent the touch type for swipe. That only happens in one place in swipes: the right three bits of the left nybble. That leaves the right four for touch strength, which never seems like a useful value.

Beyond that, the delivery of these datagrams isn’t reliable. I don’t mean “UDP isn’t reliable”, I mean that it feels like the Nanoleaf controller only sends these events when it feels like it. If I hold my finger on the panel, I get repeated hover events… sometimes… for a while. It’s not terrible, but it doesn’t feel like something I could really rely on for anything but a goof. For a goof, though, I’d have built it to show somebody, and I wouldn’t want it to fall flat!

There’s one more problem. For a while, during development, I stopped getting the datagrams at all. It happened when I was trying to move the HTTP event stream code into Perl, and my initial theory was that initiating the HTTP request with Perl wasn’t starting the streaming datagrams, but initiating with curl was. I tested this over and over, I fired up Wireshark, I fiddled with parameters, IP version, I asked friends. Finally, I did some things in a different order and realized that as best as I could tell, it didn’t matter what HTTP client I used. The problem was that I needed two HTTP connections active for the UDP stream to begin. It was easy to reproduce with a bunch of different combinations.

A week later, that symptom was gone, but the weird and unreliable datastream was still there. I was never particularly attached to doing anything with the touch events, so I just gave up on the branch and decided my next hunk of work would be about putting colors on panels. At least I made a pretty packet dumper!

List of new CPAN distributions – Aug 2023


Published by perlancar on Friday 01 September 2023 01:07

dist author abstract date
Acme-CPANModules-Sampling PERLANCAR List of modules to sample items from a list 2023-08-11T00:05:10
Acme-MetaSyntactic-always_sunny PERLANCAR Characters from the sitcom It's Always Sunny In Philadephia (2005-) 2023-08-04T00:05:29
Alien-CXC-param DJERIUS Build and Install the CIAO cxcparam library 2023-08-17T22:33:57
Alien-Ruby NHUBBARD Alien package for the Ruby programming language 2023-08-21T03:30:10
Alien-libgs1encoders HANGY Build and install libgs1encoders, a C-based GS1 barcode parser 2023-08-17T21:17:02
Alien-parasail CHRISARG Install the parasail aligner shared libraries for use with (Bio)Perl. 2023-08-25T04:22:55
App-FileComposer ARIDEV Dumps pre defined scripts! 2023-08-14T21:45:27
App-HL7-Compare BRTASTIC compare two HL7 v2 messages against one another 2023-08-19T06:15:50
App-Mkscript ARIDEV write scripts and files quickly! 2023-08-11T22:03:13
App-Oozie BURAK Tooling/wrappers for Oozie job deployment and scheduling 2023-08-31T13:55:48
App-SymlinkUtils PERLANCAR CLI utilities related to symbolic links (symlinks) 2023-08-25T00:05:29
App-alluniq TULAMILI Align the number of columns on each line upon TSV input. 2023-08-12T05:44:28
App-colalign TULAMILI Align the number of columns on each line upon TSV input. 2023-08-11T15:28:59
App-colconnect TULAMILI 2023-08-10T13:56:33
App-collen TULAMILI shows the numbers related to the numbers of the columns of each input line. 2023-08-12T06:27:22
App-perlmv-scriptlet-add_extension_according_to_mime_type PERLANCAR Guess the file content's MIME type using File::MimeInfo::Magic then if type can be guessed and file doesn't yet have extension or has unmatching extension then add an extension 2023-08-26T00:05:21
App-sdview-Output-HTML PEVANS generate HTML output from App::sdview 2023-08-25T21:42:24
App-sdview-Output-Tickit PEVANS interactive terminal-based viewer for App::sdview 2023-08-26T00:17:14
Apple-AppStoreConnect DKECHAG Apple App Store Connect API client 2023-08-06T13:46:02
Authen-SASL-SCRAM EHUELS SCRAM-SHA-1/256/512 support for Authen::SASL 2023-08-05T20:11:38
BankDetails-India MANJREKAR Perl interface to access the webservice. 2023-08-10T11:20:47
Bencher-Scenarios-Date-TimeOfDay PERLANCAR Scenarios to benchmark Date::TimeOfDay 2023-08-06T00:05:56
Bencher-Scenarios-Digest-SHA PERLANCAR Scenarios to benchmark Digest::SHA 2023-08-13T00:05:22
Bencher-Scenarios-File-Flock-Retry PERLANCAR Scenarios to benchmark File::Flock::Retry 2023-08-20T00:05:26
Bencher-Scenarios-HTTP-Tiny-Patch-Retry PERLANCAR Benchmark HTTP::Tiny::Patch::Retry 2023-08-27T00:06:14
Benchmark-DKbench DKECHAG Perl Benchmark 2023-08-28T22:30:12
Blockchain-Ethereum-Keystore REFECO Ethereum keystorage utilities 2023-08-06T23:14:42
CPE GARU Common Platform Enumeration identifiers 2023-08-17T04:27:20
CXC-Form-Tiny-Plugin-OptArgs2 DJERIUS A Plugin to interface Form::Tiny with OptArgs2 2023-08-03T04:49:22
Chicken-Ipsum DCHURCH Generate random chicken noises. 2023-08-10T20:02:58
DBIx-Class-Storage-DBI-MariaDB RAGE Storage::DBI class implementing MariaDB specifics 2023-08-07T13:33:27
Dancer2-Template-Mason YANICK Mason wrapper for Dancer2 2023-08-01T17:54:04
Data-Pretty JDEGUEST Data Dump Beautifier 2023-08-06T08:18:59
Dispatch-Fu OODLER Provides a reduction based approach to given/when or variable dispatch 2023-08-24T05:29:04
Dist-Zilla-Plugin-GitHub-CreateRelease TIMLEGGE Create a GitHub Release 2023-08-21T23:55:07
ENV-Util GARU parse prefixed environment variables and dotnev (.env) files into Perl 2023-08-10T04:30:58
Export-These DRCLAW Terse Symbol (Re)Exporting 2023-08-11T02:02:24
Finance-Random-Price SKIM Perl class for creating random price. 2023-08-29T18:50:19
GS1-SyntaxEngine-FFI HANGY Provides a FFI wrapper for libgs1encoders 2023-08-25T18:56:56
Imager-zxing TONYC Barcode scanning with libzxing-cpp 2023-08-28T12:49:08
Import-These DRCLAW Terse, Prefixed and Multiple Imports with a Single Statement 2023-08-11T03:58:17
Loverl NOBUNAGA Lover – A LÖVE2D game development command-line interface. 2023-08-03T01:32:21
Magic-Check LEONT Add type/value checks to variables 2023-08-26T15:21:42
Magic-Coerce LEONT magical coercers for scalar values 2023-08-26T11:25:58
Mo-utils-EAN SKIM Mo EAN utilities. 2023-08-27T18:31:36
Namespace-Subroutines NYRDZ Finds subroutines in namespace (attributes included). 2023-08-19T13:48:55
Object-Pad-FieldAttr-Checked PEVANS apply type constraint checks to Object::Pad fields 2023-08-14T15:07:01
Object-PadX-Log-Log4perl WATERKIP A logger role for Object::Pad based classes based on Log::Log4perl 2023-08-19T02:49:18
Onyphe GOMOR ONYPHE base class 2023-08-30T05:30:05
Proc-ForkSafe SKAJI help make objects fork safe 2023-08-03T23:08:52
RT-Extension-EmailReplyDelimiter AJWOOD Strip text from emails after a delimiter 2023-08-19T13:36:08
RT-Extension-NewTicketFromCorrespondence AJWOOD Make new tickets from correspondence 2023-08-17T22:33:46
RT-Extension-PinComment AJWOOD Add a "pin comment" feature to tickets 2023-08-19T22:42:11
Random-AcademicTitle-CZ SKIM Class for random Czech academic title. 2023-08-21T22:25:20
Resource-Silo KHEDIN lazy declarative resource container for Perl. 2023-08-12T21:03:44
Rope LNATION The great new Rope! 2023-08-15T14:51:14
SPVM-HTTP-Minimal KIMOTO HTTP Client 2023-08-22T06:32:07
SPVM-Mozilla-CA KIMOTO Mozilla's CA cert bundle in PEM format 2023-08-30T00:26:16
SPVM-Net-SSLeay KIMOTO SPVM bindings for OpenSSL 2023-08-31T01:33:14
Schedule-SGELK LSKATZ 2023-08-11T16:45:12
SlideMap JWHITE Perl module for the creation of MicroArray slide maps 2023-08-11T13:28:37
Statocles-Plugin-Highlight-Kamelon VOEGELAS Highlight code 2023-08-09T14:29:04
Term-Tmux-StatusBar FREED change tmux status bar. 2023-08-31T11:26:37
Terse-View-TT LNATION Terse Template Toolkit View 2023-08-06T19:16:12
Test-Neo4j-Types AJNN Tools for testing Neo4j type modules 2023-08-01T14:02:31
Types-Equal KFLY type constraints for single string equality 2023-08-14T00:32:06
WWW-Mechanize-Chrome-DOMops BLIAKO Operations on the DOM 2023-08-11T21:21:35
WWW-Suffit-Client ABALAMA The Suffit API client library 2023-08-03T16:00:44
WWW-Suffit-Server ABALAMA The Suffit API server library 2023-08-24T16:45:37
exact-fun GRYPHON Functions and methods with parameter lists for exact 2023-08-19T16:59:03
mccs IDOPEREL Fully-featured static file server. 2023-08-06T12:22:15
tmux-status-bar FREED change tmux status bar. 2023-08-30T18:20:04


Number of new CPAN distributions this period: 72

Number of authors releasing new CPAN distributions this period: 44

Authors by number of new CPAN distributions this period:

No Author Distributions
6 SKIM 3
10 GARU 2
13 LEONT 2
14 FREED 2
21 BURAK 1
24 KFLY 1
26 TONYC 1
29 RAGE 1
31 NYRDZ 1
32 SKAJI 1
42 GOMOR 1
44 AJNN 1

Maintaining Perl (Tony Cook) July 2023

Perl Foundation News

Published by alh on Monday 28 August 2023 08:15

Tony writes:

``` [Hours] [Activity] 2023/07/03 Monday 0.92 #21181 fixes, testing, re-push and push to smoke-me 0.50 #21180 fixes, testing, push for re-CI 1.52 apply one of my PRs, look into unexpected mingw64 failure

on another PR


2023/07/04 Tuesday 0.42 #21120 apply to blead, perldelta update, add to maint votes 0.65 #21132, #21095 apply to blead, perldelta #21202 comment 0.08 #21118, #21060 apply to blead 0.28 #21031 apply to blead 0.85 #21041 testing, checks to see if regen changes meant this needed updates, apply to blead 0.45 #21030 testing, apply to blead, perldelta 0.30 #21180 check CI results, apply to blead

1.37 #21202 look at mingw failure again, testing, comment


2023/07/05 Wednesday 2.55 #21202 more testing, only happens when linking with -g, doesn’t happen with gcc from WIP strawberry perl 3.03 #21202 work on trying to use mingw64 that’s meant to be

part of the runner


2023/07/06 Thursday 1.65 #21202 mingw64 that’s part of the runner is old, install using action, but it’s ucrt, see if we can detect that

0.98 #21202 work on ucrt support


2023/07/10 Monday 0.68 #21212 research and comment 1.98 #21202 detect CRT type and pass it into the build, start on adapting conditional compilation to match

1.22 #21202 more adaption, get it building, testing


2023/07/11 Tuesday 1.60 #21202 clean up, work on adapting CI itself

3.20 #21202 testing, fix some issues, make PR #21234


2023/07/12 Wednesday 0.38 #21202 change as suggested by xenu, push for CI 0.08 #21202 squash UCRT re-work into original commit and re- push 0.35 #21012 comment 0.13 review github notifications 1.08 #21176 fix issues, re-push 0.43 push revert for generateuudmap change to CI 0.57 #21230 review, comment 0.20 #21227 review and approve 0.08 #21226 review and approve

0.15 #21225 review and approve


2023/07/13 Thursday 1.50 #21012 follow-up, add a related fix, comment 0.10 generate_uudmap revert: make PR 21237 0.80 #21233 work on fix and testing, make into a branch on the upstream and push for CI 0.13 #21233 clean up and make pr pjf/autodie#120 0.12 #21152 briefly comment 2.15 #21186 research, testing and comment 0.73 #21084 work on fixing format strings, side-tracked by

build issue, work it out, finish fix and update branch


2023/07/17 Monday 0.13 #21240 comment 0.82 #21241 review and comments 2.40 #21186 have porting tests handle CRLF checkouts on Win32,

review some PRs while testing


2023/07/18 Tuesday 0.35 #21230 comments 0.35 #21240 review updates and approve 0.17 #21252 research and comment 0.48 #21186 re-work, testing 0.32 #21186 recheck, push for CI 0.12 #21257 review and comment

0.73 #21256 review, some comments


2023/07/19 Wednesday 0.08 #21257 comment about possible mis-close 0.18 #21241 follow-up 0.17 #21256 research 0.43 #21256 follow-up comment, separate comment on another commit 0.23 #21266 review and approve

0.12 #21264 review and comment


2023/07/20 Thursday 0.45 github notifications 0.92 #21265 review, research and approve 1.47 #20811 rebase, testing, re-check 0.13 #21152 apply to blead

0.43 #21233 make into a blead PR 21270


2023/07/24 Monday 0.48 #21256 review new changes and approve 0.45 #21230 follow-up 0.38 PPC#36 review, re-check mailing list discussion 1.08 #21271 debug and work on a fix, testing, make PR 21284

1.17 try codeql on perl source, review results


2023/07/25 Tuesday 0.65 #21271 apply to blead, add to votes files, perldelta 0.68 ppc#36 comment 0.05 #21287 review and approve 0.03 #21281 review and apply to blead 0.17 #21280 review, briefly research and comment 0.07 #21280 review changes, follow-up comment 1.75 #21286 review and approve 0.43 #21149 re-check and apply to blead

0.03 #21032 apply to blead


2023/07/26 Wednesday 0.18 ppc#36 comment 0.80 #21290 research, comment 0.08 #21289 comment briefly 0.18 #21275 close 0.08 #21292 review and approve 0.05 #21285 review and approve 1.20 #21294 reviewing more locale changes 0.43 #21294 more reviewing more locale changes 0.10 #21211 review and approve 0.22 #21236 review and approve 0.18 #21012 rebase to get the mingw fix 0.18 #21187 work on a doc fix 1.40 try -Wshadow, work on -Wconversion fixes (since it detects

some known issues)


2023/07/27 Thursday 0.60 #21294 research, follow-up 0.77 more -Wconversion 0.50 #21187 make the doc update more complete, make PR 21298 0.95 #21297 testing, comment 0.70 #21012 apply to blead and perldelta 0.65 #20990 rebase and testing

0.62 more -Wconversion


2023/07/31 Monday 0.40 #21297 review new patch and approve 0.33 #21294 review changes and approve 0.20 #21298 minor update 0.60 #21310 review, testing (and find -Dusequadmath -Dclang doesn’t work with or without this change), approve 0.07 #21302 review and approve 0.15 #21304 research 0.37 #20811 rebase and apply to blead 0.48 look at some win32/gnumakefile optimization fixes 0.32 #21312 review and approve 1.07 more win32/gnumakefile, testing 0.07 #21298 apply to blead

0.12 #21313 research


Which I calculate is 65.16 hours.

Approximately 54 tickets were reviewed or worked on, and 15 patches were applied. ```


I wonder about the state of PerlMagick.

PerlMagick represents the Perl bindings for… well, it’s complicated:

  • ImageMagick is the “original” software, which is still very popular as it grows and evolves
  • GraphicsMagick is a fork (21 years ago!) that aimed at interface stability and efficiency.

Both projects include the bindings, which eventually result in the installation of Image::Magick and Graphics::Magick respectively.

Out of curiosity, I tried to compile both modules for a fairly recent version of Perl (v5.36). With… frustrating results.

First of all, there’s no way to install them from CPAN. It’s the other way around: we compile the main thing, and the modules are available (and installable) as a side effect. A sort of Alien, but in reverse. This has its drawbacks, because tools like carton and cpanm are out of the game.

ImageMagick complains a lot. Many errors have to do with input/output, so it might be related to some library that I forgot to include during configuration/compilation.

t/blob.t .......... ok   
t/bzlib/read.t .... Failed 2/2 subtests 
t/bzlib/write.t ... Failed 1/1 subtests 
t/composite.t ..... Failed 1/18 subtests 
t/filter.t ........ Failed 1/58 subtests 
t/getattribute.t .. ok     
t/jng/read.t ...... ok     
t/jng/write.t ..... ok     
t/jpeg/read.t ..... ok   
t/jpeg/write.t .... ok   
t/montage.t ....... ok     
t/ping.t .......... ok   
t/png/read-16.t ... ok   
t/png/read.t ...... ok   
t/png/write-16.t .. ok   
t/png/write.t ..... ok   
t/read.t .......... 1/47 Readimage (gradient:red-blue):
   Exception 395: UnableToOpenConfigureFile `colors.xml'
   @ warning/configure.c/GetConfigureOptions/722
   at t/ line 317.
t/read.t .......... Failed 1/47 subtests 
t/setattribute.t .. ok     
t/tiff/read.t ..... ok     
t/tiff/write.t .... ok     
t/write.t ......... Failed 1/32 subtests 
t/zlib/read.t ..... Failed 1/2 subtests 
t/zlib/write.t .... Failed 1/1 subtests

GraphicsMagick complains too:

t/blob.t .......... ok   
t/composite.t ..... ok     
t/filter.t ........ ok     
t/getattribute.t .. ok     
t/jbig/read.t ..... ok   
t/jbig/write.t .... ok   
t/jng/read.t ...... ok     
t/jng/write.t ..... ok     
t/jpeg/read.t ..... ok   
t/jpeg/write.t .... ok   
t/montage.t ....... Failed 19/19 subtests 
t/ping.t .......... ok   
t/png/read-16.t ... ok   
t/png/read.t ...... ok   
t/png/write-16.t .. ok   
t/png/write.t ..... ok   
t/ps/read.t ....... ok   
t/ps/write.t ...... ok   
t/read.t .......... ok    
t/setattribute.t .. ok     
t/tiff/read.t ..... ok     
t/tiff/write.t .... ok     
t/ttf/read.t ...... ok   
t/write.t ......... 1/? SetImageAttribute:
   Extending attribute value text is deprecated!
SetImageAttribute: Extending attribute value text
   is deprecated! (key="comment")
t/write.t ......... ok    
t/zlib/read.t ..... ok   
t/zlib/write.t .... ok

Anyway, this seems to be a bug introduced in the very latest release (as of now, of course), properly tracked in a bug report.