Gee almost a year since my lat post. I better start posting again or Mohammad will catch up with me ;).

Been quite a year for every one on this big blue marble. I hope you are all good.

Ok here is the very short post for today.

I just did my first build and upload of PAWS to CPAN

Expect Version 0.43 to be up there later today some time.

It was a bit of an epic on my part as this whole releasing thingy, made some real bad goofs (deleting then checking in a folder), thank goodness for 'git revert' and getting the version number wrong.

Hopefully is comes out ok.

Look for more releases in the future.

judypng.png

Alt Text

Simple brute force script
[1] WordPress (Auto Detect Username)
[2] Joomla
[3] DruPal
[4] OpenCart (Coming Soon)
[5] Magento
[6] All (Auto Detect CMS)

Usage
Short Form Long Form Description
-l --list websites list
-p --passwords Passwords list

Example
perl bprute.pl -l list.txt -p passwords.txt

Installation Linux
git clone https://github.com/penucuriCode/bprute.git
cd bprute
perl bprute.pl -l list.txt -p passwords.txt

Installation Android
Download Termux

cpan install LWP::UserAgent
cpan install HTTP::Request
git clone https://github.com/penucuriCode/bprute
cd bprute
perl bprute.pl -l list.txt -p passwords.txt

Installation Windows
Download Perl
Download bprute
Extract bprute into Desktop
Open CMD and type the following commands:
cd Desktop/bprute-master/
perl bprute.pl -l list.txt -p passwords.txt

Current version is 2.1 What's New
• speed up
• Bug fixes

Thanks for your support and encouragement ...

I had many ups and downs in the month of April. In all these, I have recieved plenty of supporting voices.

First, we had the start of Ramadan. I feel fortunate to be able to fast in this holy month. However I had to break my fast for two days because I suffered by Vertigo. Luckily I recovered very fast, thanks to ALLAH s.w.t.

As you all know, I have started taking part in the weekly challenge after rather a long break. Although I am only sharing solutions in Perl for the time being. Soon, I would start doing in Raku and Swift. Having said, I started live coding regularly in recent weeks. Please find below the links to all videos that I created last month. I use OBS Studio to create live videos. Someone recently complained about the audio quality. So I bought the Blue Microphone Snowball Ice. I noticed the audio quality was way better. Feeling brave, I started making changes to the configuration to make it even more crisper. While doing so, I broke the standard settings. I panicked. I asked for help on Twitter and within no times, I had plenty of help. After fierce fighting for a week, I got it working in the end.

There is another big news that I would like to share with you all. After nearly 9 years with NTT, I decided to move on and accepted an offer from Oleeo. I joined as Senior Perl Developer on 4th May 2021. I was fortunate to receive the grand welcome by everyone. I was plesantly surprised that so many people knew me already. I met familiar faces as well e.g. Andrew Solomon (Geekuni) and James Raspass (Code Golf). Thanks to Julien Fiegehenn, my induction went very smooth.

Any new projects in the pipeline?

Well, there are two, one in Perl and another in Python. I will share the details in the next monthly report as I am still preparing the ground.

That's it for now. Stay safe and healthy.

Let's take a quick look through last month main activities.


Pull Request

4 Pull Requests submitted in the month of April 2021.

2356 Pull Requests altogether.


Git Commits

684 commits recorded in the month of April 2021.

Overall 3131 commits recorded in the year 2021.


The Weekly Challenge

Following weekly challenges proposed in the month of April 2021:

And RECAPS are listed as below:


YouTube Channel

April has been the best month as far as video contributions are concerned. For the first time, I was able to create 9 videos working on various tasks of the weekly challenges.

