Last week, we reported that rt.cpan.org would be moving from its old home, and that it would be hosted by Best Practical, the makers of RT. The timeline we gave was "will be done sometime in early March," but fortunately, the process has gone very well and is now just about complete. Within a few hours from now, rt.cpan.org will point to the new instance, where all the old data has been migrated. Some small amount of below the surface work remains to be done, but we expect that you should be able to continue using RT without interruption.

You might notice that things look pretty different. That's because the whole system has been upgraded from v4.0.18 to v5.0. If you encounter something in the new RT install that used to work and now doesn't, or that just seems plain old broken, please contact the rt.cpan.org admins, who can look into it.

Thanks to Best Practical for getting this done without any down time, and of course many thanks to the Perl NOC, who kept our old RT running for so many years!

Perl is very different from most other programming languages in that functions in Perl can be made aware of their environment, especially they can chechk what kind of data is expected from them? A scalar, a list? Maybe nothing?

This expectation might be different every place the function is called. In order to know what is expectation in the current call, the function can use the slightly incorrectly named wantarray function.

However Perl can be a lot more precize telling a function what is expected from it. Using the Want module the function can know exactly how many values it needd to return.

Once again, I have to talk you about Paul "Leonerd" Evans 😃

He is the author of the video that I will review now and I have to say first that I consider that we are lucky to have such brilliant guy in Perl community 👍 💪

The video is titled Perl in 2025 and is actually a list of open questions about Perl new operators in near future.

Leonerd goes a bit fast, but I really enjoyed the video.

isa, signatures

I won't discuss this part, it is stable and coming in the core soon, but he explained these things, and it was very clear.

Smart match

I started Perl when smart match (~~) was already around (and already not recommended to the usage).
Smartmatch

I used them a bit (I was young and bold at that time 😀) then quickly followed the recommendations and forbid myself to use them.

But what were my needs to use smartmatch?

First, it was to emulate "is in" ("Is this value in this array?"). Yes it can be done with other operators or CPAN module but ~~ seemed so short and elegant...

