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.
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.
I started Perl when smart match (~~
) was already around (and already not recommended to the usage).
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 đ
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
...
}
The same way with numeric ===
:
if(0 == undef) { # it is true
...
}
if(0 === undef) { # it will be false
...
}
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).
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"; }
Unfortunately you will get an error:
Prototype mismatch: sub main::a () vs ($) at multi.pl line 2.
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");
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! đ
This is a great talk, that opens the door to discussion and implementations.
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
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
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;
}
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]
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
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;
}
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.
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 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 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
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] ))'
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";
(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
}
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";
}
};
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};
}
}
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.
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'} );
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;
}
(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.)
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();
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.
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.
From METACPAN faq you can get some tips like the module: prefix
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::
By asking on the good old IRC, I get a solution thanks to CPANMeta
You can then list all XML::* modules
The quick and dirty hack!
I downloaded the 02packages.details.txt
file from CPAN.org
Then using a grep
grep "^XML::" 02packages.details.txt
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
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);
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
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);
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);
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'
};
I see there are also some other possible alternatives like App::CPANIDX or maybe CPANDB?
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 do you think?
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" is the small name of Regular expressions
Regex are one of the superpowers đȘ of Perl
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.
But "regex" have also a nefarious reputation because they are hard, error-prone and misused.
Damian Conway is a master of regular expressions but you can sometimes feel the pain in his mouth when he discusses regex
But on a more positive note, Damian said
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".
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, everybody knows, and here is the very famous SO answer "You can't parse [X]HTML with regex" about that đ
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
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
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)
While use of complex regex are subject to discussions, there are perfect and obvious use cases for regex:
I discussed about WrongButGoodEnough regex that help you save the world on a Friday evening:
But writing regex is hard to master and you probably don't
One solution is to leave your cat typing the regex for you!
I wanted to finish with this crazy fact, fasten your seat belts.
Perl folks are really serious about regex
This is mad.
These are some answers to the Week 100 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
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.
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
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
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
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
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
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.
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.
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"
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
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)))/
.
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.
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";
}
$ perl ch-2.pl
8
7
I think this is a relatively well known greedy tactic. In order to minimize the total sum, make the minimum choice at each step.
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:
I couldn't find what I was looking for, so I made the solution:
And I also created a demo site to show some of what's possible with this library:
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.
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:
These are the ten most rated questions at Stack Overflow last week.
Between brackets: [question score / answers count]
Build date: 2021-02-20 13:55:05 GMT
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.
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)wrap
, we also use callsame
to call the wrapped code (and there may be any number of wrappers)callsame
to defer to the next best oneproto
sub
or method
with a body, we need to run that body before we proceed with the multi-dispatchwhere
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.
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:
The examples used here are from the weekly challenge problem statement and demonstrate the working solution.
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.
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";
}
$ perl perl/ch-1.pl
1234
5678
90
1234
5678
90
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.
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.
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";
}
$ perl perl/ch-2.pl
2
3
0
4
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.
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'
Work is underway to attempt to recover the domain. If you're looking for the content, you can visit perldotcom.perl.org.
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).
We have contacted Network Solutions and verified that cpan.org is in the right hands and secured.
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.
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.
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 |
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.
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
.
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";
}
$ perl perl/ch-1.pl
THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
QEB NRFZH YOLTK CLU GRJMP LSBO QEB IXWV ALD
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
.
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.
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";
}
$ perl perl/ch-2.pl
1 flips
2 flips
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.