Perl Weekly Challenge - 100 (Task #1: Fun Time)


Perl Weekly Challenge - 106 (Task #1: Maximum Gap)


Perl Weekly Challenge - 107 (Task #1: Self-descriptive Numbers)


Perl Weekly Challenge - 108 (Task #1: Locate Memory)


Perl Weekly Challenge - 108 (Task #2: Bell Numbers)


Perl Weekly Challenge - 109 (Task #1: Chowla Numbers)


Perl Weekly Challenge - 109 (Task #2: Four Squares Puzzle)


Perl Weekly Challenge - 110 (Task #1: Valid Phone Numbers)


Perl Weekly Challenge - 110 (Task #2: Trahspose File)


There are plenty of videos available on my YouTube Channel. If you like the video then please do subscribe to my channel so that you don't miss the weekly fun live coding videos.


Meet The Champion

Last month, we declared Tyler Wardhaugh as the Champion of The Weekly Challenge.

If you are interested in past champions interview then you can find it all here.


Pull Request Club

Last month, I received Bread::Runner by Thomas Klausner. I submitted one Pull Request and it has been already accepted and merged by Thomas Klausner.

Overall participation to Pull Request Club


Perl Blog

Last month, I blogged about the following topics.


Perl Weekly Newsletter

Last month, I edited two editions of the Perl Weekly Newsletter i.e. Issue #506 and Issue #508.


Patreon

At the end of last month, April 2021, the following people / organisation supported me in the past or continued supporting me even today. I am humbled by their generosity.

Do you want to sponsor my work?

Please follow the Patreon page.

Thank You.

Most of us probably know curl as a quick and easy way to send HTTP requests from the command line.

That tool, though, is just an interface to the curl project’s real gold: the libcurl API. Using this API, applications in all sorts of languages have easy access to the awesome power that libcurl provides. This article will discuss how to use that power in Perl.

A Quick Example

use Net::Curl::Easier;

my $easy = Net::Curl::Easier->new(
    url => 'http://perl.org',
    followlocation => 1,
)->perform();

print $easy->head(), $easy->body();

Let’s talk about what just happened.

Net::Curl::Easier is a thin wrapper around Net::Curl’s “easy” interface—“easy” is what libcurl calls it!—that smooths over some rough edges in Net::Curl.

(Full disclosure: I am Net::Curl::Easier’s maintainer.)

Once we create our “Easier” object, having given it the proper URL and told it to follow HTTP redirects (followlocation refers to HTTP’s Location header), we run perform() on the Easier object.

After that, we print the HTTP response headers and body, and we’re done!

Why not just use HTTP::Tiny?

Indeed. Well, error reporting, for one. Consider:

Net::Curl::Easier->new(
    url => 'http://blahblah',
)->perform();

If you run this you’ll probably just see Couldn't resolve host name printed to standard error. But if you dig deeper you’ll see something nifty:

use Net::Curl::Easier;
use Data::Dumper;

eval {
    Net::Curl::Easier->new(
        url => 'http://blahblah',
    )->perform();
};
print Dumper $@;

It turns out that that error isn’t just a string; it’s an exception object.

In large systems I often want to handle certain failure types differently from others. HTTP::Tiny’s errors are just strings, so type-specific failure handling with HTTP::Tiny entails parsing strings, which is brittle. What if someone decides to reword some error message for clarity, thus breaking my string parser?

With Net::Curl I can look for specific numeric error codes, documentation for which the curl project itself maintains. This is much more robust.

Don’t care. What else you got?

OK. How about this:

my $easy = Net::Curl::Easier->new(
    username => 'hal',
    userpwd => 'itsasecret',
    url => 'imap://mail.example.com/INBOX/;UID=123',
)->perform();

I just queried … an email inbox?!?

Curl doesn’t just speak HTTP; it speaks many other protocols including IMAP, LDAP, SCP, and MQTT. To see the full list of protocols that your curl supports, run curl --version.

Concurrency

Curl can also run concurrent queries. To do that I recommend using Net::Curl::Promiser. (Full disclosure: I also maintain this module.)

Example, assuming use of Mojolicious:

use Net::Curl::Easier;
use Net::Curl::Promiser::Mojo;
use Mojo::Promise;

my $easy1 = Net::Curl::Easier->new(
    url => 'http://perl.org',
    followlocation => 1,
);

my $easy2 = Net::Curl::Easier->new(
    username => 'hal',
    userpwd => 'itsasecret',
    url => 'imap://mail.example.com/INBOX/;UID=123',
);

my $easy3 = Net::Curl::Easier->new(
    username => 'hal',
    userpwd => 'itsasecret',
    url => 'scp://tty.example.com/path/to/file',
);

my $promiser = Net::Curl::Promiser::Mojo->new();

Mojo::Promise->all_settled(
    $promiser->add_handle($easy1)->then( sub {
        print $easy1->head(), $easy1->body();
    } ),
    $promiser->add_handle($easy2)->then( sub {
        # ... whatever you want with the IMAP result
    } ),
    $promiser->add_handle($easy3)->then( sub {
        # ... whatever you want with the SCP result
    } ),
)->wait();

We just grabbed a web page, queried a mailbox, and downloaded a file via SCP, all in parallel!

Note, too, that this method interfaces seamlessly with other promises. So if you have existing Mojo::UserAgent-based code, you can add requests for other protocols alongside it.

Net::Curl::Promiser also works natively with
AnyEvent and
IO::Async, should those be of greater interest to you. It also provides a convenience layer for custom select-based event loops, in case that’s how you roll.

Other Modules

Some alternatives to modules presented above:

  • AnyEvent::YACurl: A newer library than Net::Curl that simplifies the interface a bit. It assumes use of AnyEvent, though, so if you’re not using AE then this may not be for you.

  • WWW::Curl: The library of which Net::Curl is a fork. It can do much of what Net::Curl does but lacks access to libcurl’s MULTI_SOCKET interface, which is faster and more flexible than curl’s internal select-based manager for concurrent requests.

  • Net::Curl::Simple: A wrapper by Net::Curl’s original author. It provides some of the same conveniences as Net::Curl::Promiser and Net::Curl::Easier but uses callbacks rather than promises.

Closing Thoughts

Curl exposes an awesome breadth of functionality, of which the above examples have just scratched the surface. Check it out!

Regarding his Raku CI Bot grant, Patrick writes:


In April I didn't find much time to work on the Raku CI Bot grant, because non computer things required my time.

I added more API mappings to my clone of [the GitHub module](https:// github.com/fayland/perl6-WebService-GitHub). In particular I added relevant parts of the Checks, Pulls, OAuth and Issues APIs. I also rebased my changes on the fork of khalid who incidentally also started working on the GitHub API module. I then learned they started working on automatic binding generation based on the API description and offered to jump in.

I also cleaned up the architecture scribbles of the core logic of the application. I hope to publish a post about it soon.

Estoy aprendiendo Español por dos años y media y pienso que la mejor manera para mejorar mi conosimiento es practicar.

Por eso empecé hacer eventos de programacion por pares en Español. Vale, en Español se roto que tengo.

links

Sí tú tienes la paciencia para hablar conmigo y quieres hacer una sesión conmigo, ¡contactarme!

Yo hice otros eventos sobre otras tecnologias pero en inglés.

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

Spoiler Alert: This weekly challenge deadline is due in a few days (May 9, 2021). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

Task 1: Search Matrix

You are given 5x5 matrix filled with integers such that each row is sorted from left to right and the first integer of each row is greater than the last integer of the previous row.

Write a script to find a given integer in the matrix using an efficient search algorithm.

Example:

Matrix: [  1,  2,  3,  5,  7 ]
        [  9, 11, 15, 19, 20 ]
        [ 23, 24, 25, 29, 31 ]
        [ 32, 33, 39, 40, 42 ]
        [ 45, 47, 48, 49, 50 ]

Input: 35
Output: 0 since it is missing in the matrix

Input: 39
Output: 1 as it exists in the matrix

We’re only trying to know whether an integer exists in the matrix. What I would normally do in such case is transform the data structure, i.e. store all the matrix items into a hash and then simply look whether an item exists in the hash. And I’ll also present such a solution.

However, looking carefully at the working of the task, we can see that the task insists on the fact that the integers are in ascending order from left to right and from top to bottom. The task further tells us that we should use an efficient algorithm. Although this is not explicitly specified, it is quite clear that we’re expected to implement a binary search algorithm, which is an efficient algorithm with sorted data.

The first idea might be to flatten the matrix into a one-dimension array, making the dataset much easier to use with a canonical binary search algorithm. But, obviously, that’s also not really what we’re expected to do. The task author wants us to implement a binary search algorithm on a 2-D matrix. We could come up with an “approximate” binary search, i.e. an heuristic looking for the approximate mid-point between two values. For example, we could start by testing any item on the third row and then goto the 2nd or 4th row depending on the result of the test. But that’s not satisfactory: that would not scale easily to other dimensions.

So I decided to perform the binary search on a list of consecutive integers between 0 and 24, and to provide a subroutine to convert these integers into 2-D indices. For example, the sixth item in that range corresponds to indices [1][0].

Search Matrix in Raku

Using Binary Search

The A2AoA subroutine converts a flat rank into 2-D indices. We simply run a binary search on the 0..24 range and use the A2AoA subroutine to find out the correspond values in the matrix. Our test cases will be quite exhaustive, since we’ll be searching the matrix for every integer between 0 and 54.

use v6;

my @matrix = (  1,  2,  3,  5,  7 ),
             (  9, 11, 15, 19, 20 ),
             ( 23, 24, 25, 29, 31 ),
             ( 32, 33, 39, 40, 42 ),
             ( 45, 47, 48, 49, 50 );

sub A2AoA ($index) {
    my ($i, $j) = $index.polymod(5).reverse;
}
sub binary ($in) {
    my ($min, $max) = 0, 24;
    while $max > $min {
        my $pivot = (($max + $min) /2).Int;
        my ($i, $j) = A2AoA $pivot;
        my $val = @matrix[$i][$j];
        # say "val = $val, $i, $j";
        return 1 if $val == $in;
        if $in > $val {
            $min = $pivot + 1;
        } else {
            $max = $pivot;
        }
    }
    return 0;
}
say "$_ => ", binary $_ for 0..54;

This program displays the following output:

$ raku ./search_item.raku
0 => 0
1 => 1
2 => 1
3 => 1
4 => 0
5 => 1
6 => 0
7 => 1
8 => 0
9 => 1
10 => 0
11 => 1
12 => 0
13 => 0
14 => 0
15 => 1
16 => 0
17 => 0
18 => 0
19 => 1
20 => 1
21 => 0
22 => 0
23 => 1
24 => 1
25 => 1
26 => 0
27 => 0
28 => 0
29 => 1
30 => 0
31 => 1
32 => 1
33 => 1
34 => 0
35 => 0
36 => 0
37 => 0
38 => 0
39 => 1
40 => 1
41 => 0
42 => 1
43 => 0
44 => 0
45 => 1
46 => 0
47 => 1
48 => 1
49 => 1
50 => 0
51 => 0
52 => 0
53 => 0
54 => 0

Note that I’m happy that I used such exhaustive test cases, since my original implementation had a relatively rare bug that I had not seen with the six or seven values I initially tested.

Using a Hash

As I said in the introduction, in the real life, I would transform the input data into a hash and simply perform hash lookup.

use v6;

my @matrix = (  1,  2,  3,  5,  7 ),
             (  9, 11, 15, 19, 20 ),
             ( 23, 24, 25, 29, 31 ),
             ( 32, 33, 39, 40, 42 ),
             ( 45, 47, 48, 49, 50 );

my %hash;
for @matrix -> @row {
    %hash{$_} = 1 for @row;
}
say "$_ => ", %hash{$_} ?? 1 !! 0 for 0..54;

As it can be seen, the code is much shorter, much simpler and much less prone to errors. It produces the same output:

$ raku ./search_item2.raku
0 => 0
1 => 1
2 => 1
3 => 1
4 => 0
5 => 1
6 => 0
7 => 1
8 => 0
9 => 1
... Lines omitted for brevity...
45 => 1
46 => 0
47 => 1
48 => 1
49 => 1
50 => 1
51 => 0
52 => 0
53 => 0
54 => 0

Search Matrix in Perl

Using Binary Search

This is a port to Perl of the binary search algorithm explained in the introduction above. The A2AoA subroutine converts a flat rank into 2-D indices. We simply run a binary search on the 0..24 range and use the A2AoA subroutine to find out the correspond values in the matrix. Our test cases will be quite exhaustive, since we’ll be searching the matrix for every integer between 0 and 54.

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

my @matrix = ( [  1,  2,  3,  5,  7 ],
               [  9, 11, 15, 19, 20 ],
               [ 23, 24, 25, 29, 31 ],
               [ 32, 33, 39, 40, 42 ],
               [ 45, 47, 48, 49, 50 ]
             );

sub A2AoA {
    my $index = shift;
    my ($i, $j) = (int $index / 5, $index % 5);
}
sub bin_search {
    my $in = shift;
    my ($min, $max) = (0, 24);
    while ($max > $min) {
        my $pivot =  int (($max + $min) /2);
        my ($i, $j) = A2AoA $pivot;
        my $val = $matrix[$i][$j];
        # say "val = $val, $i, $j";
        return 1 if $val == $in;
        if ($in > $val) {
            $min = $pivot + 1;
        } else {
            $max = $pivot;
        }
    }
    return 0;
}
say "$_ => ", bin_search $_ for 0..54;

This program displays the following output:

perl  ./search_item.pl
0 => 0
1 => 1
2 => 1
3 => 1
4 => 0
5 => 1
6 => 0
7 => 1
... lines omitted for brevity ...
45 => 1
46 => 0
47 => 1
48 => 1
49 => 1
50 => 0
51 => 0
52 => 0
53 => 0
54 => 0

Using a Hash

As mentioned above, in the real life, I would transform the input data into a hash and simply perform hash lookup. In Raku, I had to use nested for loops to populate the hash because my attempts using chained maps did not work as expected. There is certainly a way to do it with chained maps, but it is not easy to find the right syntax. No such problem with Perl where my chained maps worked perfectly on my first attempt (see below). There has to be something for which Perl is better or (more convenient) than Raku.

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

my @matrix = ( [  1,  2,  3,  5,  7 ],
               [  9, 11, 15, 19, 20 ],
               [ 23, 24, 25, 29, 31 ],
               [ 32, 33, 39, 40, 42 ],
               [ 45, 47, 48, 49, 50 ]
             );

my %hash = map { $_ => 1 } map { @$_ } @matrix;
say "$_ => ", exists $hash{$_} ? 1 : 0 for 0..54;

This displays the same output as before:

$ perl search_item2.pl
0 => 0
1 => 1
2 => 1
3 => 1
4 => 0
... Lines omitted for brevity ...
45 => 1
46 => 0
47 => 1
48 => 1
49 => 1
50 => 1
51 => 0
52 => 0
53 => 0
54 => 0

Task 2: Ordered Letters

Given a word, you can sort its letters alphabetically (case insensitive). For example, “beekeeper” becomes “beeeeekpr” and “dictionary” becomes “acdiinorty”.

Write a script to find the longest English words that don’t change when their letters are sorted.

For this, I’ll use an English word list contributed to the public domain by Grady Ward as part of the Moby Lexicon project. It is a list of 113,809 crosswords, that is words that are considered valid in crossword puzzles and other word games. The list can be found on my github repository.

Ordered Letters in Raku

We don’t really need to sort the letters: we only need to know whether they are already in the alphabetical order. In Raku, we can use the [...] reduce metaoperator together with the le less than or equal to operator on the letters of the word. Checking whether a list is sorted has a smaller computational complexity than sorting the list, so this should presumably be faster (although it is so fast with my 113-k word list that it doesn’t really matter).

use v6;

my @long-words;
my $max-length = 0;

for './words.txt'.IO.lines -> $word {
    next unless [le] $word.comb;
    my $length = $word.chars;
    if  $length > $max-length {
        @long-words = $word,;
        $max-length = $length;
    } elsif $length == $max-length {
        push @long-words, $word;
    }
}
say @long-words.join(", ");

This program finds two 7-letter words satisfying the task’s criteria and displays the following output:

$ raku ./ordered-letters.raku
beefily, billowy

I do not know what these two words mean, but they are in the input list and they satisfy the criteria.

Ordered Letters in Perl

It is slightly less convenient in Perl than in Raku to check that the letters are already in the proper order, so I’ll simply sort the letters and compare the output with the input word.

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

my @long_words;
my $max_length = 0;

my $word_list = "./words.txt";
open my $IN, "<", $word_list or die "Cannot open $word_list $!";
while (my $word = <$IN>) {
    chomp $word;
    next unless $word eq join '', sort split //, $word;
    my $length = length $word;
    if  ($length > $max_length) {
        @long_words = ($word);
        $max_length = $length;
    } elsif ($length == $max_length) {
        push @long_words, $word;
    }
}
say "@long_words";

This program produces the same two words:

$ perl ordered-letters.pl
beefily billowy

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, May 16, 2021. And, please, also spread the word about the Perl Weekly Challenge if you can.

A few months ago, Gabor asked if more CPAN modules should have their own web sites. I replied, saying thought it was a good idea and pointing out how easy it was to create project web sites on GitHub Pages.

But since then, I've been wondering if could be made even easier. Perhaps we could make it easy enough that there was really no reason not to have a web site for your CPAN module.

And today I've released App::CPANModuleSite that does just that.

The default usage is pretty easy.

  • Install the module
  • In your repo checkout run mksite <distribution-name>
  • Run git add docs to add your new website directory to your repo
  • Commit the changes and push the commit
  • Configure your repo to support GitHub pages (I covered that in my earlier blog post)

And you'll have a basic web site for your module at the web address https://<github-user>.github.io/<repo-name>.

The default site is pretty basic. And it has a big banner across the page saying that you haven't put any effort into the site yet. But that's simple enough to fix. Just add a file called tt_lib/intro.tt to your repo that contains a bit of HTML which explains more about what your module does. The next time you rebuild the site, that text will replace the default paragraph.

Other than that, the default site contains:

  • The documentation for all of the modules in your distribution
  • Links to other standard pages about your module (CPAN, CPAN testers, CPANTS, things like that)
  • Links to your code repo and issue tracker (if they are defined in your CPAN metadata)

It's also simple to add more pages to your site. Just add files in a site_src directory in your repo. Any file in that directory whose name ends in .tt will be processed by the Template Toolkit and the output will be stored in the /docs directory (with the .tt stripped from the name). Any files without a .tt extension will just be copied into /docs. If you're adding pages, then you'll almost certainly also want to edit the navbar on the page to contain links to your new pages.

Default versions of various template files in /site_src and /tt_lib are installed as part of App::CPANModuleSite's installation. To edit them, you just copy them into the same directory in your repo and edit the copied versions. Any files found inside your repo will take precedence over the versions in the default directories.

Any templates that you write (or existing ones that you edit) will have access to a few template variables:

This is all pretty experimental currently. I'm very happy to add more information to the default pages, more variables to the template engine and make pretty much any other changes that any users suggest. Let's work together to make this a useful and powerful web site generation tool.

I have a couple of thoughts for things I want to do next:

  • I've already started work on creating a GitHub Action, so that you can automatically regenerate the site, for example, whenever you check in a change to your code
  • The whole point of this is that more CPAN web sites mean better SEO for Perl. So I plan to think of ways that make the default sites as SEO-friendly as possible

Please let me know what you think. Do you think this is a good idea? Will you use the module?

Oh, and the site that App::CPANModuleSite generated for itself is at https://davorg.dev/app-cpanmodulesite/.

Back in 2007 I wrote CPANdeps, a web site which analysed dependencies between distributions on the CPAN, and displayed them along with their CPAN testers results.

I have decided to retire it, for several reasons. First, metacpan has sprouted tentacles to do the dependency analysis. Second, the code is a mess and it needs quite a bit of work to cope with the current size of the CPAN-testers database. But third, and most importantly, the employer that I left over a year ago are withdrawing the free hosting.

I've not actually used the site myself for a while, preferring the command line version. That, like metacpan, doesn't include test results, but I've found that I generally don't care much. Nigh on everything Just Works on every platform I care about.

It's going away on or shortly after the 17th of May. If anyone would like to take it over and host it themselves please email me.

Edit2: After further talk with CAT, i will acknowledge that it was not the intent of the CAT to make me wait, and they in fact did not even realize this was the effect.

I am the "second individual", i am intimately familiar with the events of both their investigations.

Shortly before the TPF informed me that their start-of-may update was nearly ready to be posted, i informed them that these were my expectations:

2021-04-29 19:00
> all i care about are correct, accurate, truthful and useful consequences

I was wholly disappointed.

----

Context: https://news.perlfoundation.org/post/cat-transparency-report-updates0

----

Edit:

And interestingly the perl.reddit.com moderation team saw fit to censor the submission of this post. It can still be seen directly, but is not in the feed anymore. This is notable as a wide variety of posts and comments that violate the "no personal attacks" rule, but also were in nature against the accused by the TPF, were allowed to remain up and are up to this day and hour, often with completely false claims about people. chromatic and briandfoy are currently the most (and probably only) active moderators there.

Our client is looking for a Perl programmer who wants to tame the job jungle for employers and employees through their candidate sourcing and data management products. TThe perfect candidate has strong experience with Modern Perl, is located within the US and is keen for a remote role! Is that you?
If you’re a Perl programmer with a passion for finance, this role may be the one for you. Our client is a financial company whose stunning growth over the last twenty years shows that they belong in the city of the future. They’ve built a company with an international presence on that idea, and business is booming.
The organization whose servers handle a jaw-dropping 80% of the UK’s job ads is looking for a few good humans, and you could be one of them! The client is interested in anyone with experience building web apps in Perl, using one of the major Perl frameworks.
With a knack for tailoring content to a variety of site aesthetics, our client sets a banquet of advertising delights for over 349 million consumers around the world. 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.
Very well-known Austrian e-commerce brand 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. Client is willing to consider all candidates with strong Perl, but they make heavy use of PostgreSQL, Elasticsearch, and Modern Perl.
Online 8-10 June 2021.
Thursday, May 22, 2021
May 13th, 2021 06:00 PM Central Time (US and Canada)
Wednesday, May 12, 2021
Wednesday, May 5, 2021; 07:00 PM Eastern Time (US and Canada)
Lior Mizrahi, the author of the package introduces it and then we fix a bug.
Another episode of the 'Automation with Rex' series in which we follow the Ansible playbook to set up Elasticsearch and Nginx on CentOS.
The 5th part in which we set up redirection, refactored the tests, and started to test the upload file phase.
Cool use of map and logical-defined-or; thanks for sharing the magic.
I noticed Roger not using \d in the regex, instead using [0-9]. I remember reading somewhere it is the preferred choice.
Luca shared some cool Raku magic dealing with regex. Thanks for sharing the knowledge.
Luis shared multiple solutions to the Transpose File task. Simply loved it. Thanks.
Laurent has been consistently sharing solutions in more than just Perl and Raku. Thanks for sharing.
I loved the discussion about memory usage for the Transpose File task. It is always a pleasure to read code showing the memory utilisation. Thanks for sharing.
Jaldhar shared a mix of Perl and Raku magics. Cool use. Thanks.
Flavio shared a special use of open(). Thanks for sharing the knowledge.
Flavio never misses the opportunity to surprise us. Thanks for the short and sweet discussion on the subject.
Dave presented us some information background about Phone Numbers. Also shared s special use of Text::CSV. Thanks for sharing.
Cool use of regex, something I never used before. Thanks Colin.
I loved his frank admission the checking other contributions and building a different solution is not an easy job. Kudo to your efforts.
Arne used a special trick to deal with the Valid Phone Numbers task by only looking at the first 4 characters.
Thanks for introducing Raku grammars and welcome back after the short break.
Adam never hesitates to try a unique tool. This week he used Parse::Yapp grammar. Thanks for sharing.
Abigail's blog post is full of magical code. I loved the one-liner solution in Perl.
I have learnt something new today - chained regexes in Perl. Thanks Abigail for sharing.
Please check out these Raku solutions by Aaron Smith.
Perl Solutions Review by Colin Crain.
Enjoy a quick recap of last week's contributions from Team PWC dealing with the "Valid Phone Numbers" and "Transpose File" 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 "Search Matrix" and "Ordered Letters". If you are new to the weekly challenge then why not join us and have fun every week. For more information, please read the FAQ.
David released a complete new distribution to figure out what type a scalar is.
Mark trying to resolve a test coverage issue in this blog post.
Gaurav has been blogging regularly to create a REST API using Mojolicious and OpenAPI. Always fun to read his blog posts.
Charlie's attempt to solve a practical problem using Perl. A very cool attempt.
Mark shared a discussion about Perl salary rankings.
Neil's take on what actually is community. He took pains to explain the term in great detail.
Flavio once again created a very handy tool, Heail, in this blog post.
Flavio continued with his daily blogging series and presents how to stringify CSS as JSON.
Mark continued his blogging series and presented the basics of installing Perl on various platforms.
John shares his experience dealing with wxPerl.
The CAT would like to make some corrections, as well as address some of the comments and questions we received on the initial transparency report.

Hi there

I am not sure if you have read the recent blog post by Neil Bowers. I have read it multiple times to understand the subject of the post. I must admit, I had never read such an in depth analysis of the term "Community". As my vocabulary is rather limited, I found it very interesting to read such a long blog post. To me, community is group of like-minded people. When I attended my first London Perl Workshop, I immediately felt part of the community. The organiser and everybody was so accommodating and friendly. It made me come again the following year and I became addicted to it afterwards. I always looked up to the big names of the community everytime I needed some inspiration. Take a look at the past recipients of the White Camel Award, you can get some idea of who's who in the community. Unfortunately it hasn't been awarded since 2018 for some reason that I am not aware of. I miss the community spirit of attending Perl Conferences. You can never experience that feeling unless you attend one. I hope and wish we get back to attending conferences. Although there has been virtual events in recent times, it can't replace real events in my humble opinion. I must give credit to everyone who is keeping the community spirit alive.

Today is a bank holiday in the UK, so all the British readers of the newsletter, enjoy your break with the newsletter. Rest of the world, start your week with weekly doses of Perl news. Stay safe and healthy.

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

Spoiler Alert: This weekly challenge deadline is due in a couple of days (May 2, 2021). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

Task 1: Valid Phone Numbers

You are given a text file.

Write a script to display all valid phone numbers in the given text file.

Acceptable Phone Number Formats:

+nn  nnnnnnnnnn
(nn) nnnnnnnnnn
nnnn nnnnnnnnnn

Input File:

0044 1148820341
 +44 1148820341
  44-11-4882-0341
(44) 1148820341
  00 1148820341

Output

0044 1148820341
 +44 1148820341
(44) 1148820341

This is obviously typically a job for regular expressions (or regexes). I will not even try to consider a language or solution not using regular expressions. I will not use a separate text file but simulate it with an array of strings or some other means.

Valid Phone Numbers in Raku

Please remember that Raku’s regexes are trying to renew the subject and have some differences with the traditional Perl or Perl-compatible regexes. Among other things, spaces are usually not relevant in a regex pattern (unless you use an option to force it).

use v6;

my @tests = " 0044 1148820341 42 ", "  +44 1148820342 abc", 
            " 44-11-4882-0343 ", " (44) 1148820344  ", " 00 1148820345";

my $ten-dgts = rx/\d ** 10/;
for @tests -> $str {
    say ~$0 if $str ~~ / ( [ \d ** 4 || '+' \d\d || \( \d\d \) ] \s+ <$ten-dgts> ) /;
}

To make things clearer, the regex above could be rewritten more clearly as:

(                 # Capture content within  poarens
  [               # group items within the [] alternative
    \d ** 4 ||    # Four digits or...
    '+' \d\d ||   # + sign and 2 digits, or ..
    \( \d\d \) ]  # two digits within parentheses
  ]               # end of the alternative
  \s+             # spaces
  <$ten-dgts>     # Ten-digits regex
)                 # end of capture

The above program displays the following output

$ perl phone.pl
0044 1148820341
+44 1148820342
(44) 1148820344
(39) 1148820344

Valid Phone Numbers in Perl

This is a port to Perl of the above Raku program. Note that we have included a test case in which thee are two phone numbers in the same input line.

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

# simulate a text file with an array of strings
my @tests = (" 0044 1148820341 42 ", "  +44 1148820342 abc", 
            " 44-11-4882-0343 ", " (44) 1148820344 foo (39) 1148820345", " 00 1148820346");

for my $str (@tests) {
    say $1 while $str =~ / ( (?: \d {4} | \+ \d\d | \( \d\d \)  ) \s+ \d{10} ) /gx;
}

This script displays the following output:

$ perl phone.pl
0044 1148820341
+44 1148820342
(44) 1148820344
(39) 1148820345

Valid Phone Numbers in Other Languages

Phone Numbers in Scala

We need to import the cala.util.matching.Regex core Scala package. Note that every backslash appears twice in the pattern of the program below. This is because in Java and Scala, a single backslash is an escape character in a string literal, not a regular character that shows up in the string. So instead of ‘\’, you need to write ‘\’ to get a single backslash in the string.

import scala.util.matching.Regex

object phoneNumber extends App {
  val pattern = "((?:\\d{4}|\\+\\d\\d|\\(\\d\\d\\))\\s+\\d{10})".r
  val tests = Array(
    " 0044 1148820341 42 ",
    "  +44 1148820342 abc",
    " 44-11-4882-0343 ",
    " (44) 1148820344  (33) 1148820345",
    " 00 1148820346"
  );
  for (str <- tests) {
    if (pattern.unanchored.matches(str)) {
      println((pattern findAllIn str).mkString(", "))
    }
  }
}

Output:

0044 1148820341
+44 1148820342
(44) 1148820344, (33) 1148820345

Phone Numbers in Python

This program uses the re core Python package:

import re 

tests = ("foo 0044 1148820341 42", "xyz +44 1148820342 abc", "44-11-4882-0343", " (44) 1148820344  ", "00 1148820345")

for str in tests:
    match = re.search("(\d{4}|\+\d\d|\(\d\d\))\s+\d{10}", str)
    if (match):
        print (match.group())

Output:

$ python3 phone.py
0044 1148820341
+44 1148820342
(44) 1148820344

Phone Numbers in Awk

Awk was the first programming language to include regular expressions, even before Perl, so it was an obvious guest language candidate for this task. I had a bit of trouble to get it to work properly because, for some reason, the \d and [:digit:] character classes did not work properly on the platform where I tested it (although they’re supposed to be part of the awk language). I used [0-9] instead, which is a quite simple solution, but I wasted quite a bit of time before I figured why it did not work as I expected. Here, we’re using a shell pipe with an awk one-liner:

$ echo '
0044 1148820341
+44 1148820342
44-11-4882-0343
(44) 1148820344
00 1148820346
' | awk '/([0-9]{4}|\+[0-9]{2}|\([0-9]{2}\))\s+[0-9]{10}/ { print $0 }'
0044 1148820341
+44 1148820342
(44) 1148820344

Phone Numbers in Julia

No need to import a dedicated library in Julia, since regexes are built into the language.

tests = ["foo 0044 1148820341 42", "xyz +44 1148820342 abc", 
         "44-11-4882-0343", " (44) 1148820344  ", "00 1148820345"]
pattern = r"(\d{4}|\+\d\d|\(\d\d\))\s+\d{10}"

for str in tests 
    m = match(pattern, str)
    if (! (m === nothing)) 
        println(m.match)
    end
end

Output:

    $julia phone.jl
    0044 1148820341
    +44 1148820342
    (44) 1148820344

Phone Numbers in Ruby

For some reason the \d character class and the \+ literal plus sign don’t seem to work on my Ruby installation, although they should if I understand the documentation correctly. So, I used the [0-9] and [+] character classes instead.

tests = ["foo 0044 1148820341 42", "xyz +44 1148820342 abc", 
         "44-11-4882-0343", " (44) 1148820344  ", "00 1148820345"]
pattern = %r{((\d{4}|\+\d{2}|\(\d{2}\))\s+\d{10})}
for str in tests
    match = str.match(pattern)
    if match then
        print(match[0], "\n")
    end
end

Output:

0044 1148820341                                                                                                                               
+44 1148820342                                                                                                                                
(44) 1148820344

Phone Numbers in Rust

Here, I have chosen to use a single string containing several phone numbers as input and check that we can extract several valid phone numbers from that input string.

use regex::Regex;

fn main() {
    let pattern = Regex::new(r"((\d{4}|\+\d{2}|\(\d{2}\))\s+\d{10})").unwrap();
    let test = "foo 0044 1148820341 42 xyz +44 1148820342 abc 
        44-11-4882-0343 (44) 1148820344 00 1148820345";
    for matches in pattern.captures_iter(test) {
        println!("{:?}", &matches[0]);
    }
}

Output:

"0044 1148820341"
"+44 1148820342"
"(44) 1148820344"

Task 2: Transpose File

You are given a text file.

Write a script to transpose the contents of the given file.

Input File

name,age,sex
Mohammad,45,m
Joe,20,m
Julie,35,f
Cristina,10,f

Output:

name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

For practical reasons, I will not use an external file but simulate it in various ways.

Transpose File in Raku

We simulate the input file with an array of strings. The program takes the @input array of strings, reads each line in turn (as we would do with an actual file), split each line and on commas, and store the individual items in a @transposed array of arrays. At the end, we just need to output the rows of the @transposed array.

use v6;

my @input = <name,age,sex Mohammad,45,m 
             Joe,20,m Julie,35,f Cristina,10,f>;

my @transposed;
for @input -> $in {
    my $i = 0;
    for $in.split(',') -> $str {
        push @transposed[$i], $str;
        $i++;
    }
}
for @transposed -> @line {
    say @line.join(',');
}

This program displays the following output:

$ raku ./transpose.raku
name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

Transpose File in Perl

We simulate the input file with space-separated string. The construction of the @transposed array of arrays is following the same idea as in Raku.

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

# Note: input array simulated with a string
my $in_string = "name,age,sex  Mohammad,45,m 
         Joe,20,m Julie,35,f  Cristina,10,f";
my @input = split /\s+/, $in_string;
my @transposed;
for my $in (@input) {
    my $i = 0;
    for my $str (split /,/, $in) {
        push @{$transposed[$i]}, $str;
        $i++;
    }
}
for my $line (@transposed) {
    say join ',', @$line;
}

This program displays the following output:

$ perl  transpose.pl
name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

Transpose File in Awk

We pipe the input to the awk program standard input.

BEGIN{ 
    FS = "," 
}
{ table[0,NR] = $1 }
{ table[1,NR] = $2 }
{ table[2,NR] = $3 }
{ max = NR }
END {
    for (i = 0; i < 3; i++) {
        for (j = 1; j < max - 1; j++) printf "%s,", table[i,j]
        printf "%s\n", table[i,max-1]
    }
}

This is an example run:

$  echo 'name,age,sex
> Mohammad,45,m
> Joe,20,m
> Julie,35,f
> Cristina,10,f
> ' | awk -f transpose.awk
name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

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, May 9, 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 text file. Write a script to display all valid phone numbers in the given text file.

Solution


use Capture::Tiny q/capture_stdout/;
use PhoneNumberParser;

MAIN:{
    my $parser = new PhoneNumberParser();
    while(my $line = ){
        $line =~ s/^\s+|\s+$//g;
        my $syntax_error = capture_stdout {
            $parser->parse($line); 
        };
        print("$line\n") if !$syntax_error;
    }
}   

__DATA__
0044 1148820341
 +44 1148820341
  44-11-4882-0341
(44) 1148820341
 00 1148820341

The Parse::Yapp grammar.


%token SPACE DIGIT OPEN CLOSE PLUS
%%

phone_number: prefix SPACE area_exchange_subscriber
;

prefix: DIGIT DIGIT DIGIT DIGIT
    | OPEN DIGIT DIGIT CLOSE
    | PLUS DIGIT DIGIT
;   

area_exchange_subscriber: DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT DIGIT
;

%%

sub lexer{
    my($parser) = @_;
    $parser->YYData->{INPUT} or return('', undef);
    ##
    # send tokens to parser
    ##
    for($parser->YYData->{INPUT}){
        s/^(\s)// and return ("SPACE", $1);
        s/^(\d)// and return ("DIGIT", $1);
        s/^(\()// and return ("OPEN", $1);
        s/^(\))// and return ("CLOSE", $1);
        s/^(\+)// and return ("PLUS", $1);
    }  
}

sub error{
    exists $_[0]->YYData->{ERRMSG}
    and do{
        print $_[0]->YYData->{ERRMSG};
            return;
    };
    print "syntax error\n"; 
}

sub parse{
    my($self, $input) = @_;
    $self->YYData->{INPUT} = $input;
    my $result = $self->YYParse(yylex => \&lexer, yyerror => \&error);
    return $result;  
}

Sample Run


$ yapp perl/PhoneNumberParser.yp
$ perl -Iperl perl/ch-1.pl
0044 1148820341
+44 1148820341
(44) 1148820341

Notes

While a set of regular expression would have done the job quite nicely I figured I’d use this problem as a reason to shake the rust off my grammar writing skills. Not that I am a master parser writer or anything, but Parse::Yapp makes it easy enough!

Well, easy is a bit relative I suppose. This is definitely not the simplest way of performing this task.

Part 2

You are given a text file. Write a script to transpose the contents of the given file.

Solution


sub transpose{
    my @columns = @_;
    return transpose_r([], \@columns);  
}

sub transpose_r{
    my($transposed, $remaining) = @_;
    return $transposed if(@{$remaining} == 0);   
    $transposed = transpose_row_r($transposed, $remaining->[0]);  
    shift @{$remaining}; 
    transpose_r($transposed, $remaining);  
}

sub transpose_row_r{
    my($transposed, $row) = @_;
    return $transposed if(@{$row} == 0); 
    my $index = @{$row} - 1;
    push @{$transposed->[$index]}, pop @{$row};  
    transpose_row_r($transposed, $row);    
}

MAIN:{
    my @columns;
    while(my $line = ){
        chomp($line);
        my @fields = split(/,/, $line);   
        push @columns, \@fields; 
    }
    my $transposed = transpose(@columns);   
    for my $i (0 .. @{$transposed} - 1){
        print join(",", @{$transposed->[$i]}) . "\n";       
    }    
}

__DATA__
name,age,sex
Mohammad,45,m
Joe,20,m
Julie,35,f
Cristina,10,f

Sample Run


$ perl perl/ch-2.pl
name,Mohammad,Joe,Julie,Cristina
age,45,20,35,10
sex,m,m,f,f

Notes

Similar to Part 1 this is also not the easiest way to perform this task. Here the same sort of recursion is used that is used in the Prolog version of the solution to this part. That is, we recurse over the table itself and then for each row perform a separate recursion to perform the transpostion.

References

Challenge 110

The fifth part of the live development course management application using Mojolicous together with Mark Gardner.

The CAT would like to make some corrections, as well as address some of the comments and questions we received to the initial transparency report. The CAT plans to publish a separate statement in the coming days relating to general changes and improvements to the process.

The subject of investigations #1 and #2, as referenced in the previous transparency report and below in this document, is the same and therefore will be known as the Subject throughout this document. The other individual mentioned in the previous transparency report is not mentioned except under the Corrections section.

There have been questions and concerns raised by members of the community regarding TPF CAT’s process in handling the incidents in question and our authority to sanction someone in response. We believe that this is within our authority for several reasons.

First, while TPF has never published a “year round” Standards of Conduct document, all TPF conferences have had a Standards of Conduct document (or equivalent) since YAPC in 2012 (Madison). The exact content of that document has varied over the years, though it’s been in something close to its current form for quite a number of years. The Subject has attended many of these conferences, and has agreed to these Standards of Conduct in the past as a matter of attending.

Second, the investigations we conducted and the sanctions we imposed in response are based on reports of harmful behavior by the Subject in multiple forums across a number of years. A subset of these were investigated in detail and reported on as investigation #1 and #2. While there are other reports, the results of both investigations combined were enough to take action.

Third, while some of the most recent behavior did not occur at a TPF event or in a TPF-controlled online space, we believe that the purpose of the CAT is primarily to protect people from harm in the spaces we do control. If someone demonstrates through their behavior that they are overwhelmingly likely to cause harm to the community in our events and spaces, we believe it is within our authority to impose sanctions on them because of that behavior in order to prevent future harm.

However, we do have a significant correction we want to make to the previous report in regards to authority. The initial report stated: “The CAT has instructed the Subject to leave and cease participation...” and went on to mention various online spaces that TPF does not control. This was not intended to be an instruction to take technical measures, but a request for the Subject to cease participation, and was done to prevent any further harm from occurring. However, we recognize that this was poorly worded, and we never intended to assert any control over these spaces. We recognize that these spaces are operated independently by various communities and each community must decide for themselves how to manage their community. The initial report further stated the CAT “may: explicitly extend the scope of the ban, take further technical measures”. TPF recognizes that this is out of scope.

In addition, there are a number of other corrections and clarifications we would like to make.

Corrections

  1. The ban from attending TPF conferences, events, and using TPF online chat platforms (Slack) stands. However:
    1. This is modified to a minimum duration of 1 year.
    2. The length of the ban is modified because having a year round Standards of Conduct is new, as is the CAT. Given all this, we felt it was fairer to start with a more limited sanction.
    3. For the ban to be lifted, the Subject must agree to not repeat their past unacceptable behavior and agree to abide by the Standards of Conduct going forward.
    4. Unacceptable behavior within that 1 year period could lead to an extension or modification of the length or the terms of the ban. This includes interactions between the Subject and others in the Perl and Raku communities, even outside of TPF events and online platforms.
    5. For examples of unacceptable behavior, please see the current Standards of Conduct for the 2021 Conference in the Cloud.
  2. The initial transparency report stated that warning would be issued to the second individual investigated as part of “investigation #1”.
    1. The CAT apologizes and recognizes that this individual should not have been mentioned in the transparency report.
    2. After reconsideration, it was decided that the warning is not appropriate based on the evidence in “investigation #1” and therefore will not be issued.
    3. The CAT had a conversation with the second individual to discuss this.
  3. The CAT acknowledges it should have delayed the publication of the transparency report to give the Subject more time to respond.
    1. The Subject disagrees with the extent of CAT’s assertion that the events of investigation #1 and #2 are part of a pattern of bad behavior.
    2. The Subject disagrees with the level of harm this pattern of bad behavior causes the community.
    3. The Subject is willing to leave or step down from their responsibilities within various online spaces, communities, and subcommunities if asked by the leaders or committees responsible for those online spaces, communities, or subcommunities.
    4. The Subject does not commit to leaving other online spaces, communities, or subcommunities, except those which they have since been banned from.
    5. The Subject accepts the ban on attending TPF conferences and events.

Clarifications and responses to specific questions

The CAT would like to address a few of the questions and comments it received on the last transparency report:

  1. The CAT wants to be clear that the behavior from investigation #1 alone would not have resulted in the CAT’s decision.
    1. The events of “investigation #1” and “investigation #2” were investigated as a pattern of behavior which extends beyond the events of either investigation.
    2. The CAT found that there was a pattern of bad behavior.
  2. Regarding the event from “investigation #2”: whether the Subject willingly left or was given an ultimatum did not have any bearing on the CAT’s decision.
  3. The community member who was harmed in investigation #1 is a different person than the community member harmed in investigation #2.
  4. The second investigation was opened due to reports that there was a pattern of bad behavior. Aside from that, the investigations are not related.
  5. Discriminatory statements need not be intended to attack nor directed at a specific person to cause harm.
  6. As part of investigation #2, the CAT talked to multiple people who attended the event.
  7. The CAT has subsequently provided a more detailed transparency report to the board of directors whilst respecting privacy of the subjects.
    1. This more detailed version does not share the names of any parties of the investigations, but was deemed too detailed for public release.

Conclusion

The Community Affairs Team is committed to a safe environment, at conferences and physical events as well as online between members of the Perl and Raku community. If you have comments regarding this public statement you can send them to cat@perlfoundation.org with the word “comment” in the subject.

If you want to report: discriminatory, harassing, or otherwise unacceptable behavior, please contact cat@perlfoundation.org. For examples of what may constitute unacceptable behavior, please see the Standards of Conduct for this year’s Conference in the Cloud.

Addenda

Update, 2021-05-07: We've had a few people say that the paragraph about online spaces that TPF doesn't control was unclear. We agree! To clarify, the CAT doesn't provide unsolicited advice on how other spaces should run things, and the statement above should not be read as reserving the right to do so.

In my training course I give exercises to my students. They can (and in some of these course they must) submit them. I can then review them and give comments. I would like to have a web application to keep track of all the exercises and the submission.

In this experimental project Mark Gardner and myself will develop this application using live pair programming.

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

  1. Beam::Wire - Lightweight Dependency Injection Container
    • Version: 1.024 on 2021-04-27
    • Votes: 15
    • Previous version: 1.023 was 2 years, 1 month, 4 days before
  2. CryptX - Cryptographic toolkit
    • Version: 0.072 on 2021-04-29
    • Votes: 41
    • Previous version: 0.071 was 30 days before
  3. Data::Alias - Comprehensive set of aliasing operations
    • Version: 1.21 on 2021-04-30
    • Votes: 15
    • Previous version: 1.22 was 8 days before
  4. Devel::NYTProf - Powerful fast feature-rich Perl source code profiler
    • Version: 6.08 on 2021-04-27
    • Votes: 168
    • Previous version: 6.07 was 23 days before
  5. experimental - Experimental features made easy
    • Version: 0.023 on 2021-04-30
    • Votes: 29
    • Previous version: 0.022 was 11 months, 26 days before
  6. Future::AsyncAwait - deferred subroutine syntax for futures
    • Version: 0.50 on 2021-04-30
    • Votes: 37
    • Previous version: 0.49 was 2 months, 6 days before
  7. JSON::Validator - Validate data against a JSON schema
    • Version: 4.17 on 2021-04-28
    • Votes: 28
    • Previous version: 4.16 was 1 month, 4 days before
  8. Mojo::mysql - Mojolicious and Async MySQL/MariaDB
    • Version: 1.21 on 2021-04-28
    • Votes: 34
    • Previous version: 1.22 was 4 months, 6 days before
  9. Mojolicious::Plugin::OpenAPI - OpenAPI / Swagger plugin for Mojolicious
    • Version: 4.03 on 2021-04-28
    • Votes: 40
    • Previous version: 4.02 was 1 month, 4 days before
  10. PDL - Perl Data Language
    • Version: 2.044 on 2021-05-01
    • Votes: 41
    • Previous version: 2.039 was 7 days before
  11. Raisin - A REST API microframework for Perl.
    • Version: 0.91 on 2021-04-28
    • Votes: 40
    • Previous version: 0.90 was 10 months, 6 days before
  12. SPVM - Static Perl Virtual Machine. Fast Calculation, Fast Array Operation, and Easy C/C++ Binding.
    • Version: 0.0949 on 2021-04-30
    • Votes: 21
    • Previous version: 0.0946 was 7 days before

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

Week's winner: List::Keywords (+3)

Build date: 2021/05/01 14:33:20 GMT


Clicked for first time:


Increasing its reputation:

dist author version abstract
Acme-Brainbuz-markdown BRAINBUZ 0.001 turns baubles into trinkets
Acme-CPANModules-BrowsingTableInteractively PERLANCAR 0.001 Creating a palette of visually distinct colors
Acme-CPANModules-CreatingPaletteOfVisuallyDistinctColors PERLANCAR 0.001 Creating a palette of visually distinct colors
Acme-Markdown-Embarrassing CONTRA 0.01 Testing the MetaCPAN Markdown converter
Alien-OpenMP ETJ 0.001 Encapsulate system info for OpenMP
App-Greple-ical UTASHIRO 0.01 Module to support Apple OS X Calendar data
App-MigrateToTest2V0 UTGWKK 0.01 Migrate your tests from Test::More to Test2::V0
App-ProxyThat SIMBABQUE 0.001 Proxy an URL from the command line
App-SQLiteUtils PERLANCAR 0.001 Utilities related to SQLite
App-dateseq-idn PERLANCAR 0.003 Like dateseq, but with built-in support for Indonesian holidays
App-perlimports OALDERS 0.000001 Make implicit imports explicit
ArrayData PERLANCAR 0.1.0 Specification for ArrayData::*, modules that contains array data
ArrayDataRoles-Standard PERLANCAR 0.001 Standard set of roles for ArrayData
Astro-Coord-Constellations DKECHAG 0.01 Identify the constellation for position (RA, Dec)
Astro-Coord-Precession DKECHAG 0.01 Precess coordinates between 2 epochs
Beekeeper JMICO 0.01 Framework for building applications with a microservices architecture
BigIP-REST GROUSSE 0.1 REST interface for BigIP
Book-Bilingual HOEKIT v0.001 Data structure for a bilingual book
Business-Stripe-WebCheckout BOD 0.1_1 Simple way to implement payments using Stripe hosted checkout
CGI-Tiny DBOOK 0.001 Common Gateway Interface, with no frills
CXC-Number DJERIUS 0.03 A namespace for modules which deal with numbers.
CodeGen-Protection OVID 0.01 Safely rewrite parts of generated code
Crypto-API MICVU 0.01 Crypto API
Crypto-Exchange-API MICVU 0.01 Crypto Exchange API
Crypto-Exchange-Binance MICVU 0.01 Crypto Exchange Binance
Crypto-Exchange-Binance-Spot-API MICVU 0.01 Crypto Exchange Binance Spot API
Data-Enum RRWO v0.1.0 fast, immutable enumeration classes
Data-TableData-Lookup PERLANCAR 0.002 Lookup value in a table data structure
Data-TableData-Object PERLANCAR 0.112 Manipulate data structure via table object
Devel-GlobalSub ZARABOZO 0.01 Automagically import a subroutine into all namespaces
File-Codeowners CCM 0.50 Read and write CODEOWNERS files
File-Edit HOEKIT v0.0.1 A naive, probably buggy, file editor.
File-SortedSeek-PERLANCAR PERLANCAR 0.015.0 A fork of File::SortedSeek with some more options
Finance-Alpaca SANKO 0.9900 Perl Wrapper for Alpaca's Commission-free Stock Trading API
Finance-Dogechain CHROMATIC 1.20210418.2306 use the dogecoin.info API from Perl
Fork-Utils CDN 0.01 set of usefull methods to work with processes and signals
Function-Version HOEKIT 0.0001 Define and use different function versions
Google-UULE-Generator FAYLAND 0.01 Generate Google UULE param
Hash-ExtendedKeys LNATION 0.01 Hash Keys
Hash-RestrictedKeys LNATION 0.01 restricted hash keys
JSON-Pointer-Extend VRAG 0.01 JSON::Pointer extension module
LINQ-Database TOBYINK 0.000_001 LINQ extension for working with databases
Lagrange KOBOLDWIZ v0.1.3 Perl extension for Lagrange Theory and Applications
Lib-CPUInfo XSAWYERX 0.001 Perl interface to PyTorch's libcpuinfo C library
Lib-PWQuality XSAWYERX 0.001 Perl interface to the libpwquality C library
Lingua-StarDict-Writer NATARAJ 0.01 A module that allows to create a StarDict dictionary
Linux-MCELog ERICLEE 0.01 Perl extensions to extract memory failure information from MCELog UNIX domain socket on Linux.
List-AllUtils-Null PERLANCAR 0.001 List subroutines that treat undef as contagious unknown, like null in SQL
List-Keywords PEVANS 0.01 a selection of list utility keywords
MIDI-SP404sx RVOSA v1.0.0 Convert between MIDI files and SP404sx patterns
Minion-Backend-Redis DFUG 0.002 Redis backend for Minion job queue
Mojo-OBS-Client CORION 0.01 Mojolicious client for the OBS WebSocket remote plugin
Mojo-Reactor-Prima KARASIK 1.00 Prima event loop backend for Mojo::Reactor
Myriad DERIV 0.001 async microservice framework
Net-Protocol-OBSRemote CORION 0.01 event-loop agnostic protocol to control OBS via the WebSocket plugin
OEIS ABIGAIL 2021041201 Fetch values from sequences of the OEIS.
OpenAPI-Generator DOOJONIO 0.01 generate openapi definition
OpenMP-Environment OODLER 1.0.0 Perl extension managing OpenMP variables in %ENV within a script.
Package-Checkpoint PLICEASE 0.01 Checkpoint the scalar, array and hash values in a package for later restoration
Perl-Oberon KOBOLDWIZ v0.1.3 an Oberon compiler system written in Perl 5
Perl-PrereqScanner-Scanner-DistZilla-PluginBundle ASDAGO 0.001 scan for required plugins in Dist::Zilla plugin bundles
Plack-App-WWW LTM 0.01 Serve cgi-bin and static files from root directory
Pod-Coverage-TrustMe HAARG 0.001_001 Pod::Coverage but more powerful
Role-TinyCommons-Collection PERLANCAR 0.001 Roles related to collections
Role-TinyCommons-Iterator PERLANCAR 0.001 A basic iterator
SMS-Send-KR-Aligo KEEDI 0.004 An SMS::Send driver for the smartsms.aligo.in SMS service
Sah-Schemas-Finance-SE-IDX PERLANCAR 0.001 Schemas related to the Indonesian Stock Exchange
See INA 0.01 Debug See
Stats-Fermi KOBOLDWIZ v0.1.2 Perl extension for Fermi, Boltzmann potentials
Stats-Hawking KOBOLDWIZ v0.1.1 Perl extension for a Hawking Boltzmann Model
Sub-Genius OODLER 0.05 manage concurrent Perl semantics in the uniprocess execution model of perl.
Sub-Genius-TRIAL OODLER 0.01 module for managing concurrent Perl semantics in the uniprocess execution model of perl.
Syntax-Keyword-Match PEVANS 0.01 a match/case syntax for perl
TOML-XS FELIPE 0.01 Parse TOML with XS
TableData PERLANCAR 0.1.3 Specification for TableData::*, modules that contains table data
TableDataRoles-Standard PERLANCAR 0.007 Standard set of roles for TableData
Text-Table-TickitWidget PERLANCAR 0.001 View table data on the terminal using Tickit::Widget::Table
Tree-Trek PRBRENAN 20210424 Trek through a tree one character at a time.
Trim PRBRENAN 20210401 Trim various things by removing leading and trailing whitespace.
UniEvent-Socks SYBER v0.1.0 Socks support for UniEvent's tcp handles.
Unicode-Confuse BKB 0.01 abstract here.
Win32-Symlinks ZARABOZO 0.03 A maintained, working implementation of Perl symlink built in features for Windows.
XS-Parse-Keyword PEVANS 0.01 XS functions to assist in parsing keyword syntax

Stats

Number of new CPAN distributions this period: 83

Number of authors releasing new CPAN distributions this period: 50

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 16
2 KOBOLDWIZ 4
3 MICVU 4
4 HOEKIT 3
5 OODLER 3
6 PEVANS 3
7 PRBRENAN 2
8 DKECHAG 2
9 ZARABOZO 2
10 XSAWYERX 2
11 LNATION 2
12 CORION 2
13 SYBER 1
14 SIMBABQUE 1
15 DBOOK 1
16 LTM 1
17 CDN 1
18 BOD 1
19 BKB 1
20 RVOSA 1
21 GROUSSE 1
22 NATARAJ 1
23 HAARG 1
24 CCM 1
25 ETJ 1
26 CONTRA 1
27 KARASIK 1
28 OVID 1
29 TOBYINK 1
30 ASDAGO 1
31 CHROMATIC 1
32 VRAG 1
33 ABIGAIL 1
34 KEEDI 1
35 DOOJONIO 1
36 DERIV 1
37 PLICEASE 1
38 FELIPE 1
39 INA 1
40 JMICO 1
41 FAYLAND 1
42 OALDERS 1
43 UTASHIRO 1
44 DFUG 1
45 BRAINBUZ 1
46 RRWO 1
47 UTGWKK 1
48 ERICLEE 1
49 SANKO 1
50 DJERIUS 1

Today I was invited to join Gabor Szabo for a live pair programming session, where we worked on adding Docker and CI to his course management application. You can view the video of our informal competition who is the worst typist here.

At first I was bit skeptical about the concept of live coding (who wants to watch people google^w code for two hours?), but in the end it was a funny and informative (for me) session. Maybe I'm just totally deprived of live human interaction (thanks, Corona), but I think I'd enjoy similar sessions also under normal circumstances.

Things I learned

  • I forgot a lot of docker command line options after mostly using docker-compose.
  • There is no really smooth way to COPY a lot of dirs into the container.
  • Adding a .dockerignore file (to ignore at least ~/.git/) saves some time and network, because docker will not send the ignored files to the docker daemon in the famous sending build context to docker daemon step at the start of each build.
  • -P exposes the ports listed in EXPOSE, but maps them to random ports on the host (which makes no sense during dev, but probably when deploying to clouds)
  • Some people prefer -ti, some prefer -it
  • I'm a bit rusty on using the github pull request workflow (esp. the part where you have to fetch upgrades from upstream), due to mostly working on repos where several devs have direct write access.
  • Setting up github CI is really not a lot of work (at least to only run the basic tests). Only 16 lines of YAML. I will try to add this to my CPAN github repos.

If you're interested in the Dockerfile aspect of this session, may I point you to my talk Writing a good Dockerfile for a (Perl) app from the 2020 Perl Conference, where I elaborate on some of the finer points, and with better preparation than today :-)

Oh, and this reminds me that I should submit a talk (maybe on docker-compose?) for this years Perl & Raku conference. The CfP runs until tomorrow, so I better hurry.

[This article is part of our Popular articles project to update Perl.com for contemporary practices]

If you’re reading this article, you’re likely looking for a simple way to download and install the Perl programming language. Or you already have Perl installed as part of your operating system, but it’s older than the currently-supported versions (5.32.1 or 5.30.3) and you’d like to use the latest and greatest features. The download options may seem daunting, especially if you’re new to computers or programming. We’ll take things step by step, and soon you’ll be on your way to writing your first Perl program.

A word of warning, though: Several of these steps (and usually Perl itself) require using your computer’s command-line or terminal interface.

The first step: Download pre-built

If you’re getting started in Perl development, you may only need a pre-built binary distribution. Further on, though, you might want to consider building your own, especially if you need to juggle different versions to support different environments or want to use a later version than is available pre-made.

For now, though, let’s consider the pre-built options. You have several, depending on what computer operating system you’re using.

Microsoft Windows

The two main “flavors” of Perl for Windows are ActiveState Perl and Strawberry Perl. Which one you choose depends on what you plan to use it for.

ActiveState provides a free community edition of ActivePerl licensed only for development purposes. If you intend to do commercial work or want technical support beyond community forums, you’ll need to subscribe to a team plan or higher.

The free community edition is also 64-bit only, and as of this writing, only the earlier versions 5.28 (2018) and 5.26 (2017) are available, with an experimental 5.32 (2020) release licensed for any purpose. The latter is also currently only installable via the Windows command line; earlier versions use a standard Windows setup wizard.

Strawberry Perl is a Perl environment for Windows that strives to be as close as possible to Perl on Unix and Linux systems, where the language got its start. Besides the Perl binaries, it also includes a compiler, related tools, external libraries, and database clients. This is important as many modules for extending Perl’s functionality need a compiler. It’s also available in both 64-bit and 32-bit editions of the current 5.32 version.

What do I recommend? There’s no escaping Perl’s Unix heritage, so you’ll have an easier time with Strawberry Perl. That said, if you think you’ll be taking advantage of ActiveState’s commercial offerings of support and their ActiveState Platform for managing different language runtimes, you may want to give them a try.

Windows also has two Linux-like environments in the form of Cygwin and Windows Subsystem for Linux. Follow the Linux directions below to install Perl in one of these.

There is also the Chocolatey package manager for Windows, which provides an option for installing either ActiveState or Strawberry Perl.

Apple macOS

macOS comes with Perl pre-installed: version 5.18 (2013) on macOS Catalina 10.15 and 5.28 (2018) on Big Sur 11. But, Apple has said that scripting language runtimes are deprecated, and are only “included … for compatibility with legacy software.” You should consider installing your own.

Like Windows, ActiveState has a free community edition for developers. The Windows caveats above apply, except for a current Perl version 5.32—it’s “coming soon” as of this writing.

Your best bet is to install the Homebrew package manager in the macOS Terminal application (after installing its requirements), and then issue the command brew install perl. This will install the latest version of Perl, as well as give you instructions for making sure that installed Perl modules stay that way across updates by Homebrew.

Linux or another Unix-like system

Like macOS, most Linux and Unix systems come with Perl pre-installed, or installable using the operating system’s software package manager. Also like macOS, these are usually older versions provided for compatibility with other software provided by the OS.

To install your own on Linux, you can go the ActiveState route as above, or also use the Homebrew package manager. There are several requirements to install first, and then you can follow the directions for installing Homebrew and issue the command brew install perl.

For other Unix systems with an older version of Perl, I’m afraid you’re going to have to build from source as detailed below.

Next steps: Building your own with perlbrew or plenv

Perl’s source code (the instructions that build a program) is freely available and compiles on over 100 platforms. You can download it directly and build a version yourself, after installing any prerequisite packages used to build software on your operating system (see below). However, most Perl developers choose to use a tool to automate that process and manage different versions of Perl side-by-side. Enter perlbrew.

Perlbrew requires an already-installed system version of Perl, but it can be as old as 5.8 (2002), which should cover most Linux and Unix systems in use today. Once you’ve installed your operating system’s build tools and followed the directions on the perlbrew home page, typing perlbrew install 5.32.1 followed by perlbrew switch 5.32.1 will install and switch to the latest version of Perl as of this writing. Installing older versions of Perl and switching between them use the same steps, e.g.:

perlbrew install 5.30.3 --as older-perl
perlbrew switch older-perl

I use an alternative, plenv, which uses a different mechanism to manage versions of Perl using the bash command shell. It also enables you to use different versions of Perl depending on which file system directory you’re working in. It’s set up using either Homebrew or git.

Windows users have the option of berrybrew, which acts much like perlbrew for Strawberry Perl with slightly different options.

Building from the source directly

If you feel you don’t need to manage multiple installations of Perl or you want to do things old-school, you can always download and build directly from the source code. Select “Download Latest Stable Source” from the Perl Download web page, then unarchive it into a directory.

You should always check the included README files for information on how to build on your system; there’s a generic one as well as specific READMEs for various platforms (README.linux, README.macosx, README.win32, etc.). Note that the README.macosx document applies to current versions of macOS, which was previously called Mac OS X; README.macos is for the “Classic” Macintosh operating system, unsupported since 2004.

On most Unix-like systems (including macOS), you can then configure, build, test, and install Perl by issuing the following commands:

./Configure -des -Dprefix=/usr/local/
make
make test
sudo make install

This will build Perl with all default options for your system and install it in the /usr/local directory.

Up and running

Regardless of whether you’ve chosen to install a pre-built package or roll your own, you should now be able to issue the following at your command line:

perl -v

…and receive a reply that looks something like this:

This is perl 5, version 32, subversion 1 (v5.32.1) built for darwin-2level
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2021, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl".  If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

Congratulations, you’re now using the latest version of Perl on your computer! Now head on over to Perl.org and start learning!

The fourth part of the live development course management application using Mojolicous together with Mark Gardner.

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

Part 1

Write a script to display the first 20 Chowla Numbers.

Solution


use strict;
use warnings;
use constant CHOWLA_COUNT => 20;
sub factor{
    my($n) = @_;
    my @factors = ();
    foreach my $j (2..sqrt($n)){
        push @factors, $j if $n % $j == 0;
        push @factors, ($n / $j) if $n % $j == 0 && $j ** 2 != $n;
    }    
    return @factors;  
}

sub chowla{
    my(@factors) = @_;
    my $sum = unpack("%32I*", pack("I*", @factors)); 
}

MAIN:{
    my @chowla_numbers;
    for my $n (1 .. CHOWLA_COUNT){
        push @chowla_numbers, chowla(factor($n));
    }
    print join(", ", @chowla_numbers) . "\n"; 
}

Sample Run


$ perl perl/ch-1.pl
0, 0, 0, 2, 0, 5, 0, 6, 3, 7, 0, 15, 0, 9, 8, 14, 0, 20, 0, 21

Notes

This code borrowed quite a bit a previous challenge involving Perfect Numbers. Indeed, the code is nearly identical! After we get the factors there is only the matter of summing them and displaying them.

Part 2

Place the given unique numbers in the square box so that sum of numbers in each box is the same.

Solution


use strict;
use warnings;
##
# You are given four squares as below with numbers named a,b,c,d,e,f,g.
# to place the given unique numbers in the square box so that sum of 
# numbers in each box is the same. 
#               (1)                    (3)
#        +--------------+      +--------------+
#        ?              ?      ?              ?
#        ?      a       ?      ?      e       ?
#        ?              ? (2)  ?              ?  (4)
#        ?          +---+------+---+      +---+---------+
#        ?          ?   ?      ?   ?      ?   ?         ?
#        ?          ? b ?      ? d ?      ? f ?         ?
#        ?          ?   ?      ?   ?      ?   ?         ?
#        ?          ?   ?      ?   ?      ?   ?         ?
#        +----------+---+      +---+------+---+         ?
#                   ?       c      ?      ?      g      ?
#                   ?              ?      ?             ?
#                   ?              ?      ?             ?
#                   +--------------+      +-------------+
##
use AI::Prolog;

my $prolog = do{
    local $/;
    ;
}; 
$prolog = new AI::Prolog($prolog); 
$prolog->query("sums_in_squares([1,2,3,4,5,6,7], Squares).");

my $result;
print join("\t", "a" .. "g") . "\n";  
while ($result = $prolog->results()){
    print join("\t", @{$result->[2]}) . "\n";
}

__DATA__
member(X,[X|T]).
member(X,[H|T]):- member(X,T).
sums_in_squares(Numbers, [A, B, C, D, E, F, G]):-  
    member(A, Numbers), 
    member(B, Numbers),
    member(C, Numbers),
    member(D, Numbers),
    member(E, Numbers),
    member(F, Numbers),
    member(G, Numbers),
    A \= B, A \= C, A \= D, A \= E, A \= F, A \= G,
    B \= A, B \= C, B \= D, B \= E, B \= F, B \= G,
    C \= A, C \= B, C \= D, C \= E, C \= F, C \= G,
    D \= A, D \= B, D \= C, D \= E, D \= F, D \= G,
    E \= A, E \= B, E \= C, E \= D, E \= F, E \= G,
    F \= A, F \= B, F \= C, F \= D, F \= E, F \= G,
    G \= A, G \= B, G \= C, G \= D, G \= E, G \= F,
    Box1 is A + B,
    Box2 is B + C + D,
    Box3 is D + E + F,
    Box4 is F + G,
    Box1 == Box2,
    Box2 == Box3,
    Box3 == Box4.

Sample Run


$ perl perl/ch-2.pl
a       b       c       d       e       f       g
3       7       2       1       5       4       6
4       5       3       1       6       2       7
4       7       1       3       2       6       5
5       6       2       3       1       7       4
6       4       1       5       2       3       7
6       4       5       1       2       7       3
7       2       6       1       3       5       4
7       3       2       5       1       4       6

Notes

This sort of problem practically screams out for a Prolog solution! In the interest of keeping with the name, if not the spirit of the weekly challenge, this first part is indeed Perl, albeit using AI::Prolog, a module which offers a pure Perl implementation of a basic Prolog.

I have used AI::Prolog previously and it’s a neat way to take advantage of Prolog within a Perl based solution. The two main downsides are that (1) it is not a full ISO Prolog and (2) it is slow. So very very slow. I suspect, in fact, there is a serious bug in the implementation. Even accounting for the fact that a pure Perl Prolog would be much slower than one written in C, such as Gnu Prolog, the execution time differences are laughably dramatic. I didn’t bother with precise metrics but the code above takes about an hour to run on fairly current hardware (i.e. my 2018 Mac Mini). Essentially the same code run on the same hardware but with Gnu Prolog completes in mere seconds.

Still, this is a nice way to incorporate a bit of Symbolic AI in a Perl code base if there is a small search space. Say, for some simple game logic or a small chat bot.

The pure Prolog solution I did for this uses the same approach, in part, although I also wrote this to take advantage of Gnu Prolog’s FD solver. The FD version of the code completes in about 10ms!

References

Challenge 109

Sarvadaman D. S. Chowla

AI::Prolog

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

  1. Dancer2 - Lightweight yet powerful web application framework
    • Version: 0.301002 on 2021-04-18
    • Votes: 124
    • Previous version: 0.301001 was 1 month, 1 day before
  2. Data::Alias - Comprehensive set of aliasing operations
    • Version: 1.21 on 2021-04-22
    • Votes: 14
    • Previous version: 1.21 was 3 years, 4 months, 14 days before
  3. Graph - graph data structures and algorithms
    • Version: 0.9721 on 2021-04-18
    • Votes: 26
    • Previous version: 0.9720 was 24 days before
  4. JavaScript::V8 - Perl interface to the V8 JavaScript engine
    • Version: 0.10 on 2021-04-23
    • Votes: 16
    • Previous version: 0.09 was 2 years, 12 days before
  5. List::AllUtils - Combines List::Util, List::SomeUtils and List::UtilsBy in one bite-sized package
    • Version: 0.19 on 2021-04-23
    • Votes: 30
    • Previous version: 0.18 was 7 months, 18 days before
  6. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20210420 on 2021-04-21
    • Votes: 34
    • Previous version: 5.20210320 was 1 month before
  7. Module::ScanDeps - Recursively scan Perl code for dependencies
    • Version: 1.31 on 2021-04-21
    • Votes: 13
    • Previous version: 1.30 was 3 months, 8 days before
  8. Mojolicious::Plugin::Authentication - A plugin to make authentication a bit easier
    • Version: 1.36 on 2021-04-21
    • Votes: 17
    • Previous version: 1.33 was 3 years before
  9. PDL - Perl Data Language
    • Version: 2.039 on 2021-04-24
    • Votes: 41
    • Previous version: 2.037 was 8 days before
  10. PDL::Stats - a collection of statistics modules in Perl Data Language, with a quick-start guide for non-PDL people.
    • Version: 0.78 on 2021-04-24
    • Votes: 14
    • Previous version: 0.76 was 4 months, 5 days before
  11. Perl::MinimumVersion - Find a minimum required version of perl for Perl code
    • Version: 1.40 on 2021-04-22
    • Votes: 18
    • Previous version: 1.38 was 6 years, 8 months before
  12. Pod::Weaver - weave together a Pod document from an outline
    • Version: 4.017 on 2021-04-17
    • Votes: 32
    • Previous version: 4.015 was 4 years, 6 months, 2 days before
  13. Prima - a perl graphic toolkit
    • Version: 1.61 on 2021-04-23
    • Votes: 33
    • Previous version: 1.60 was 5 months, 23 days before
  14. SPVM - Static Perl Virtual Machine. Fast Calculation, Fast Array Operation, and Easy C/C++ Binding.
    • Version: 0.0946 on 2021-04-23
    • Votes: 21
    • Previous version: 0.0942 was 8 days before
  15. SVG - Perl extension for generating Scalable Vector Graphics (SVG) documents.
    • Version: 2.86 on 2021-04-22
    • Votes: 18
    • Previous version: 2.85 was 9 months, 20 days before

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

Week's winners (+3): App::perlimports 

Build date: 2021/04/24 19:10:30 GMT


Clicked for first time:


Increasing its reputation:

Jonathan writes:


March didn't see me doing that many grant hours; I was keeping my keyboard time down for the first half of the month, and then had a lot to catch up on in the second half (and still needed to avoid putting in more than a usual working day). On the upside, the time that was spent was productive: I got some way into implementing more of Raku's multiple dispatch semantics in terms of the new dispatcher. I've written a blog post about that work (although some of the work it covers was done during April).

Total time worked:: 7 hours 29 minutes

Following issues raised within the community, the CAT opened an investigation into community conduct. A second investigation was opened based on information discovered during the first investigation.

What follows constitutes our second transparency report as well as an additional conclusion statement by the CAT. If you have not read it already, we highly recommend you read our latest Community Affairs Team Update.

Investigation #1

Based on a recent public post viewed by the CAT, the CAT investigated two individuals for potentially unacceptable behavior over IRC and Twitter. The investigation found that the first individual continued communication on multiple platforms despite being asked repeatedly to stop. Past behavior by the first individual was discovered during the course of the investigation. The CAT opened a separate investigation into this past behavior, and that investigation’s results are explained as part of “Investigation #2”.

Regarding the second individual investigated as part of “Investigation #1”, the CAT has decided to issue them a warning. The CAT is in contact with them and has scheduled a meeting with them to discuss this.

Investigation #2

Based on the previous investigation, the CAT investigated past behavior by the first individual. The CAT found that as an attendee of a 2019 Perl event, they had made repeated discriminatory statements and arguments in a conversation with the target, which was also overheard by other attendees. The individual continued arguing for this position despite being asked repeatedly to stop, the next day there were asked to leave the event.

They were instructed not to repeat the discriminatory statements and arguments. They were told an apology should not be made to the target of the harassment. Later, the individual repeated the discriminatory statements publicly on Twitter in discussions with other members of the community which were also viewed by the target. The target told the individual not to contact them ever again. Despite being asked explicitly not to contact them, the individual later contacted the target by email, which was an additional instance of unacceptable behavior.

Consequences

The CAT has informed the individual investigated as part investigation #1 and #2 that they are banned from attending any Perl Foundation conferences or events in perpetuity.

The CAT has instructed the individual to leave and cease participation on any public IRC channels on irc.perl.org, leave and cease participation on the Perl and Raku public channels on Freenode, unsubscribe and cease participation on any Perl and Raku community mailing lists including but not limited to the perl5-porters mailing list. The CAT has informed them to not contact the targets of their behavior from “Investigation #1” or “Investigation #2”. The CAT has informed them to not repeat the offending statements or arguments from “Investigation #2”. If the CAT decides the letter or the spirit of this decision has been violated, it may: explicitly extend the scope of the ban, take further technical measures to ensure compliance, or take other actions as it deems necessary.

Other findings

In addition to the findings of both investigations, the CAT wants to make it clear that separate and inclusive of the two reported investigations, it found many instances of communication which alone may not have constituted unacceptable behavior, but when taken together did constitute unacceptable behavior. The CAT asks all members of the Perl community to be respectful of others and that discriminatory or harassing conduct will not be tolerated.

Conclusion

The Community Affairs Team is committed to a safe environment, at conferences and physical events as well as online between members of the Perl and Raku community. If you have comments regarding this public statement you can send them to cat@perlfoundation.org with the word “comment” in the subject. If you want to report: discriminatory, harassing, or otherwise unacceptable behavior, including evasion of CAT decisions, please contact cat@perlfoundation.org. For examples of what may constitute unacceptable behavior, please see the Standards of Conduct for this year’s Conference in the Cloud.

The CAT’s purpose is to foster a positive and safe environment for anyone who shares an interest in Perl and Raku.

It has been one year since the Community Affairs Team was first announced in March of 2020. In June, the Perl & Raku Conference in the Cloud took place. This was the first conference where Community Affairs Moderators were present to respond to and handle Standards of Conduct violations. Prior to the conference, Community Affairs Moderators and the CAT committee for the event received training on handling and responding to SoC complaints within the community. A month later in July, the Chair of the CAT was appointed by the TPF board. In October, the first Standards of Conduct transparency report was released.

Following that, the CAT has been working on a charter document which outlines in more concrete terms its role and responsibilities as it relates to the community, as well as an updated Standards of Conduct which would apply not just to conferences, but to other TPF online spaces. Recent events in the community have expedited the CAT’s work and the board’s approval of these documents, which are planned to be publicly released within the next week.

The CAT is also preparing for the upcoming Perl & Raku Conference in the Cloud, and training similar that received in 2020 is planned for the moderators and CAT committee for this event. The CAT thanks the many people who provided their input to the formation of the CAT, and Samantha McVey, Stuart Mackintosh, and Ricardo Signes for continuing their work on the CAT committee as well as their work on the CAT committee during last year’s conference.

The Community Affairs Team is committed to a safe environment, at conferences and physical events as well as online between members of the Perl and Raku community. If you have comments regarding this update you can send them to cat@perlfoundation.org with the word “comment” in the subject.

The third part of the live development course management application using Mojolicous together with Mark Gardner.

I've been using Digital Ocean for many years for some of my hosting needs. Besides the nice GUI they also have an API and there is a Perl module called DigitalOcean that can be used to access it.

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

Part 1

Write a script to declare a variable or constant and print it’s location in the memory.

Solution


use strict;
use warnings;
use Devel::Peek;
use Capture::Tiny q/capture_stderr/;
use constant A => "test";
my $a = 1;    
my $address;  
my $stderr = capture_stderr {
    Dump(A)
};
$stderr =~ m/at\s(0x.*\n).*/;
$address = $1;  
chomp($address);
print "Address of constant A: $address\n"; 
$stderr = capture_stderr {
    Dump($a)
};
$stderr =~ m/at\s(0x.*\n).*/;
$address = $1;  
chomp($address);
print "Address of \$a: $address\n";

Sample Run


$ perl perl/ch-1.pl
Address of constant A: 0xfd31ae90
Address of $a: 0xfdb2f770

Notes

This is a somewhat unusual challenge for Perl. Sometimes these challenges allow for a certain amount of interpretation. For example, under the hood, the representation of Perl data in memory involves more complicated data structures. I think it is in the spirit of this challenge to demonstrate access to this, without necessarily implementing complete and fully generalized solution.

Here I use Devel::Peek in order to get a report on the underlying memory usage of the given variables. The Dump function only prints a memory report to STDERR, so in order to obtain the information we seek Capture::Tiny is used to encapsulate the STDERR output and save it to a variable. A regex is then used to pull out the memory address which is then printed.

The memory address printed here is the reference address. For additional details on Perl’s core see the perlguts documentation.

Part 2

Write a script to display the first 10 Bell Numbers.

Solution


use strict;
use warnings;

sub bell_triangle{
    my($n) = @_; 
    my @bell_numbers = ([]);
    $bell_numbers[0]->[0] = 1;
    for (my $i=1; $i<=$n; $i++) {
      $bell_numbers[$i]->[0] = $bell_numbers[$i-1]->[$i-1];
      for (my $j=1; $j<=$i; $j++){  
          $bell_numbers[$i]->[$j] = $bell_numbers[$i-1]->[$j-1] + $bell_numbers[$i]->[$j-1];
       }
   }
   return $bell_numbers[$n]->[0];
}

MINA:{
    for my $b (0 .. 9){  
        print "B_$b: " . bell_triangle($b) . "\n";  
    } 
}

Sample Run


$ perl perl/ch-2.pl
B_0: 1
B_1: 1
B_2: 2
B_3: 5
B_4: 15
B_5: 52
B_6: 203
B_7: 877
B_8: 4140
B_9: 21147

Notes

This is an interesting problem. At first glance one might be tempted to proceed and compute the partitions and then take the total number of them all. Instead, it turns out that there is a simpler closed form solution whereby we can compute the Bell Triangle and then take the values on the leftmost diagonal to be the Bell Numbers as required.

For fun the Prolog solution does indeed compute the partitions instead of simply using the Bell Triangle!

References

Challenge 108

perlguts

Bell Numbers

Bell Triangle

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

Part 1

Write a script to generate self-descriptive numbers.

Solution


use strict;
use warnings;
use Thread; 
use boolean;
use constant SDN_COUNT => 3;
use constant THREAD_COUNT => 4;
use constant RANGE_SIZE => 10_000;

sub self_describing{
    my($i) = @_;
    my @digits = split(//, $i);
    for my $x (0 .. @digits - 1){
        my $count = 0;
        for my $j (0 .. @digits - 1){
            $count++ if($digits[$j] == $x);
            return false if($count > $digits[$x]);
        }
        return false if($count != $digits[$x]);
    }
    return true;
}

sub self_describing_number{
    my($start, $end) = @_;  
    my @r = (); 
    for(my $i = $start; $i < $end; $i++){
        push @r, [length($i), $i] if(self_describing($i));  
    }   
    return \@r;  
}

MAIN:{
    my @threads; 
    my $count = 0; 
    my $lower = 1; 
    my $upper = RANGE_SIZE; 
    do{
        for(0..(THREAD_COUNT - 1)){  
            my $t = Thread->new(\&self_describing_number, ($lower, $upper));
            push @threads, $t;  
            $lower = $upper + 1;  
            $upper = $lower +  RANGE_SIZE;  
        }  
        foreach my $t (@threads){  
            my $sdns = $t->join();                 
            foreach my $sdn (@{$sdns}){ 
                print "Base " . $sdn->[0] . ":" .  $sdn->[1] . "\n" if $count < SDN_COUNT; 
                $count++;  
            }  
        }   
        @threads = ();   
    } while($count < SDN_COUNT);
}

Sample Run


$ perl perl/ch-1.pl
Base 4:1210
Base 4:2020 
Base 5:21200

Notes

Part 1 this week is repeated from Challenge 043. In order to provide something fresh for the same problem I modified the previous code to be multi-threaded.

Part 2

Write a script to list methods of a package/class.

Solution


use strict;
use warnings;

sub analyze{
    my($file) = @_;
    my @subs;
    my @uses; 
    my @subroutines;
    my $subs = `perlanalyst $file --analysis Sub`;
    $subs =~ s/$file://;
    @subs = split(/\n/, $subs);   
    my $uses = `perlanalyst $file --analysis Use`;
    $uses =~ s/$file://;
    @uses = split(/\n/, $uses);   
    for my $s (@subs){
        $s =~ s/\s+//;
        my @fields = split(/:/, $s); 
        push @subroutines, $fields[1] if(length($s) > 0); 
    }
    push @subroutines, "BEGIN" if(@uses); 
    return @subroutines; 
}

MAIN:{
    my $FILE = $ARGV[0];
    my @subroutines = analyze($FILE);
    print join("\n", sort {$a cmp $b} @subroutines) . "\n"; 
}

Sample Run


$ perl perl/ch-2.pl perl/Calc.pm 
BEGIN
DESTROY
add
div
mul
new

Notes

Getting a list of methods can mostly be done via just some plain analysis of the code. Rather than re-invent the wheel I am using a module, Perl::Analysis::Static, to do that for me. This is a pretty neat tool but has been left in an alpha state. The most stable way to use it is via the command line instead of its incomplete API. In this code I call the perlanalyst command and then parse the output.

If given a BEGIN block or if use-ing a module Perl will execute a BEGIN at compile time. I would argue that this is out of scope for this challenge. However, as given in the problem statement we are expected to catch this it seems. I do this by inspecting the perlanalyst output for use lines. I could have done a few other things as well but decided not to do more with this since it seems like a funny requirement anyway!

References

Challenge 107

Challenge 043

Perl::Analysis::Static

@davorg / Friday 07 May 2021 13:51 UTC