Second, as explained by Paul, another hidden usage of ~~ is internally in given/when construction (that I don't used so much at the end).

I would actually have loved to continue to use smartmatch, but I'm a prudent programmer so one warning was sufficient to make me run away and totally forget about this construction 😂

Sharpy equalities

Leonerd then discusses also about new operators equ and === that I unilaterally decided to name "nervous equalities" or "sharpy equalities" (maybe it sounds terribly bad, but yes I'm not a native english speaker 😀).

The need for them comes from smartmatch (watch the video to know why!) but extends to simplify basic comparisons (if(defined $var and $var eq "perl")).

It appeared to me to be at first a very sharp usage, but finally it seems very cool:

if("" eq undef) { # it is true
    ...
}
if("" equ undef) { # it will be false
    ...
}
Enter fullscreen mode Exit fullscreen mode

The same way with numeric ===:

if(0 == undef) { # it is true
    ...
}
if(0 === undef) { # it will be false
    ...
}
Enter fullscreen mode Exit fullscreen mode

any and in

any and in would cover the need (dig into lists) that I previously mentioned.

Leonerd presents in as a possible metaoperator that you can "parametrize" to choose how it behaves (a bit crazy in a Raku way).

By detailing any, in, given/when, and friends, I understand the difficulty it was to properly implement smartmatch (that contains all these things).

Multi dispatch

The same way, "multi dispatch" makes me think again of Raku which is amazing on this.

I wondered what dispatch mechanism was already implemented in Perl, since we already have a notion of Method Resolution Order. The answer is that there is dispatch mechanism but limited to Oriented Object Programming.

What if we try to do multi sub dispatch in the same package?

With prototypes, if you try something like:

sub a() { print "a\n"; }
sub a($) { print "aa\n"; }
Enter fullscreen mode Exit fullscreen mode

Unfortunately you will get an error:

Prototype mismatch: sub main::a () vs ($) at multi.pl line 2.
Enter fullscreen mode Exit fullscreen mode

With signatures, if you try something like:

use v5.20;
use feature qw(signatures);
no warnings qw(experimental::signatures);

sub b() { print "b\n"; }
sub b($arg) { print "bb\n"; }

b();
b("myarg");
Enter fullscreen mode Exit fullscreen mode

The latest declaration will override the previous one and you can get Too few arguments for subroutine or Too many arguments for subroutine depending the order you declared the sub b.

@mjgardner (and others) do not hesitate to correct me, you master better than me all these things.

You can still use the flexibility of Perl and handle dispatch inside the sub, but it is not properly native dispatch.

Back to the MRO (Method Resolution Order), Perl MRO is by default implemented using DFS (Depth First Search) but can be configured to use C3 from the CPAN module C3.
Python or Raku use C3 algorithm as default impementation.

Then as a summary, Paul discusses about adding multi dispatch (i.e. method overriding or polymorphism in the same package) and he proposes implementations based on signatures, isa and is (that I do not talked but is is a part of possible new ops).

My thought is... It would be nice! 😃

All things together

This is a great talk, that opens the door to discussion and implementations.

All

As a conclusion, thank you again Leonerd!

That was the last time I talked about you... for today 😀

Here are solutions to this weeks challenges from the Perl Weekly Challenge.

You can find my full code on Github

Task 1: Pack a Spiral

You are given an array @A of items (integers say, but they can be anything).

Your task is to pack that array into an MxN matrix spirally counterclockwise, as tightly as possible.

‘Tightly’ means the absolute value |M-N| of the difference has to be as small as possible.

(1..4)  ->  4 3
            1 2
(1..6)  ->  6 5 4   5 4
            1 2 3   6 3
                    1 2
                   
(1..12) ->  9  8  7  6    8  7  6
           10 11 12  5    9 12  5
            1  2  3  4   10 11  4
                          1  2  3

The solution

No attempting at real golfing this week - but still want to keep it "minimalist"...

Our pack_spiral routine starts by finding the largest factor of the size of the list below sqrt of the size of the list. The two dimensions we will need are this ($rows) and $cols. Just for compactness when printing we chose it so that $rows < $cols

sub pack_spiral {
  my( $rows )               = reverse grep { ! (@_ % $_) } 1 .. sqrt @_;
  my( $cols, $r, $c, @out ) = ( @_/$rows, $rows-1, -1 );

while( @_ ) { # do until empty
$out[ $r ][ ++$c ] = shift foreach 1 .. $cols--; # >>
$out[ --$r ][ $c ] = shift foreach 1 .. --$rows; # ^^
last unless @_; # exit if empty
$out[ $r ][ --$c ] = shift foreach 1 .. $cols--; # <<
$out[ ++$r ][ $c ] = shift foreach 1 .. --$rows; # vv
}
return \@out;
}


Notes: shift by itself shifts off the magic "@_" array - so in our cases takes the next item of the list...

You can see the progress below:

       [__]  [__]  [__]  [__] 

[__] [__] [__] [__]

(st) [__] [__] [__] [__]

$rows = 3; $cols = 4; $r = 2; $c = -1; @_=12;
$out[ $r ][ ++$c ] = shift foreach 1 .. $cols--;
< 4 >
[__] [__] [__] [__]

[__] [__] [__] [__]

st ->[_1]->[_2]->[_3]->(_4)

$rows = 3; $cols = 3; $r = 2; $c = 3; @_=8;
$out[ --$r ][ $c ] = shift foreach 1 .. --$rows;
< 2 >
[__] [__] [__] (_6)
^^
[__] [ ] [ ] [_5]
^^
st [_1]->[_2]->[_3]->[_4]

$rows = 2; $cols = 3; $r = 0; $c = 3; @_=6;
$out[ $r ][ ++$c ] = shift foreach 1 .. $cols--;
< 3 >
(_9)<-[_8]<-[_7]<-[_6]
^^
[__] [ ] [ ] [_5]
^^
st [_1]->[_2]->[_3]->[_4]

$rows = 2; $cols = 2; $r = 0; $c = 0; @_=3;
$out[ ++$r ][ $c ] = shift foreach 1 .. --$rows;
< 1 >

[_9]<-[_8]<-[_7]<-[_6]
vv ^^
(10) [ ] [ ] [_5]
^^
st [_1]->[_2]->[_3]->[_4]

$rows = 1; $cols = 2; $r = 1; $c = 0; @_=1;
$out[ $r ][ ++$c ] = shift foreach 1 .. $cols--;
< 2 >
[_9]<-[_8]<-[_7]<-[_6]
vv ^^
[10]->[11]->(12) [_5]
^^
st [_1]->[_2]->[_3]->[_4]

$rows = 1; $cols = 1; $r = 1; $c = 2; @_=0;
$out[ --$r ][ $c ] = shift foreach 1 .. --$rows; # does nothing..
< 0 >

[_9]<-[_8]<-[_7]<-[_6]
vv ^^
[10]->[11]->(12) [_5]
^^
st [_1]->[_2]->[_3]->[_4]

Task 2: Origin-containing Triangle

You are given three points in the plane, as a list of six co-ordinates: A=(x1,y1), B=(x2,y2) and C=(x3,y3).

Write a script to find out if the triangle formed by the given three co-ordinates contain origin (0,0).

Print 1 if found otherwise 0.

Input: A=(0,1) B=(1,0)  C=(2,2)   Output: 0
Input: A=(1,1) B=(-1,1) C=(0,-3)  Output: 1
Input: A=(0,1) B=(2,0)  C=(-6,0)  Output: 1

The solution

One of the uses I put my degree to at work was to use "Winding numbers" to replicate image maps in web pages {we needed to implement drag features and click feature on an image}... So winding numbers are what I will use here...

Winding number - imaging you are a dalek standing at the origin - and you trace around the triangle with your gunstick... If your head turns a full 360 either way then you are in the triangle - if it does not you are outside the triangle! This extends to any shape - you are inside the shape if you take an odd number of turns - outside if you take an even number.

sub winding_number {
  my ( $a, $b, $wn ) = @_[ -2, -1 ], 0;

while( my($x,$y) = splice @_, 0, 2 ) {
$wn += $a<=0 ? $y>0 && $a*$y-$x*$b > 0 ? 1 : 0
: $y<=0 && $a*$y-$x*$b <= 0 ? -1 : 0;
($a,$b)=($x,$y);
}
return $wn%2;
}

our

In Perl the our keyword is used to declare one or more package variables. More exactly it creates lexical alias to a packaga variable, but for our practical purposes our means we are allowed to use the package variable without giving the fully qualified name and without violating the rules of use strict.

With that out of the way, in most cases, you'd want to declare variables in a lexical scope using the my keyword.

my

In Perl the my keyword is used to declare one or more lexical variables. That is variables that are scoped to the enclosing block of curly braces. There are also package variables in Perl that are declared using the our keyword.

q

q behaves just like single quotes ' do, but they make it easy to include other single-quotes in a string without the need to escape them.

qq

qq behaves just like double quotes " do, they interpolate variables, but they make it easy to include double-quotes in a string without the need to escape them.

I always have to search how to generate a random integer number between a range because this is a common task that I use a lot in tests, but really, I can't memorize it.

Though, this is how I would do it in 2021.

use v5.16;
use strict;
use warnings;

# Class definition
package Random::Range {
  use Zydeco;
  class Integer {
    method pick ( Int $min, Int $max ) {
      return $min + int ( rand ( $max - $min ));
    }
  }
}

# Script
say Random::Range->new_integer->pick(1, 100);
#==> 42 
Enter fullscreen mode Exit fullscreen mode

So what did we do here? We used the rand function where we applied the int function, so we would get an integer, not a fractional number. The small calculation makes possible to restrict the result to the desired interval.

All of this is glued into a minimal Zydeco class that adds a very nice object-oriented interface. You maybe don't need Zydeco, this simple one-liner would work:

perl -le 'my @interval = (1, 100); print $interval[0] + int ( rand ( $interval[1] - $interval[0] ))'  
Enter fullscreen mode Exit fullscreen mode

Note this is not cryptographically secure and should only be used in simple cases: if you need a secure implementation, please check some appropriate solutions on CPAN.

Art: digital painting by myself.

Failure is a universal truth of computers. Files fail to open, web pages fail to load, programs fail to install, messages fail to arrive. As a developer you have no choice but to work in a seemingly hostile environment in which bugs and errors lurk around every corner.

Hopefully you find and fix the bugs during development and testing, but even with all bugs squashed exceptional conditions can occur. It’s your job as a Perl developer to use the tools available to you to handle these exceptions. Here are a few of them.

eval, die and $EVAL_ERROR ($@) (updated)

Perl has a primitive but effective mechanism for running code that may fail called eval. It runs either a string or block of Perl code, trapping any errors so that the enclosing program doesn’t crash. It’s your job then to ignore or handle the error; eval will return undef (or an empty list in list context) and set the magic variable $@ to the error string. (You can spell that $EVAL_ERROR if you use the English module, which you probably should to allow for more readable code.) Here’s a contrived example:

use English;

eval { $foo / 0; 1 }
  or warn "tried to divide by zero: $EVAL_ERROR";
Enter fullscreen mode Exit fullscreen mode

(Why the 1 at the end of the block? It forces the eval to return true if it succeeds; the or condition is executed if it returns false.)

What if you want to purposefully cause an exception, so that an enclosing eval (possibly several layers up) can handle it? You use die:

use English;

eval { process_file('foo.txt'); 1 }
  or warn "couldn't process file: $EVAL_ERROR";

sub process_file {
    my $file = shift;
    open my $fh, '<', $file
      or die "couldn't read $file: $OS_ERROR";

    ... # do something with $fh
}
Enter fullscreen mode Exit fullscreen mode

It’s worth repeating that as a statement: You use exceptions so that enclosing code can decide how to handle the error. Contrast this with simply handling a function’s return value at the time it’s executed: except in the simplest of scripts, that part of the code likely has no idea what the error means to the rest of the application or how to best handle the problem.

autodie (updated)

Since many of Perl’s built-in functions (like open) return false or other values on failure, it can be tedious and error-prone to make sure that all of them report problems as exceptions. Enter autodie, which will helpfully replace the functions you choose with equivalents that throw exceptions. Introduced in Perl 5.10.1, it only affects the enclosing code block, and even goes so far as to set $EVAL_ERROR to an object that can be queried for more detail. Here’s an example:

use English;
use autodie; # defaults to everything but system and exec

eval { open my $fh, '<', 'foo.txt'; 1 } or do {
    if ($EVAL_ERROR
      and $EVAL_ERROR->isa('autodie::exception') {
        warn 'Error from open'
          if $EVAL_ERROR->matches('open');
        warn 'I/O error'
          if $EVAL_ERROR->matches(':io');
    }
    elsif ($EVAL_ERROR) {
        warn "Something else went wrong: $EVAL_ERROR";
    }
};
Enter fullscreen mode Exit fullscreen mode

try and catch

If you’re familiar with other programming languages, you’re probably looking for syntax like try and catch for your exception needs. The good news is that it’s coming in Perl 5.34 thanks to the ever-productive Paul “LeoNerd” Evans; the better news is that you can use it today with his Feature::Compat::Try module, itself a distillation of his popular Syntax::Keyword::Try. Here’s an example:

use English;
use autodie;
use Feature::Compat::Try;

sub foo {
    try {
        attempt_a_thing();
        return 'success!';
    }
    catch ($exception) {
        return "failure: $exception"
          if not $exception->isa('autodie::exception');

        return 'failed in ' . $exception->function
          . ' line ' . $exception->line
          . ' called with '
          . join ', ', @{$exception->args};
    }
}
Enter fullscreen mode Exit fullscreen mode

Note that autodie and Feature::Compat::Try are complementary and can be used together; also note that unlike an eval block, you can return from the enclosing function in a try block.

The underlying Syntax::Keyword::Try module has even more options like a finally block and a couple experimental features. I now prefer it to other modules that implement try/catch syntax like Try::Tiny and TryCatch (even though we use Try::Tiny at work). If all you need is the basic syntax above, using Feature::Compat::Try will get you used to the semantics that are coming in the next version of Perl.

Other exception modules (updated)

autodie is nice, and some other modules and frameworks implement their own exception classes, but what if you want some help defining your own? After all, an error string can only convey so much information, may be difficult to parse, and may need to change as business requirements change.

Although CPAN has the popular Exception::Class module, its author Dave Rolsky recommends that you use Throwable if you're using Moose or Moo. If you’re rolling your own objects, use Throwable::Error.

Using Throwable couldn’t be simpler:

package Foo;

use Moo;
with 'Throwable';

has message => (is => 'ro');

... # later...

package main; 
Foo->throw( {message => 'something went wrong'} );
Enter fullscreen mode Exit fullscreen mode

And it comes with Throwable::Error, which you can subclass to get several useful methods:

package Local::My::Error;
use parent 'Throwable::Error';

... # later...

package main;
use Feature::Compat::Try;

try {
    Local::My::Error->throw('something bad');
}
catch ($exception) {
    warn $exception->stack_trace->as_string;
}
Enter fullscreen mode Exit fullscreen mode

(That stack_trace attribute comes courtesy of the StackTrace::Auto role composed into Throwable::Error. Moo and Moose users should simply compose it into their classes to get it.)

Testing exceptions with Test::Exception

Inevitably bugs will creep in to your code, and automated tests are one of the main weapons in a developer’s arsenal against them. Use Test::Exception when writing tests against code that emits exceptions to see whether it behaves as expected:

use English;
use Test::More;
use Test::Exception;

...

throws_ok(sub { $foo->method(42) }, qr/error 42/,
  'method throws an error when it gets 42');
throws_ok(sub { $foo->method(57) }, 'My::Exception::Class',
  'method throws the right exception class');

dies_ok(sub { $bar->method() },
  'method died, no params');

lives_and(sub { is($baz->method(17), 17) },
  'method ran without exception, returned right value'); 

throws_ok(sub { $qux->process('nonexistent_file.txt') },
  'autodie::exception', # hey look, it's autodie again
  'got an autodie exception',
);
my $exception = $EVAL_ERROR;
SKIP: {
    skip 'no autodie exception thrown', 1
      unless $exception
      and $exception->isa('autodie::exception');
    ok($exception->match(':socket'),
      'was a socket error:' . $exception->errno);
}

done_testing();
Enter fullscreen mode Exit fullscreen mode

Note that Test::Exception’s functions don’t mess with $EVAL_ERROR, so you’re free to check its value right after you call it.

Documenting errors and exceptions

If I can leave you with one message, it’s this: Please document every error and exception your code produces, preferably in a place and language that the end-user can understand. The DIAGNOSTICS section of your documentation (you are writing documentation, right, not just code comments?) is a great candidate. You can model this section after the perldiag manual page, which goes into great detail about many of the error messages generated by Perl itself.

(A previous version of this article did not note that one should make sure a successful eval returns true, and incorrectly stated that Class::Exception and Throwable were deprecated due to a bug in the MetaCPAN web site. Thanks to Dan Book for the corrections.)

We sent the below email to all the CPAN Mirror contacts yesterday:

An Important Update about the CPAN Mirror List

You're receiving this email because you're listed as a contact point for a CPAN mirror. Thank you! The mirror network has been a huge part of CPAN’s success. Soon, the way clients use CPAN mirrors is changing. You don't need to do anything, but after reading this email, you might want to.

Some background: For a long time, when the CPAN client (aka CPAN.pm) started up for the first time, it prompted users to configure it by picking a nearby mirror. The assumption was that it would be best to find a geographically nearby mirror. This necessitated the keeping of a central list of mirrors which the client could retrieve and offer as a menu. That's the CPAN Mirror List, maintained by the Perl NOC.

In 2011, the client changed behavior to configure itself automatically, meaning that most new users never saw this list. Furthermore, www.cpan.org was pointed at a global CDN, meaning that traffic could be routed efficiently without client configuration. The CDN also meant that users wouldn’t need to worry about out of date or down mirrors..

After ten years of CPAN defaulting to the CDN, we are going to stop maintaining the mirror list. It will still be present, but have only one entry: www.cpan.org. This means that anyone attempting to pick a mirror from the list will only find this one option. The mirror status site will be replaced with a static page. As has always been the case, the CPAN client can be configured manually to use any mirror, whether or not it's on the mirror list.

Users who have configured their CPAN clients to point at your mirror will continue to hit it. No new users are likely to find it -- but after all, they were already very unlikely to do so! That said, you do not need to shut down your mirror. If you use your mirror, you can keep mirroring. We’re not removing or changing the ability to mirror. If you know you have users of your mirror who would like to keep using it, please feel free to keep mirroring it.

On the other hand, if you would like to stop mirroring CPAN, feel free to do that, too. Clients have always had to deal with their mirror going away, and they will be fine if you choose to shut down your mirror.

We have not set a firm date for the emptying of the mirror list, but we expect it to happen no earlier than mid-February and no later than June 2021.

If you have any questions, please email us at <cpan at perl.org>.

Concerned this is fake? A copy of this email can be found at https://log.perl.org/2021/02/cpan-mirror-list-changes.html.

Finally: Thanks! The mirror network helped make CPAN practical for many years, and CPAN helped make Perl a success. You were part of this endeavor, and we appreciate it! 

-- The CPAN Mirror List Admins

 

I once was looking to filter out CPAN modules per namespace. Namespaces generally have meaning in CPAN since there are conventions and Perl folks try to be rigourous and to fit well in the existing naming

So back again to my research, I was looking for a way to filter out CPAN modules per namespaces.

Become the master of MetaCPAN search

From METACPAN faq you can get some tips like the module: prefix
MetaCPAN tips

With this trick, you can search for instance all XML related modules

It works well, but does not achieve exactly what I want since it returns me also for instance the SVG::XML which is not actually prefixed by XML::
Problem

CPANMeta the great

By asking on the good old IRC, I get a solution thanks to CPANMeta

You can then list all XML::* modules
CPANMeta

Manual grep

The quick and dirty hack!

I downloaded the 02packages.details.txt file from CPAN.org

Then using a grep

grep "^XML::" 02packages.details.txt
Enter fullscreen mode Exit fullscreen mode

And the output is a long list of modules:

XML::XSS                         v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Comment                v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Document               v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Element                v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::ProcessingInstruction  v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Role::Renderer         v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Role::StyleAttribute   v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::StyleAttribute         v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Stylesheet::HTML2TD    v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Template               v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XSS::Text                   v0.3.5  Y/YA/YANICK/XML-XSS-0.3.5.tar.gz
XML::XUpdate::LibXML           0.006000  P/PA/PAJAS/XML-XUpdate-LibXML-0.6.0.tar.gz
XML::YYLex                         0.04  B/BO/BOEWE/XML-YYLex-0.04.tar.gz
Enter fullscreen mode Exit fullscreen mode

More experiments

I tried also to use CPAN::02Packages::Search but it seems to only allow exact match.

Look at this working code

#!/usr/bin/env perl

use CPAN::02Packages::Search;
use Data::Dumper;

my $index = CPAN::02Packages::Search->new(file => './02packages.details.txt');
my $res = $index->search('Plack'); 

print Dumper($res);
Enter fullscreen mode Exit fullscreen mode

I tried to tweak it with $index->search('XML::*'); or $index->search('XML::.*'); but it is not valid 😕

CPAN::Common::Index::Mirror is promising to do the job according to the documentation
Index

But I was not able to make it work at first 😃

I started with this code snippet

#!/usr/bin/env perl

use CPAN::Common::Index::Mux::Ordered;
use Data::Dumper;

my $index = CPAN::Common::Index::Mux::Ordered->assemble(
    MetaDB => {},
    Mirror => { mirror => "http://cpan.cpantesters.org" },
);

my $result = $index->search_packages( { package => 'XML::LibXML' } );

print Dumper($result);
Enter fullscreen mode Exit fullscreen mode

And tried various XML::* and XML::.* and /^XML::.*/ and m/^XML::.*/ and the same with - instead of :: but no way 😬

Thanks to @grinnz , I get it!

#!/usr/bin/env perl

use CPAN::Common::Index::Mux::Ordered;
use Data::Dumper;

my $index = CPAN::Common::Index::Mux::Ordered->assemble(
    MetaDB => {},
    Mirror => { mirror => "http://cpan.cpantesters.org" },
);

my @result = $index->search_packages( { package => qr/^XML::/ });

print Dumper(@result);
Enter fullscreen mode Exit fullscreen mode

That will returns several packages:

$VAR2326 = {
             'version' => 'undef',
             'package' => 'XML::XSH::Parser',
             'uri' => 'cpan:///distfile/CHOROBA/XML-XSH-1.8.6.tar.gz'
           };
$VAR2327 = {
             'version' => '0.48',
             'package' => 'XML::XSLT',
             'uri' => 'cpan:///distfile/JSTOWE/XML-XSLT-0.48.tar.gz'
           };
$VAR2328 = {
             'package' => 'XML::XSLT::DOM::TextDOE',
             'version' => '0.31',
             'uri' => 'cpan:///distfile/MAHEX/XML-XSLT-0.31.tar.gz'
           };
Enter fullscreen mode Exit fullscreen mode

I see there are also some other possible alternatives like App::CPANIDX or maybe CPANDB?

MetaCPAN native treeview

I wonder if it should not simply be part of MetaCPAN. I other words a native tree view in MetaCPAN 💃

Maybe I'm missing a point, but a feature like this would make me happy for a while.

What about something like
CPAN treeview

What do you think?

Not all jobs are created equal. Sure, most pay the bills, but some do more. They impart a sense of purpose; when you log out at day’s end, it’s with the satisfaction that you are part of something bigger, something more important than yourself. You’ve left the world a little better than you found it, and isn’t that what life is really about?
Looking for Perl developers with a strong background in Modern Perl – you should be comfortable with Moose and PSGI/Plack, and a solid grounding in using Perl’s testing tools. Our client has opened a new office in Belarus. This role offers a unique opportunity to join an established company in a new space.
If your mouth is watering at the thought of joining this dynamic team and you’re a senior Perl programmer with a solid understanding of Go programming languages, they just might set a place for you at the table.
The client is interested in anyone with experience building web apps in Perl, using one of the major Perl frameworks. If you’re a crack-hand with Catalyst, a Mojolicious master, or a distinguished Dance, they want you. You’ll be deploying apps your work to AWS, so experience would be handy, and the company’s big on testing, so they’d like you to know your way around Test::More.
Our client takes the legwork out of the hunt for the best bargain, offering one of the largest product and price comparison platforms in German-speaking countries. They’re looking for a heroic Perl programmer to develop and deliver quality content and all the info users need to find their gadgets for the right price.
Online 9-11 June 2021.
It will take place online between March 24-26 2021. The private ticket will be cheaper (EUR 30). People who register in time and transfer the participation fee, will get exclusive extras.
Thursday, March 4, 2021
Wednesday, February 18, 2021
Thursday, February 25, 2021
Wednesday, February 24, 2021

Rex

Ferki taught me a few things about Rex and now we are planning a live session in which he is going to teach me a lot more. Follow my Twitch channel to get notified.
Some of the distributions on CPAN are marked as 'looking for maintainer'. Test::Class displayed this message, so I asked for it and became the maintainer of that module. Then came the question, how can I remove the notifiaction about the need for a maintainer. In this video you will see how to add this explanation to the FAQ of MetaCPAN and then how to add a link from the notification banner to this entry in the FAQ.
In this episode, you'll learn how to accept a one time payment with stripe-perl aka Net::Stripe.
Celebrating the 100th week of The Weekly Challenge.
Please find all the talks recorded at the recently-held FOSDEM conference.
In Perl warn and die tell us where a problem was noticed. carp and croak tell us where it was created.
List::GroupBy is a small module converting a list of hashes to some multi-level hash tabele. This is a code-reading video.
Luis' one-liner is easily decodable and does the job.
Simon came up with a cryptic one-liner. Decoding one-liners is always fun.
It is pretty evident that Roger doesn't like Perl one-liners. He came up with detailed solution as always.
Luca shares his Raku skill and presented some Raku magic.
Laurent's modular approach is always very elegant. Thanks for sharing.
Lance presented us a double bonus this week, thank you.
Lance promotes TDD with great precision. Thanks for the kind words.
James turned out to be a big fan of Perl one-liners. I loved his code.
I enjoy the story behind the solution. The solution itself is so trivial.
Flavio's beautifully laid out solution is very pleasing.
Dave's contribution is always verbose and his blog posts explain every minute detail.
Colin uses modulo to solve the fun time task; a very different approach.
As always, Arne's blog post is full of Raku tricks. You don't want to miss it.
Andinus use of Grammar is a great example.
Adam also shows his regex skill while dealing with this week's task.
Abigail's use of map to read the input numbers is interesting.
Abigail shows his one-liner skill with great detail.
Aaron is becoming a master of the one-liner in Perl. It is always fun to decode his code.
Enjoy a quick recap of last week's contributions by Team PWC dealing with the "Fun Time" and "Triangle Sum" tasks in Perl and Raku. You will find plenty of solutions to keep you busy.
Welcome to a new week with a couple of fun tasks "Pack a Spiral" and "Origin-containing Triangle". If you are new to the weekly challenge then why not join us and have fun every week. For more information, please read FAQ page.
Do you want to inline Fortran in your Perl script?
libdeflate compression library turned into a CPAN module:
Import/export plain Excel (XLSX) files as simply as possible.
Convenience wrapper around Net::Curl::Easy
Please do share your opinion on the subject.
If you have followed the Corinna project and have thoughts about it being in the Perl core, then why not share with the team?
An interesting use case for WebSockets.
Detailed guide to setting up Mojolicious using Vagrant.
Find out how blogging can help to promote Perl.
Mark continued playing with method signatures.
Ricardo shared the good news with us.
This video demonstrates how to use ActiveState Platform’s CLI interface, the State Tool to install Perl environments generally. For purposes of this demo, we compare two web frameworks: Mojolicious versus Dancer. Take a look!

Hi there

What an honour to present the 500th edition of the Perl Weekly newsletter. Thank you Gabor Szabo.

Let's begin the week with the good news, rt.cpan.org is staying. You can find more details here.

Andrew Shitov raised an issue with regard to creating separate entity - "The Raku Foundation". Feel free to share your views on the subject.

Did you know Cor has been given a new name, Corinna?

Curtis Poe recently requested the general public to share their views about Corinna being in the Perl core. Please do checkout the wiki page

This week, we celebrated the 100th week of The Weekly Challenge. I even created YouTube Video to thank Team PWC for their support and encouragements.

After a long time, I finally got the opportunity to try Pair Programming thanks to my friend, Julien Fiegehenn. We spent an hour and half and got MooX::Clone released to CPAN in the end. It all started when I was working on my latest project Design Patterns using Modern Perl, more specifically, Prototype Design Pattern where I was looking for a clean interface to create a clone of Moo object.

Zum ersten Mal teilen wir Blogs in nicht-englischer Sprache. Ich hoffe es würde unseren deutschen Lesern gefallen.

Enjoy the rest of the newsletter.

Regex

"Regex" is the small name of Regular expressions

Regex are one of the superpowers 💪 of Perl
Perl <3 Regex

It's a productivity superpower the same way knowing command line shortcuts and mastering vim.

Regex could become one of your programmer superpowers also if you decide to.
True power

But "regex" have also a nefarious reputation because they are hard, error-prone and misused.
100

Damian Conway is a master of regular expressions but you can sometimes feel the pain in his mouth when he discusses regex
Pain

Or even
Misery

But on a more positive note, Damian said
WrongButGoodEnough

It could be strange to advocate a wrong thing but sometimes you just don't need more than a one shot program, and for me it would be dumb (or irresponsible) to spend more time than needed just "for the sake of correctness".
David Goodenough

I know it's not really the hype of these days where over engineering is better perceived than KISS principles (I exaggerate just a little) but it is pragmatism.

Regex are bad

Regex are bad, everybody knows, and here is the very famous SO answer "You can't parse [X]HTML with regex" about that 😀
Idiot

Are they really?

Some people have played the "devil's advocate" and came with regex for XML like this great answer from Tom Christiansen where he used regex to tokenize then Perl to parse.

But even Tom Christiansen said
Should

Seems also like PCRE are more than simple regular grammars but actually I can't say if mathematically Perl regex can or can't parse XML, regular expression page on wikipedia says that
Regular not regular

Another interesting old link on this topic is REX. The abstract of it is

The syntax of XML is simple enough that it is possible to parse an XML document into a list of its markup and text items using a single regular expression. Such a shallow parse of an XML document can be very useful for the construction of a variety of lightweight XML processing tools

(I do not quoted this one on a picture since I'm too afraid to awake Cthulhu)

Then what are regex recommended for

While use of complex regex are subject to discussions, there are perfect and obvious use cases for regex:

  • Validation of input
  • Cleaning of input
  • Restructuring of input
  • Looking for substrings within input

Folklore

I discussed about WrongButGoodEnough regex that help you save the world on a Friday evening:
Save

But writing regex is hard to master and you probably don't
Trial

One solution is to leave your cat typing the regex for you!
Cat regex

Perl folks are crazy about regex

I wanted to finish with this crazy fact, fasten your seat belts.

Perl folks are really serious about regex
Serious

This is mad.

These are some answers to the Week 100 of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Task 1: Fun Time

You are given a time (12 hour / 24 hour).

Write a script to convert the given time from 12 hour format to 24 hour format and vice versa.

Ideally we expect a one-liner.

Example 1:

Input: 05:15 pm or 05:15pm
Output: 17:15

Example 2:

Input: 19:15
Output: 07:15 pm or 07:15pm

Well, I like concise code, but I don’t think it makes real sense to try to pack this task into a one-liner. I have no doubt that it can be done, but it will either be not a real one-liner (like a pipeline chaining multiple statements into one expression), or a difficult to understand golfing attempt. So, I will not try to do a one-liner.

Fun Time in Raku

We use a regex to detect whether the input string matches “am” or “pm”; if so, we remove that “am” or “pm” string and add 12 hours if the matched string was “pm”; otherwise, we subtract 12 from the hour part it if is larger than 12 and add “pm” or “am” depending on the case.

use v6;

my $time = @*ARGS[0];
if $time ~~ /(<[ap]>)m/ {
    if $0 eq 'a'  {
        $time ~~ s/(\d\d':'\d\d).*/$0/;
    } else {
        $time ~~ s/(\d\d)':'(\d\d).*/{$0 + 12}:$1/;
    }
} else {
    $time ~~ /^(\d\d)':'(\d\d)/;
    my ($suffix, $hour) = $0 > 12 ?? ('pm', $0 - 12) !! ('am', $0);
    $time = "$hour:$1 $suffix";
}
say $time;

These are some execution examples with various input strings:

$ raku fun-time.raku '10:54'
10:54 am
-
$ raku fun-time.raku '17:54'
5:54 pm
-
$ raku fun-time.raku '10:54 pm'
22:54
-
$ raku fun-time.raku '10:54 am'
10:54

Fun Time in Perl

This is a port to Perl of the Raku program just above:

use strict;
use warnings;
use feature "say";

my $time = shift;
if ($time =~ /([ap])m/) {
    if ($1 eq 'a')  {
        $time =~ s/(\d\d:\d\d).*/$1/;
    } else {
        $time =~ /(\d\d):(\d\d.).*/;
        my $hour = $1 + 12;
        $time = "$hour:$2";
    }
} else {
    $time =~ /^(\d\d):(\d\d)/;
    my ($suffix, $hour) = $1 > 12 ? ('pm', $1 - 12) : ('am', $1);
    $time = "$hour:$2 $suffix";
}
say $time;

And some execution examples:

$ perl fun-time.pl '10:54 pm'
22:54

$ perl fun-time.pl '10:54 am'
10:54

$ perl fun-time.pl '10:54'
10:54 am

$ perl fun-time.pl '15:54'
3:54 pm

Task 2: Triangle Sum

You are given triangle array.

Write a script to find the minimum path sum from top to bottom.

When you are on index i on the current row then you may move to either index i or index i + 1 on the next row.

Example 1:

Input: Triangle = [ [1], [2,4], [6,4,9], [5,1,7,2] ]
Output: 8

Explanation: The given triangle

            1
           2 4
          6 4 9
         5 1 7 2

The minimum path sum from top to bottom:  1 + 2 + 4 + 1 = 8

             [1]
           [2]  4
           6 [4] 9
          5 [1] 7 2

Example 2:

Input: Triangle = [ [3], [3,1], [5,2,3], [4,3,1,3] ]
Output: 7

Explanation: The given triangle

            3
           3 1
          5 2 3
         4 3 1 3

The minimum path sum from top to bottom: 3 + 1 + 2 + 1 = 7

             [3]
            3  [1]
           5 [2] 3
          4 3 [1] 3

Triangle Sum in Raku

We use the traverse recursive subroutine to find the smallest path through the triangular array:

use v6;

my @triangle = (1), (2,4), (6,4,9), (5,1,7,2);
my @min-path = map { $_[0] }, @triangle; # pick any path
my $min-path-val = @min-path.sum;
my $index = 0;
traverse @triangle, (), $index;
say @min-path;

sub traverse (@triangle, @path, $index) {
    my @first-line = @triangle[0];
    my @new-triangle = @triangle[1 .. @triangle.end];
    say "First-line: ", @first-line;
    my @new-path = | (@path, @first-line[$index]);
    say @new-path, "  ", "\n";
    if @new-triangle.elems > 0 {
        traverse(@new-triangle, @new-path, $index);
        traverse(@new-triangle, @new-path, $index + 1);
    } else {
        my $new-path-val = @new-path.sum;
        if $new-path-val < $min-path-val {
            @min-path = @new-path;
            $min-path-val = $new-path-val
        }
    }
}

Output:

$ raku triangle-sum.raku 1 2 4 1

Triangle Sum in Perl

Except for the fact that we define also a sum subroutine, this essentially the same Raku algorithm ported to Perl:

use strict;
use warnings;
use feature "say";

my $triangle = [ [1], [2,4], [6,4,9], [5,1,7,2] ];
# $triangle = [ [1], [2,4], [6,30,9], [30,30,30,2] ];
my $min_path = [ map { $_->[0] } @$triangle];
my $min_path_val = sum($min_path);
my $index = 0;
find_min_path($triangle, [], $index);
say "@$min_path";

sub sum {
    my $aref = shift;
    my $sum = 0;
    $sum += $_ for @$aref;
    return $sum;
}

sub find_min_path {
    my ($tri_ref, $path, $index) = @_;
    my @triangle = @$tri_ref;
    my @first_row = @{$triangle[0]};
    my @new_triangle = @triangle[1 .. $#triangle];
    my $new_path = [ @$path, $first_row[$index] ];
    if (@new_triangle) {
        find_min_path([@new_triangle], $new_path , $index);
        find_min_path([@new_triangle], $new_path, $index + 1);
    } else { 
        my $new_path_val = sum($new_path);
        if ($new_path_val < $min_path_val) {
            $min_path = $new_path;
            $min_path_val = $new_path_val;
        }
    }
}

Output with the above input data:

$ perl  triangle-sum.pl
1 2 4 1

If you uncomment the second triangle definition, you get the following output:

$ perl  triangle-sum.pl
1 4 9 2

Wrapping up

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

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

Part 1

You are given a time (12 hour / 24 hour). Write a script to convert the given time from 12 hour format to 24 hour format and vice versa.

Solution


perl -e 'shift=~/(\d+):(\d\d\s*((am|pm)))/;if($1 < 12 && $3 eq "pm"){$h = $1 + 12}elsif($1 > 12 && $3 eq "pm"){$h = "0" . ($1 - 12)}else{$h = $1}print "$h:$2\n"' "17:15 pm"

Sample Run


perl -e 'shift=~/(\d+):(\d\d\s*((am|pm)))/;if($1 < 12 && $3 eq "pm"){$h = $1 + 12}elsif($1 > 12 && $3 eq "pm"){$h = "0" . ($1 - 12)}else{$h = $1}print "$h:$2\n"' "17:15 pm"
05:15 pm
perl -e 'shift=~/(\d+):(\d\d\s*((am|pm)))/;if($1 < 12 && $3 eq "pm"){$h = $1 + 12}elsif($1 > 12 && $3 eq "pm"){$h = "0" . ($1 - 12)}else{$h = $1}print "$h:$2\n"' "05:15 pm"
17:15 pm

Notes

Ok, so this isn;t going to win and Perl Golf competitions, that’s for sure! Frankly, this approach using regexes might not be the best for succinctly handling the bi-directionality.

For anyone that might not be familiar shift=~/(\d+):(\d\d\s*((am|pm)))/ means shift the first argument off of @ARGV (the command line arguments and then match against the regex. This is equivalent to $ARGV[0]=~/(\d+):(\d\d\s*((am|pm)))/.

Part 2

You are given triangle array. Write a script to find the minimum path sum from top to bottom. When you are on index i on the current row then you may move to either index i or index i + 1 on the next row.

Solution


use strict;
use warnings;

sub minimum_sum{
    my(@triangle) = @_;
    my($i, $j) = (0, 0);
    my $sum = $triangle[0]->[0]; 
    while($i < @triangle){
        unless(!exists($triangle[$i+1])){
            $j = ($triangle[$i+1]->[$j] >= $triangle[$i+1]->[$j+1]) ? $j+1 : $j; 
            $sum += $triangle[$i+1]->[$j]; 
        } 
        $i++;
    }  
    return $sum;
}

MAIN:{
    my(@TRIANGLE);
    @TRIANGLE = ([1], [2, 4], [6, 4, 9], [5, 1 , 7, 2]); 
    print minimum_sum(@TRIANGLE) . "\n"; 

    @TRIANGLE =([3], [3, 1], [5, 2, 3], [4, 3, 1, 3]); 
    print minimum_sum(@TRIANGLE) . "\n"; 
}

Sample Run


$ perl ch-2.pl 
8
7

Notes

I think this is a relatively well known greedy tactic. In order to minimize the total sum, make the minimum choice at each step.

References

Challenge 100

Despite rt.cpan.org still displaying the sunset message, it is in fact not going away forever on the 1st of March, but will have an 'extended downtime' while it is moved elsewhere. In future it'd be nice if communications of such things, and even allowing others to have a say on the matter, could be handled better.

See also:

Hi all,

I started the Inline::F2003 project in 2017 because I have a strong interest in modern Fortran and Perl programming.

The project features the Perl module Inline::F2003. This module allows modern Fortran source to be inlined and called from a Perl program. The module compiles the Fortran source and builds an executable shared library that is loaded into the Perl system.

Inline::F2003 is usually invoked at compile-time. The source fragment below shows typical use of the module.

use constant { BOOL_T => 1, BOOL_F => 0 };
use File::Spec;

use Inline F2003 => "DATA",
         ( FOR        => "gfortran",
           MAKEFILE   => "matopmul.mk",
           MAKEDIR    => File::Spec->curdir(),
           SRCLIST    => [ qw( ModMatrixOps.f03 ) ],
           DIRECTORY  => $main::InlineRoot,
           PRINT_INFO => BOOL_T );

I've uploaded a new version (1.03) to Sourceforge. The project home page is located at,

https://sourceforge.net/projects/inline-f2003/

If you are interested in Perl-Fortran interoperability I would encourage you to have a look and let me know what you think. At present the project only runs on Linux systems. All the documentation is contained in the file README.html. Please read it carefully to get a good understanding of the project.

Any comments/suggestions/questions are most appreciated.

Thank you!

It's often (for work or for personal projects) that I need to create a real-time feature for a website. This can range from a simple notification whenever an event happens on the server of an existing website, to implementing a real-time multiplayer game or adding a feature inspired from social media websites.

Unfortunately the increase in complexity in code (Perl & JS) and architecture involved in setting up a reliable solution, very often made me forego the opportunity to use WebSockets for many of these projects, and instead resorted to http polling to keep the solution simple for the others to maintain.

So I started looking for a library with a client & server component, that would make life easier. The library would hopefully have to have the following features:

  • Automatically reconnect to the WebSockets server, after a broken connection
  • Server channels that broadcast event streams that browsers can subscribe to, like Socket.io
  • A shared data object among all connected clients, that is always kept up to date, like Firebase
  • Automatic and transparent retrieval of all missed broadcast events after a temporary disconnect
  • Perl compatibility
  • Custom authorization routines, to decide who gets to join a channel
  • Free and open source self-hosted solution, for privacy so that it can be used in companies, plus because some customers don't like paying monthly subscription fees
  • Easy to use and set-up
  • (Optionally) allow requests/responses over the WebSocket connection

I couldn't find what I was looking for, so I made the solution:

The BoardStreams library

And I also created a demo site to show some of what's possible with this library:

https://boardstreams.com

That's all. I'm curious to see if you guys think this is interesting to you at all.

Last year The Perl Foundation participated in Outreachy May to August internships and it was successfully completed. We are looking to participate again this year.

At this stage we are looking for mentors and project ideas from the Perl and Raku community. If you are interested in becoming a mentor, please read the Mentor description and add your ideas at our repo. We plan to close our internal submission process on February 28th. Note that mentors are expected to spend 5-10 hours per week during the program period.

We also have a Perl/Raku Outreachy discussion forum at Google Groups.

Outreachy, formerly The Outreach Program for Women, was started by the GNOME Foundation in 2006 to encourage women to participate in the GNOME project. Since inception the project has grown to include many Free and Open Source organisations, including The Perl Foundation, and now the program has been rebranded and extended to encourage the participation of other underrepresented groups.

Outreachy explicitly invites applicants from around the world who are women (cis and trans), trans men, and genderqueer people. Additionally, they explicitly invite residents and nationals of the United States of any gender who are Black/African American, Hispanic/Latino, American Indian, Alaska Native, Native Hawaiian, or Pacific Islander. Anyone who faces systemic bias or discrimination in the technology industry of their country is invited to apply.

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

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.047004 on 2021-02-15
    • Votes: 13
    • Previous version: 2.047002 was 1 month, 16 days before
  2. Dumbbench - More reliable benchmarking with the least amount of thinking
    • Version: 0.501 on 2021-02-15
    • Votes: 13
    • Previous version: 0.111 was 3 years, 7 months, 28 days before
  3. ExtUtils::MakeMaker - Create a module Makefile
    • Version: 7.60 on 2021-02-17
    • Votes: 47
    • Previous version: 7.58 was 1 month, 27 days before
  4. GraphQL - Perl implementation of GraphQL
    • Version: 0.49 on 2021-02-15
    • Votes: 17
    • Previous version: 0.48 was 10 days before
  5. HTTP::Message - HTTP style message (base class)
    • Version: 6.28 on 2021-02-19
    • Votes: 59
    • Previous version: 6.27 was 1 month, 14 days before
  6. Log::Any - Bringing loggers and listeners together
    • Version: 1.709 on 2021-02-17
    • Votes: 58
    • Previous version: 1.708 was 1 year, 1 month, 4 days before
  7. Minion - Job queue
    • Version: 10.16 on 2021-02-16
    • Votes: 80
    • Previous version: 10.15 was 1 month, 13 days before
  8. Minion::Backend::SQLite - SQLite backend for Minion job queue
    • Version: v5.0.4 on 2021-02-16
    • Votes: 13
    • Previous version: v5.0.3 was 6 months, 14 days before
  9. Mojo::IRC - IRC Client for the Mojo IOLoop
    • Version: 0.46 on 2021-02-17
    • Votes: 12
    • Previous version: 0.45 was 2 years, 8 months, 10 days before
  10. Mojo::SQLite - A tiny Mojolicious wrapper for SQLite
    • Version: 3.005 on 2021-02-16
    • Votes: 23
    • Previous version: 3.004 was 6 months, 24 days before
  11. Mojolicious - Real-time web framework
    • Version: 9.01 on 2021-02-16
    • Votes: 444
    • Previous version: 8.73 was 10 days before
  12. Mojolicious::Plugin::AssetPack - Compress and convert css, less, sass, javascript and coffeescript files
    • Version: 2.11 on 2021-02-19
    • Votes: 47
    • Previous version: 2.10 was 2 months, 8 days before
  13. Mojolicious::Plugin::OAuth2 - Auth against OAuth2 APIs
    • Version: 1.59 on 2021-02-16
    • Votes: 16
    • Previous version: 1.58 was 1 year, 7 months, 13 days before
  14. Mojolicious::Plugin::OpenAPI - OpenAPI / Swagger plugin for Mojolicious
    • Version: 4.00 on 2021-02-17
    • Votes: 39
    • Previous version: 3.41 was 24 days before
  15. PDL - Perl Data Language
    • Version: 2.026 on 2021-02-13
    • Votes: 38
    • Previous version: 2.025 was 3 months before
  16. Test::Class - Easily create test classes in an xUnit/JUnit style
    • Version: 0.52 on 2021-02-17
    • Votes: 21
    • Previous version: 0.50 was 5 years, 8 months, 10 days before
  17. Text::ANSITable - Create nice formatted tables using extended ASCII and ANSI colors
    • Version: 0.602 on 2021-02-19
    • Votes: 15
    • Previous version: 0.601 was 4 months, 14 days before
  18. Tk - Tk - a Graphical User Interface Toolkit
    • Version: 804.036 on 2021-02-14
    • Votes: 26
    • Previous version: 804.035 was 10 months, 17 days before
  19. XML::Hash::XS - Simple and fast hash to XML and XML to hash conversion written in C
    • Version: 0.56 on 2021-02-13
    • Votes: 12
    • Previous version: 0.55 was 11 months, 11 days before

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

Week's winners (+3): Teng

Build date: 2021/02/20 14:03:38 GMT


Clicked for first time:


Increasing its reputation:

This is a monthly report by Tony Cook on his grant under Perl 5 Core Maintenance Fund. We thank the TPF sponsors to make this grant possible.

Approximately 46 tickets were reviewed, and 6 patches were
applied

[Hours]         [Activity]
  1.88          #17331 research
  .             #17331 more research and comment (and more discussion with khw)
  0.73          #17848 review hvds’ alternative and comment
  0.33          #18014 review, research
  0.50          #18073 rebase, re-test, bump version, apply to blead
  0.93          #18252 testing, review build process and comment
  1.35          #18256 research and long comment
  1.25          #18273 research and comment
  0.77          #18423 review, research and comment
  1.60          #18431 research and comment
  3.12          #18433 review, research
  .             #18433 review, testing and comments
  2.68          #18435 review and comments
  .             #18435 review latest changes, testing, apply to blead
  0.23          #18443 comment
  0.47          #18444 review, some research, comments
  0.50          #18454 review and apply to blead
  2.32          #18456 review, testing, run into an unrelated build issue,
                fix it, test and update authors, and apply to blead
  0.27          #18457 review, test and apply to blead (and notice a build
                issue)
  0.95          #18459 reproduce, report upstream and close
  0.37          #18461 review and comment
  0.42          #18466 review and briefly comment
  1.71          #18467 test, research and comment
                review github notifications, comment on #18467
  1.48          #18473 debugging, research
  0.33          #18486 review and briefly comment
  0.22          #18490 review and apply to blead
  0.18          #18493 comment
  0.73          #18496 review and approve
  3.30          #18505 review and comment
                review notifications, including review #18505 changes
  0.75          5.32.1 discussion
  0.58          5.32.1 discussion follow-up (and a typo fix)
  1.57          :utf8 code review, find an issue work on test and fix
  5.90          :utf8 debugging
                :utf8 debugging
                :utf8 debugging
                :utf8 debugging  
  2.53          :utf8 debugging, find one problem and fix
  1.80          :utf8 debugging, more PoC discussion/thinking
  1.57          :utf8 fill out different mode tests, valgrind some and
                find a bug and fix
  1.82          :utf8 find an issue, debugging
  1.55          :utf8 fix cpan module expected buggy :utf8, rebase to
                blead, work on more tests
  0.98          :utf8 more testing, fixes
  2.53          :utf8 more testing, port test changes and other fixes
                forward
  1.50          :utf8 re-work to avoid bad rebase
  1.45          :utf8 try to break it, fuzzing, debugging
  0.85          discussion with khw re freebsd and default warnings, email
                response to jim keenan re coverity scan results
  0.25          dTHX discussion with khw
  0.25          freebsd build issue discussion with khw, testing
  0.40          review github notifications
  1.33          review notifications, manual test mingw64, find and fix a
                parallel build problem with pl2bat
  0.47          review POC note and comment
  0.53          track down build issue and fix (d1293dc)

 57.23 hours total

Happy to announce that Jonathan was able to resume work on his Raku Development Grant. Here is his report.


In January, I at last felt in shape to get back to the new dispatch mechanism. The key remaining piece of the mechanism is dispatch resumption - a general term I'm using for a range of situations where we start doing some kind of dispatch, and may continue it later. For example:

  • When we call a method, we might later use callsame or similar in order to call a method in the base class (strictly, given multiple inheritance, the next method in the method resolution order)
  • When we use wrap, we also use callsame to call the wrapped code (and there may be any number of wrappers)
  • When we call a multi candidate, we can also use callsame to defer to the next best one
  • When we have a proto sub or method with a body, we need to run that body before we proceed with the multi-dispatch
  • Today, when we have a multi-dispatch with where clauses or unpacks, we need to do a test bind of the signature to see if the candidate is valid, followed by doing the invocation. This creates duplicate work. A better way would be to just try calling the candidate and having a way to treat a failure in parameter binding as a dispatch resumption, at which point we'd just continue with the next candidate.

Having an intuition that these can be neatly handled as cases of the same thing is rather easier, however, than coming up with a design to make it happen! Last year, before I had to take a break from my work on this, I had a number of false starts: designs that were partly right, and gave me some things to implement, but that all ran into problems.

Finally, I believe I've got a design that holds up. While that was still a quite theoretical claim at the end of January, I'm writing this report mid-February, by which point I've got a significant amount of the desgin implemented and working. Despite the fact that the specializer has not yet learned about this aspect of the new dispatch mechanism, I'm still seeing speedups of a factor of about 7 in a callsame to parent method benchmark (with 4 levels of inheritance), and a factor of 10 in a benchmark involving a subroutine with a single wrapper. I had planned to accompany this report with a link to a blog post with further technical details and the benchmarks; unfortunately, that's been delayed thanks to an injured arm (which I hope is now on the mend, although I should still keep my keyboard time down a bit for the days to come).

``` 15:59 Work on dispatch resumption in new dispatch mechanism 00:17 Code review

Total time worked: 16 hours 16 minutes ```

Since the announcement of the upcoming closure of rt.cpan.org, we've looked at what could, should, or must be done to keep it available in one form or another. After looking at a few options, The Perl Foundation has voted to contract Best Practical to take over the hosting of the CPAN RT instance. Starting immediately, they will be porting the data to their hosting, upgrading the RT instance to the latest version, and adapting the custom RT plugins and code that make rt.cpan.org go.

This work is expected to take until some time during March. With the current RT install going dark on March 1, this means that there may be an extended downtime at the beginning of the month. We will keep the page at rt.cpan.org up to date with the progress of the project. When the upgrade is complete, we have a commitment for three years of hosting from Best Practical. If future changes are likely or needed, we'll post them well in advance.

Das Schreiben von CLI-Tools erfordert einiges an Infrastrukturcode, um ein komfortables Tool mit Kommandos zu erstellen. Teile dieses Codes gleichen sich bei der Implementierung von Unterkommandos. Die Distribution App::Cmd hilft mit Mitteln der objektorientierten Entwicklung dabei, ein komfortables CLI-Tool schnell und erweiterbar zu implementieren.
Updates for great CPAN modules released last week. A module is considered great if its favorites count is greater or equal than 12.

  1. CryptX - Cryptographic toolkit
    • Version: 0.070 on 2021-02-12
    • Votes: 41
    • Previous version: 0.069 was 5 months, 18 days before
  2. DBD::CSV - DBI driver for CSV files
    • Version: 0.58 on 2021-02-10
    • Votes: 23
    • Previous version: 0.57 was 1 month, 24 days before
  3. Log::Log4perl - Log4j implementation for Perl
    • Version: 1.54 on 2021-02-06
    • Votes: 89
    • Previous version: 1.53 was 4 months, 19 days before
  4. Markdent - An event-based Markdown parser toolkit
    • Version: 0.39 on 2021-02-12
    • Votes: 20
    • Previous version: 0.38 was 3 months, 5 days before
  5. Mojolicious::Plugin::Status - Mojolicious server status
    • Version: 1.14 on 2021-02-09
    • Votes: 12
    • Previous version: 1.13 was 1 month, 6 days before
  6. PerlPowerTools - BSD utilities written in pure Perl
    • Version: 1.023 on 2021-02-10
    • Votes: 28
    • Previous version: 1.022 was 30 days before
  7. Pithub - Github v3 API
    • Version: 0.01036 on 2021-02-08
    • Votes: 19
    • Previous version: 0.01035 was 1 year, 2 months, 15 days before
  8. Search::Elasticsearch - The official client for Elasticsearch
    • Version: 7.711 on 2021-02-11
    • Votes: 38
    • Previous version: 7.30 was 4 months, 26 days before
  9. SPVM - Static Perl Virtual Machine. Fast Calculation, Fast Array Operation, and Easy C/C++ Binding.
    • Version: 0.0932 on 2021-02-08
    • Votes: 21
    • Previous version: 0.0931 was 2 days before
  10. Test::BDD::Cucumber - Feature-complete Cucumber-style testing in Perl
    • Version: 0.77 on 2021-02-10
    • Votes: 15
    • Previous version: 0.75 was 1 month, 13 days before
  11. Test::Class::Moose - Serious testing for serious Perl
    • Version: 0.99 on 2021-02-07
    • Votes: 16
    • Previous version: 0.98 was 1 year, 3 months, 12 days before

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

This week there isn't any remarkable distribution

Build date: 2021/02/13 16:22:37 GMT


Clicked for first time:


Increasing its reputation:

Sowohl für Nutzer als auch für Entwickler ist es ganz schön, wenn auf einen Blick der Zustand eines Moduls ersichtlich ist: Sind Fehler bekannt? Kann das Projekt gebaut werden? Wie ist die Testabdeckung?

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

Part 1

You are given file $FILE. Create subroutine readN($FILE, $number) returns the first n-characters and moves the pointer to the (n+1)th character.

Solution


use strict;
use warnings;
sub read_maker0{
    my $n = 0;
    return sub{
        my($file, $x) = @_;
        my $chars;
        open(FILE, $file);
        unless(seek(FILE, $n, 0)){
            close(FILE);
        }
        read(FILE, $chars, $x);
        $n = $n + $x;
        return $chars;
    }
}

sub read_maker1{
    my ($file) = @_;
    my $n = 0;
    open(FILE, $file);
    return sub{
        my($x) = @_;
        my $chars;
        my $read = read(FILE, $chars, $x);
        $n = $n + $x;
        unless(seek(FILE, $n, 0)){
            close(FILE);
        }
        return $chars;
    }
}

MAIN:{
    my($FILE, $number) = ("ch-1.dat", 4);
    my($read_n, $chars);
    $read_n = read_maker0();
    $chars = $read_n->($FILE, $number);
    print "$chars\n";
    $chars = $read_n->($FILE, $number);
    print "$chars\n";
    $chars = $read_n->($FILE, $number);
    print "$chars\n";
    
    
    $read_n = read_maker1($FILE);
    $chars = $read_n->($number);
    print "$chars\n";
    $chars = $read_n->($number);
    print "$chars\n";
    $chars = $read_n->($number);
    print "$chars\n";
}

Sample Run


$ perl perl/ch-1.pl
1234
5678
90

1234
5678
90

Notes

I actually did this two different ways. The first follows the letter of the challenge as to the parameters of the read_n function and the second differs, only passing in $number and does not include the filename.

Before I get into the differences it makes sense to point out how read_maker0() works. What is does is create a closure over the value $n which will hold the current position in the file. Think of the variable $n created in read_maker0() as captured inside the function that is being returned. This process is called currying and it’s a neat trick. I’ve used it in the past for these challenges, the first being way back in Challenge 003! In this way read_maker0() is creating the function which we are referring to by the scalar $read_n.

After each read $n is incremented and used to seek to the next position. I should note that this is not really necessary here since the value of $number is never changed. In this case the read alone will advance the file position as necessary. However, by including seek the solution is more general. We would be able to move around the file however we want, backwards and forwards, with seek if we wanted to.

So we see that we can capture $n and use it to store the file position between function calls. The challenge states that we are to called read_n with two parameters, the filename and the number of characters to read. As you can see, we do not need to keep sending the filename with each function call. The filename can also be a part of the closure!

That is the difference between read_maker0() and read_maker1(). The first returns a read_n function that matches the challenge specification of taking a filename and a number of characters to read. read_maker1() returns a function that only takes the number of characters to read, the function itself has a stored value for the file handle we want.

One small final thing to mention: anyone unfamiliar with read might notice that there is no checking to see if we attempt to read past the end of the file. That is because read will read all the characters it can and if it hits the end of the file it will stop. The return value from read is the number of characters successfully read. While we do not check that value in this code, if we did we would see that in this example the final read would return 2, which is clear in the output shown.

Part 2

You are given a sorted array of distinct integers @N and a target `$N``. Write a script to return the index of the given target if found otherwise place the target in the sorted array and return the index.

Solution


use strict;
use warnings;

sub find_insert{
    my($list, $n) = @_;
    if($n < $list->[0]){
        unshift @{$list}, $n;
        return 0;
    }
    if($n > $list->[@{$list} - 1]){
        push @{$list}, $n;
        return @{$list} - 1;
    }
    for(my $i = 0; $i < (@{$list} - 1); $i++){
        return $i if $n == $list->[$i];
        if($n > $list->[$i] && $n < $list->[$i + 1]){
            splice(@{$list}, $i, 2, ($list->[$i], $n, $list->[$i + 1]));
            return $i + 1;
        }
    }
}


MAIN:{
    my(@N, $N, $i);
    @N = (1, 2, 3, 4);
    $N = 3;
    $i = find_insert(\@N, $N);
    print "$i\n"; 
    
    @N = (1, 3, 5, 7);
    $N = 6;
    $i = find_insert(\@N, $N);
    print "$i\n"; 
    
    @N = (12, 14, 16, 18);
    $N = 10;
    $i = find_insert(\@N, $N);
    print "$i\n"; 
    
    @N = (11, 13, 15, 17);
    $N = 19;
    $i = find_insert(\@N, $N);
    print "$i\n"; 
}

Sample Run


$ perl perl/ch-2.pl
2
3
0
4

Notes

While somewhat convoluted sounding at first this part of Challenge 098 ended up being fairly straightforward, especially when using splice to do any array insertions. Probably there are more “fun” ways to have done this but the intuitive way here has an almost comforting look to it. Reminds me of university computer lab exercises!

Anyway, the approach here is to consider the possible cases. find_insert starts off by checking to see if $n would belong at the very start or end of the array. If neither of those cases hold we loop over the array looking for where $n might be. If found in the array we return with the index, else we insert with splice.

The challenge never asks to see the modified array so I suppose it is possible to merely return where $n belongs without actually inserting it but that didn’t seem quite as sporting.

References

Challenge 098

Perlmonks article on currying

 The perl.com domain was hijacked this morning, and is currently pointing to a parking site.  Work is ongoing to attempt to recover it.

 We encourage you NOT to visit the domain, as there are some signals that it may be related to sites that have distributed malware in the past.

  Some users may have it selected as their CPAN mirror.  To update your mirror in CPAN.pm use o conf urllist http://www.cpan.org/

# perl -MCPAN -eshell
cpan shell -- CPAN exploration and modules installation (v2.20)
Enter 'h' for help.

cpan[1]> o conf urllist http://www.cpan.org/
Please use 'o conf commit' to make the config permanent!
cpan[2]> o conf commit
commit: wrote '/root/.cpan/CPAN/MyConfig.pm'

Update 2021-01-28:

Work is underway to attempt to recover the domain.  If you're looking for the content, you can visit perldotcom.perl.org.

Update 2021-01-30:

Network Solutions is working with Tom Christiansen, the rightful registrant, on the recovery of the Perl.com domain. There is no estimated timeline for its recovery but the process is underway. The Perl.com site is temporarily at perldotcom.perl.org. Anyone using a perl.com host for their CPAN mirror should use www.cpan.org instead. Please direct all inquiries to brian d foy (brian.d.foy@gmail.com).

Update 2021-02-01:

We have contacted Network Solutions and verified that cpan.org is in the right hands and secured.

Update 2021-02-02:

Verisign has restored the proper nameservers (*.bitnames.com) for perl.com. You should see addresses in 151.101/16. If you still see something different, please leave a comment in GitHub issue #313. Some providers or services may have sinkholed or blocked Perl.com; if you are still seeing that, please let us know.

Update 2021-02-05:
Network Solutions has recovered the domain and your whois output should reflect that. If you notice that your firewalls or other security layers still mark perl.com as compromised, please leave us a note at https://github.com/tpf/perldotcom/issues/313.

 

Der Januar ist rum, Zeit mal nachzuschauen was wir im Januar so alles auf CPAN geladen haben.
Ist eine Webanwendung öffentlich erreichbar, wird es nicht lange dauern und irgendwelche Bots versuchen sich anzumelden. Oder es werden wild irgendwelche URLs aufgerufen. Auch wenn die Anmeldeversuche wahrscheinlich scheitern, geht die Bot-Aktivität zu Lasten der Webanwendung. Und mit genügend versuchen klappt es vielleicht doch mal, dass sich jemand Unbefugtes anmeldet.
dist author version abstract
Acme-CPANModules-ContainingJustData PERLANCAR 0.002 Modules that just contain data
Acme-CPANModules-PERLANCAR-Forked PERLANCAR 0.002 List of my modules which are forked from others
Acme-CPANModules-UUID PERLANCAR 0.001 Modules that can generate immutable universally unique identifier (UUIDs)
Acme-ConspiracyTheory-Random TOBYINK 0.001 random theories
Acme-STEVEB STEVEB 0.43 One line description
AnyEvent-Discord NMELNICK 0.1 Provides an AnyEvent interface to the Discord bot API
Apache2-SSI JDEGUEST v0.1.0 Apache2 Server Side Include
App-Device-Chip-sensor PEVANS 0.01 Base class to build Device::Chip::Sensor-based applications on
App-Dusage JV 2.00 provide disk usage statistics
App-Greple-xp UTASHIRO 0.01 extended pattern module
App-idxdb PERLANCAR 0.001 Import data from IDX and perform queries on them
App-lcpan-CmdBundle-borderstyle PERLANCAR 0.001 lcpan subcommands related to BorderStyle
App-streamfinder PERLANCAR 0.001 CLI for StreamFinder, a module to fetch actual raw streamable URLs from video & podcasts sites
Audio-StreamGenerator OELE 0.01 create a 'radio' stream by mixing ('cross fading') multiple audio sources (files or anything that can be converted to PCM audio) and sending it to a streaming server (like Icecast)
Audio-TinySoundFont ATRODO 0.10 Interface to TinySoundFont, a "SoundFont2 synthesizer library in a single C/C++ file"
Bio-MUST-Tools-Mcl DBAURAIN 0.210170 Scripts for processing MCL clusters
Bio-MUST-Tools-TreeParsing DBAURAIN 0.210200 Scripts for parsing trees
CSS-Struct-Output-Indent-ANSIColor SKIM 0.01 Indent printing 'CSS::Struct' structure to CSS code with ansi color output.
CSS-Tidy BKB 0.00_01 reformat CSS
CatalystX-Errors JJNAPIORK 0.001001 Default Web HTTP Error Pages
ColorTheme-Distinct-WhiteBG PERLANCAR 0.001 Pick some distinct colors (that are suitable for white background) for you
Crayon LNATION 0.01 CSS Toolkit
Crypt-OpenSSL-Verify-TRIAL TIMLEGGE 0.20 OpenSSL Verify certificate verification in XS.
D64-Disk-Layout PAWELKROL 0.01 Handling entire Commodore (D64/D71/D81) disk image data in pure Perl
Data-FormValidator-Constraints-NumberPhone GTERMARS 0.04 Data constraints, using Number::Phone
Data-FormValidator-Filters-WikiTrim GTERMARS 0.03 Trim filter for wikitext fields
Data-FormValidator-URI GTERMARS 0.03 URI constraint/filter for Data::FormValidator
Data-Prepare ETJ 0.001 prepare CSV (etc) data for automatic processing
Data-QuickMemoPlus-Reader BSHIELDS 0.01 Extract text from QuickMemo+ LQM export files.
Dist-Zilla-Plugin-EnsureMinimumPerl GTERMARS 0.01 Ensure that you have specified a minimum version of Perl
Dist-Zilla-Plugin-GitHub-RequireGreenBuild GTERMARS 0.01 Require a successful GitHub Actions workflow run
Dist-Zilla-Plugin-SyncCPANfile PERLSRVDE 0.01 Sync a cpanfile with the prereqs listed in dist.ini
Dist-Zilla-PluginBundle-Author-DOMM DOMM 0.906 Dist::Zilla config suiting my needs
Dist-Zilla-PluginBundle-DOMM DOMM 0.900 Dist::Zilla config suiting my needs
Fancazzista-Scrap AMICELI 0.01 Scrap websites and reddit posts
Feature-Compat-Try PEVANS 0.01 make try/catch syntax available
File-FormatIdentification-RandomSampling ART 0.005 methods to identify content of device o media files using random sampling
Future-IO-Impl-UV PEVANS 0.01 implement Future::IO using UV
Games-Dice-Roller LORENZO 0.01 a full featured dice roller system
GitHub-Actions JMERELO 0.0.3 Work in GitHub Actions using Perl
Gtk2-Html2 XAOC 0.05 DEPRECATED Perl bindings for the GtkHtml2 Html display widget
Gtk2-Recent XAOC 0.052 (DEPRECATED) Perl wrapper to the recent files spec Gtk
HTML-Make-Calendar BKB 0.00_01 Make an HTML calendar
HTML-Make-Page BKB 0.00_01 Automate making HTML <head> and <body>
Image-PNG-Util BKB 0.00_01 manipulate the image data part of PNGs
JSON-Server BKB 0.00_01 JSON-only server
JSON_minify RCOSCALI 1.0 minify a JSON and also remove comments
Kelp-Module-Raisin BRTASTIC 1.00 Raisin integration with Kelp
Kelp-Module-Sereal BRTASTIC 1.00 Sereal encoder / decoder for Kelp
Lingua-String NHORNE 0.01 Class to contain a string in many different languages
Loctools-Markdown AFAN 0.9 Localization-focused Markdown parser/generator
Module-List-More-Patch-Hide PERLANCAR 0.001 Hide some modules from Module::List::More
Mojo-UserAgent-SecureServer JHTHORSEN 0.01 Secure application server for Mojo::UserAgent
Mojolicious-Matterbridge CORION 0.01 a simplistic module to connect to chat servers via matterbridge
Mojolicious-Plugin-Component AWNCORP 0.01 Module-based Component Renderer
Neo4j-Types AJNN 1.00 Common Neo4j type system
Net-OBS-Client FSM v0.0.5 simple OBS API calls
OTRS-OPM-Validate PERLSRVDE 0.01 Validate .opm files
Pod-Modifier VERMAUDH 1 Modify/ add to an existing POD dynamically
Pulsar-WebSocket-Client WESLEY 0.01 Perl client for Apache Pulsar WebSocket API
Sah-Schemas-BorderStyle PERLANCAR 0.001 Sah schemas related to BorderStyle
Sah-Schemas-ColorTheme PERLANCAR 0.001 Sah schemas related to ColorTheme
Simd-Avx512 PRBRENAN 20210121 Simd::Avx512 – Emulate SIMD instructions
Statocles-Plugin-VideoTag GENE 0.0100 Change video file anchors to video elements
Store-Directories CAMTAUXE 0.1 Manage a key/value store of directories with controls for
Syntax-Keyword-Finally PEVANS 0.01 add FINALLY phaser block syntax to perl
Table-Trans BKB 0.00_01 simple translations for templating
Table-Translations BKB 0.00_01 simple translations for templating
TableData-Lookup PERLANCAR 0.001 Lookup value in a table data structure
Task-OpenTracing SNEZ v0.0.1 install all the OpenTracing modules
Task-PerlCriticAllPolicies GUGOD 0.01 A Task for installing all Perl::Critic policies at once.
Template-Plugin-StripComments GTERMARS 1.02 Template Toolkit filter to strip comment blocks
Text-BibTeX-Validate MERKYS 0.1.0 validator for BibTeX format
Text-LooksLike BKB 0.00_01 make guesses about snippets of text
Text-Unmunch ELIONORA 0.1
USCIS-Case ERICLEE 0.01 Perl extensions to check USCIS case status. More features would be added in the future.
UUID-Random-PERLANCAR PERLANCAR 0.002 Another implementation of UUID::Random
UUID-Tiny-Patch-UseMRS PERLANCAR 0.001 Make UUID::Tiny use Math::Random::Secure's rand()
WHO-GrowthReference-GenChart PERLANCAR 0.001 Create WHO growth chart ()
WHO-GrowthReference-GenTable PERLANCAR 0.001 Add WHO reference fields to table
WebService-Postex WATERKIP 0.001 A Postex WebService implemenation in Perl
Wireguard-WGmeta TOBIB v0.0.6 An approach to add metadata to the main Wireguard config
WordList-EN-ColorName-WWW PERLANCAR 0.003 Color names from Graphics::ColorNames::WWW
WordList-ID-ColorName-HTML_ID PERLANCAR 0.002 List of color names from Graphics::ColorNames::HTML_ID

Stats

Number of new CPAN distributions this period: 84

Number of authors releasing new CPAN distributions this period: 48

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 17
2 BKB 8
3 GTERMARS 6
4 PEVANS 4
5 BRTASTIC 2
6 PERLSRVDE 2
7 DOMM 2
8 DBAURAIN 2
9 XAOC 2
10 AWNCORP 1
11 AMICELI 1
12 JDEGUEST 1
13 ELIONORA 1
14 PAWELKROL 1
15 JJNAPIORK 1
16 AFAN 1
17 GUGOD 1
18 AJNN 1
19 STEVEB 1
20 TOBYINK 1
21 SKIM 1
22 UTASHIRO 1
23 JHTHORSEN 1
24 MERKYS 1
25 ERICLEE 1
26 LNATION 1
27 ATRODO 1
28 SNEZ 1
29 BSHIELDS 1
30 TIMLEGGE 1
31 NMELNICK 1
32 FSM 1
33 GENE 1
34 WATERKIP 1
35 NHORNE 1
36 TOBIB 1
37 ART 1
38 RCOSCALI 1
39 CAMTAUXE 1
40 LORENZO 1
41 ETJ 1
42 VERMAUDH 1
43 JV 1
44 PRBRENAN 1
45 OELE 1
46 CORION 1
47 JMERELO 1
48 WESLEY 1

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

Part 1

You are given string $S containing alphabets A..Z only and a number $N. Write a script to encrypt the given string $S using Caesar Cipher with left shift of size $N.

Solution


use strict;
use warnings;
sub caesar_cypher{
    my($s, $n) = @_;
    my @cypher = map { unless(ord($_) == ord(' ')){
                           my $x = ((ord($_) - $n) < ord('A')?(ord($_) - $n + 26):(ord($_) - $n)); 
                           chr($x);
                       }
                       else{
                           $_
                       }
                 } split(//, $s);
    return join("", @cypher);
}

MAIN:{
    my($S, $N);
    $S = "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG";
    $N = 3;
    print "$S\n";
    print caesar_cypher($S, $N) . "\n";
}

Sample Run


$ perl perl/ch-1.pl
THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD

Notes

The basic approach here is pretty much the straightforward one: use the ascii values for the characters and subtract $n. In Perl we use the ord function to do this and the chr to go in the other direction, ascii value to character. The only thing we really need to be careful of is if subtracting $n takes us outside the ascii range for upper case letters, then we need to add 26 to get back in range.

Certain style instructions have been burned into my brain over the years and I find them almost impossible to deviate from. The one that applies here is Whenever possible do not use numeric literals. They are often poorly documented and become “magic numbers”, and make code readability and future debugging unnecessarily difficult. So it is in that spirit that I write, for example, ord(' ') instead of just 32.

Part 2

You are given a binary string $B and an integer $S. Write a script to split the binary string $B of size $S and then find the minimum number of flips required to make it all the same.

Solution


use strict;
use warnings;

use feature "bitwise";

sub substrings{
    my($d, $s) = @_;
    my @substrings;
    for(my $i = 0; $i < length($d); $i+=$s){
        push @substrings, substr($d, $i, $s);
    }    
    return @substrings;
}

sub min_flips{
    my($d, $s) = @_;
    my @flips;
    my @substrings = substrings($d, $s);
    for my $digits (@substrings){
        my $flip_count = 0;
        map { $flip_count += unpack("%32b*", $digits ^. $_) } @substrings;
        push @flips, $flip_count;
    }
    return [sort {$a <=> $b} @flips]->[0];
}

MAIN:{
    my($B, $S);
    $B = "101100101";
    $S = 3;
    print min_flips($B, $S) . " flips\n";
    $B = "10110111";
    $S = 4;
    print min_flips($B, $S) . " flips\n";
}

Sample Run


$ perl perl/ch-2.pl
1 flips
2 flips

Notes

The substrings function is just a convenient wrapper around the code necessary to break the string into the right sized chunks. The assumption is that the string is evenly divisible into chunks of size $s. If we were not making this assumption we would need to add some zero padding for any unevenly sized substring.

Since use feature "bitwise"; is present the ^. is defined and the operands to ^. are taken to be bit strings and the result is itself a bit string.min_flips does a bitwise xor operation, pairwise comparing each substring in a map. Since xor is 1 only when the bits are different the result is a bit string of set bits, the ones needed to be flipped. unpack is used to sum these, and the result added $flip_count which is then pushed into an array. The minimum number of flips is determined by the smallest number in that array. The bitwise feature was introduced in Perl 5.22 and graduated from experimental status in Perl 5.28.

References

ASCII Table

xor

Perl’s xor

bitwise feature

In der agilen Software-Entwicklung wird oft die formale Korrektheit von User Storys über ihren eigentlichen Zweck gestellt: Die Beteiligten erzählen einander Geschichten aus Anwendersicht. Während der Umsetzung der Software verlieren Beteiligte zudem oft den Blick »auf’s große Ganze«. Die Methode »User Story Mapping« möchte helfen, diese Probleme zu beheben und durch die enstehende Software das Leben der Anwender verbessern.
@davorg / Saturday 27 February 2021 09:51 UTC