Bitbucket Pipelines (the CI system) for Perl projects

Perl Maven

Published by Gabor Szabo on Monday 25 October 2021 10:30

Bitbucket Pipelines (the CI system) for Perl projects

#535 - Exercism and Perl

Perl Weekly

Published on Monday 25 October 2021 10:00

Hi there!

A long, long time ago I contributed a few Perl-related exercises to Exercism, but then for another long time I only recommended it, but didn't use it myself. Recently I returned to it with the hope to use it as a platform to allow my students to practice. I noticed that the Perl track has 62 exercises while many of the other tracks have more. Some of them twice as many.

Have you tried doing the Perl track recently? Are you a mentor on the Perl track? Have you contributed an exercises?

I wonder if it would be a good idea for Mohammad, to post his Weekly challenges as exercises on Exercism.

Enjoy your week!

Please spare ten minutes for the Calgary Research Study

Perl Foundation News

Published by Nic Evans on Monday 25 October 2021 03:44

Have you completed the online survey which forms part of the research by Dr. Ann Barcomb of the University of Calgary to understand episodic, or occasional, participation in the Perl and Raku communities. The research is being undertaken in collaboration with The Perl Foundation. More information is in the launch article.

The survey requires 125-150 participants before analysis of the results can begin. To date 95 people have completed the survey.

If you've already filled the survey, please forward it to friends or colleagues who are a part of the community too.

As well as this online survey, the research team are looking for interview participants to look at your experiences working with episodic contributors, and episodic contributions, in the Perl/Raku community. If you are interested, please read the full invitation to take part.

Caught in the Middle With SEDOL

RabbitFarm Perl

Published on Sunday 24 October 2021 15:17

The examples used here are from The Weekly Challenge problem statement and demonstrate the working solution.

Part 1

You are given an integer. Write a script find out the middle 3-digits of the given integer, if possible, otherwise show a sensible error message.

Solution


use strict;
use warnings;
use POSIX;
sub middle_3{
    my($i) = @_;
    $i = abs($i);
    my $length = length($i);
    return "even number of digits" if $length % 2 == 0;
    return "too short" if $length < 3;
    my $middle = ceil($length / 2);
    return substr($i, $middle - 2, 3);
}

MAIN:{
    print middle_3(1234567) . "\n";
    print middle_3(-123) . "\n";
    print middle_3(1) . "\n";
    print middle_3(10) . "\n";
}

Sample Run


$ perl perl/ch-1.pl
345
123
too short
even number of digits

Notes

Maybe on of the more interesting things about this is just what we consider the middle 3. Truly it only makes sense for an integer with an odd number of digits. But could we have stretched the idea to allow for an even number of digits, perhaps with some left padding? Perhaps, but here we don't. So all integers with only 1 or 2 digits are discarded as are those with an even number of digits. Negative numbers are allowed, but we do not consider the minus sign in determining the middle.

Part 2

You are given 7-characters alphanumeric SEDOL. Write a script to validate the given SEDOL. Print 1 if it is a valid SEDOL otherwise 0.

Solution


use strict;
use warnings;
use boolean;

sub is_sedol{
    my($sedol) = @_;
    my $base = substr($sedol, 0, 6);
    my $check_digit = substr($sedol, 6, 1); 
    ##
    # check length
    ##
    return false if length($sedol) != 7;
    ##
    # check for alphanumerics only
    ##
    my $test_base = $base;
    $test_base =~ tr/[0-9][B-Z]//d;
    return false if $test_base;
    ##
    # confirm the check_digit
    ##
    return false if $check_digit != compute_check_digit($base);
    ##
    # all tests passed!
    ##
    return true;
}

sub compute_check_digit{
    my($base) = @_;
    my @chars = split(//, $base);
    my @weights = (1, 3, 1, 7, 3, 9),
    my $sum = 0;
    do{
        my $c = ord(shift @chars);
        if($c >= 66 && $c <= 90){
            $sum += (($c - 64 + 9) * shift @weights);
        }
        if($c >= 48 && $c <= 57){
            $sum += (($c - 48) * shift @weights);
        }
    }while(@chars);
    return (10 - ($sum % 10)) % 10
}

MAIN:{
    print is_sedol(2936921) . "\n";
    print is_sedol(1234567) . "\n";
    print is_sedol("B0YBKL9") . "\n";
}

Sample Run


1
0
1

Notes

The rules around SEDOLs are a bit more complex than this problem lets on. I won't recount them all here, but suffice to say we are dealing with a quite idealized set of validations here. For example, prior to 2004 only numerals were allowed, but since then letters are allowed. But only a numeral can follow a letter. Again, though, those are only rules that apply for a certain time range.

Here we are just checking on length, whether or not the SEDOl contains all numerals and/or (uppercase) letter, and the checksum validation.

References

Challenge 135

Stock Exchange Daily Official List (SEDOL)

Some Perl Code In Memory of a Great Scientist

blogs.perl.org

Published by martin on Sunday 24 October 2021 17:10

On August 21, 2021, famous Polish mathematician Andrzej Schinzel passed away at the age of 84. He was one of the great minds behind modern number theory. May he rest in peace. I have extended one of my CPAN modules relating to his work and dedicated the release to his memory.

I'll outline one of the insights credited to Beeger (1884-1965) and Schinzel. Suppose we want to factor an integer number of the form kn ± 1. We can use classical Algebra to factor rational polynomials xn ± 1. For example, x21 + 1 = (x + 1)(x2 - x + 1)(x6 - x5 + x4 - x3 + x2 - x + 1)(x12 + x11 - x9 - x8 + x6 - x4 - x3 + x +1). These factors always have integer coefficients, are called cyclotomic polynomials, and are "easy" to obtain. Evaluating these polynomials at x = k yields us a first partial factorization of our number.

To continue our example, we see that 221 + 1 = 3·3·43·5419, 321 + 1 = 4·7·547·682969, etc. Can we do better? Enter Aurifeuillean factorization. Aurifeuille, Le Lasseur and Lucas observed that some cyclotomic polynomials can be written in the form C2 - n·x·D2 = (C - √(n·x)D)(C + √(n·x)D) where n is a positive integer and C and D are again polynomials with integer coefficients. In algebraic terms, while irreducible over the field of Rationals ℚ, cyclotomic polynomials may be reducible over some extension field ℚ[√n]. Now if the square root of n·x happens to be an integer, that is when x is n times a square number, the formula above gets all integer, splitting a cyclotomic factor into two smaller integer factors. In short, Aurifeuille & Co. improve our factorization for some, but not all combinations of n and k.

For square-free n > 1, meaning n without square divisors, Lucas C,D polynomials can split one cyclotomic factor of nn - 1 if n ≡ 1 (mod 4), or of nn + 1 otherwise, into two smaller factors. Note that the base and the exponent are equal.

It turns out that these are special cases of something more profound. Beeger and Schinzel found the best currently known generalization. Essentially, they give us C,D polynomials covering more cases. To illustrate their range, let's compare some factorizations of 21st powers plus one. We leave out perfect powers, as kn21 can be better treated as an n21st power of k than as a 21st power of kn.

+-----+------------+-----------------------------------------+
|  n  |  kind      |  factors of n^21+1                      |
+-----+------------+-----------------------------------------+
|     +------------+-----------------------------------------+
|  2  | cyclotomic |  3  3  43  5419                         |
|     +------------+-----------------------------------------+
|     | complete   |  3  3  43  5419                         |
+-----+------------+-----------------------------------------+
|     +------------+-----------------------------------------+
|  3  | cyclotomic |  4        7  547  682969                |
|     +------------+-----------------------------------------+
|     | Lucas      |  4     1  7  547  682969                |
|     +------------+-----------------------------------------+
|     | Schinzel   |  4     1  7  547  301    2269           |
|     +------------+-----------------------------------------+
|     | complete   |  2  2     7  547  7  43  2269           |
+-----+------------+-----------------------------------------+
|     +------------+-----------------------------------------+
|  5  | cyclotomic |  6     21    13021    290639881         |
|     +------------+-----------------------------------------+
|     | complete   |  2  3  3  7  29  449  7  43  127  7603  |
+-----+------------+-----------------------------------------+
|     +------------+-----------------------------------------+
|  6  | cyclotomic |  6     21    13021    290639881         |
|     +------------+-----------------------------------------+
|     | complete   |  2  3  3  7  29  449  7  43  127  7603  |
+-----+------------+-----------------------------------------+
|     +------------+-----------------------------------------+
|  7  | cyclotomic |  8        43  102943    15772610449     |
|     +------------+-----------------------------------------+
|     | Lucas      |  8        43  113  911  15772610449     |
|     +------------+-----------------------------------------+
|     | Schinzel   |  8        43  113  911  51031  309079   |
|     +------------+-----------------------------------------+
|     | complete   |  2  2  2  43  113  911  51031  309079   |
+-----+------------+-----------------------------------------+

As we can see, "Schinzel" polynomials, as I like to call them, help us with many large cyclotomic factors Lucas polynomials leave aside.

As I wanted to include Aurifeuillean factorization in my CPAN module Math::Polynomial::Cyclotomic for quite some time, I finally took the opportunity to do that. I implemented Lucas and "Schinzel" polynomials there as well as methods applying these to find algebraic factors of integer numbers of the form kn ± 1. Factoring large numbers can be hard—crypto-algorithms like RSA rely on that—, and a partial factorization can be the crucial step to reduce the problem to a feasible magnitude. Curiously, Lucas C,D polynomials seem to be rare in computer algebra libraries and Schinzel's results even rarer. At least CPAN now has some of these. I intend to add a Raku version later. A treasure trove of other number-theoretic functions can be found in Dana Jacobsen's Math::Prime::Util, including some that are used in M::P::Cyclotomic.

Andrzej Schinzel published more than 200 research papers and was the expert for number-theoretic aspects of polynomials. I dedicate the latest release of Math::Polynomial::Cyclotomic to his memory.

References

(ccclxiv) 11 great CPAN modules released last week

Niceperl

Published by Unknown on Saturday 23 October 2021 15:53

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

  1. Alien::Build - Build external dependencies for use in CPAN
    • Version: 2.44 on 2021-10-20
    • Votes: 19
    • Previous version: 2.42 was 21 days before
  2. App::Netdisco - An open source web-based network management tool.
    • Version: 2.050003 on 2021-10-19
    • Votes: 13
    • Previous version: 2.050001 was 7 days before
  3. DateTime::TimeZone - Time zone object base class and factory
    • Version: 2.51 on 2021-10-22
    • Votes: 17
    • Previous version: 2.50 was 7 days before
  4. HTTP::BrowserDetect - Determine Web browser, version, and platform from an HTTP user agent string
    • Version: 3.35 on 2021-10-19
    • Votes: 22
    • Previous version: 3.34 was 2 months, 16 days before
  5. local::lib - create and use a local lib/ for perl modules with PERL5LIB
    • Version: 2.000028 on 2021-10-17
    • Votes: 84
    • Previous version: 2.000027 was 3 days before
  6. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20211020 on 2021-10-21
    • Votes: 36
    • Previous version: 5.20210920 was 1 month, 1 day before
  7. Mojolicious - Real-time web framework
    • Version: 9.22 on 2021-10-21
    • Votes: 462
    • Previous version: 9.21 was 2 months, 8 days before
  8. Object::Pad - a simple syntax for lexical slot-based objects
    • Version: 0.56 on 2021-10-22
    • Votes: 20
    • Previous version: 0.55 was 11 days before
  9. Search::Elasticsearch - The official client for Elasticsearch
    • Version: 7.715 on 2021-10-20
    • Votes: 42
    • Previous version: 7.714 was 2 months, 11 days before
  10. Selenium::Remote::Driver - Perl Client for Selenium Remote Driver
    • Version: 1.45 on 2021-10-21
    • Votes: 44
    • Previous version: 1.44 was 6 months, 25 days before
  11. Yancy - The Best Web Framework Deserves the Best CMS
    • Version: 1.078 on 2021-10-17
    • Votes: 41
    • Previous version: 1.077 was 1 month, 11 days before

Weekly Challenge 135

dev.to #perl

Published by Simon Green on Saturday 23 October 2021 12:39

Challenge, My solutions

TASK #1 › Middle 3-digits

Task

You are given an integer.

Write a script find out the middle 3-digits of the given integer, if possible otherwise throw sensible error.

My solution

This task was pretty straight forward.

  • Check the an integer was provided.
  • If it is negative, make it positive with the abs function.
  • Display an error if it contains an even number of digits, or one digit
  • The first character we want to show can be calculated by (length - 3) ÷ 2. Use this value with substr to display the middle three digit

Examples

$ ./ch-1.pl 1234567
345

$ ./ch-1.pl -123
123

$ ./ch-1.pl 1
too short

$ ./ch-1.pl 10
even numbers of digits

TASK #2 › Validate SEDOL

Task

You are given 7-characters alphanumeric SEDOL.

Write a script to validate the given SEDOL. Print 1 if it is a valid SEDOL otherwise 0.

My solution

The first thing that I need to do is check if the input is valid. I use the regular expression ^[B-DF-HJ-NP-TV-Z0-9]{6}[0-9]$ to perform this. According to the specification, vowels are not valid. Did anyone else sing the alphabet song when generating the regular expression? :)

I set the value of $sum to the last digit. I then go through the other digits. I work out the value of the digit in the position (0-9 if it is is a number, 10-35 if it is a letter) and multiple the weight.

If the resulting sum is divisible by 10, I return 1 (a valid SEDOL value), otherwise I return 0.

Examples

$ ./ch-2.pl 2936921
1

$ ./ch-2.pl 1234567
0

$ ./ch-2.pl B0YBKL9
1

13 reasons why you should not use Perl

dev.to #perl

Published by Parvez M Robin on Thursday 21 October 2021 20:15

Currently, I am conducting a natural language processing course. As part of the curriculum, I need to learn and code in Perl. I was exited! I was enthusiastic! However, the verb is "WAS". I am neither exited nor enthusiastic any more. I already have experience in C, CPP, C#, Java, Golang, Python, JavaScript, TypeScript and Bash. Among this versatile experience, Perl is now my second most hated language after Bash. Let me tell you why.

  1. Weird variable access: I have worked with typed language where I need to tell the type. I have worked with weakly typed language where the language knows which is which. Then comes Perl. It is weakly typed. But, I need to prefix a variable by either $ or @ or % to tell Perl about the type of variable. And I need to do it every time I access the variable. Even more - the prefix changes time to time based on the usage.

  2. Too much implicit code: Remember, explicit is always better than implicit. But, Perl works the opposite way. Consider the following snippet.

    while (<>) {
        print;
    }
    

    What this does is reads from the input stream in <> this command, stores it in a variable named $_, then prints that variable. Of course you can assign and use your own variable but Perl developers seem to prefer this. Well, I don't.

  3. Lacking readability: Continuing from the previous example, when someone sees that snippet, it is literally hard to get what it is doing. At least, it was hard for me.

  4. No clear parameter list: While declaring a function (called subroutine in Perl), it does not specify the parameter list. You will always pass a list of arguments and the function need to extract them from an array. The end product is too much boiler-plating with too less readability.
    This is what you will do, if you need to retrieve 3 parameters.

    sub func1 {
        my $x = shift;
        my $y = shift;
        my $z = shift;
        // do something with the variables
    }
    
    func1(1, 2, 3);
    
  5. Weirdly passing arrays to function: When you pass an array to a perl function, it flattens everything. Consider the following code.

    sub func1 { print scalar(@_); }
    
    @a = (1, 2, 3);
    @b = (4, 5, 6);
    func1(@a, @b);
    

    The scalar function returns the length of an array and the @_ variable holds the arguments as an array. So, scalar(@_) will give us the number of arguments. What do you think the output is? 2? It should be. But, it's perl and the output is 6.
    If you want to pass an array as an array, you need to make a reference of the array, pass the reference and de-reference it inside the function. Hell of a job for such a simple task!

  6. Weirder passing hash/map to function: Okay. When we pass something to a perl function, it flattens everything and makes a single array. What happens to hashes/maps? Well! It makes that an array too. And that array contains all the keys and values; in a single place. Consider the following code.

    sub func1 { print join ', ', @_; }
    
    %f = (one => 1, two => 2);
    func %f;
    

    What do you think the former code prints? My guess was it will print the keys of the map. At the worst case, it will print the values instead. Alas! The actual worst case worse than what I anticipated. It prints both keys and values. So, the output is one, 1, two, 2. And it becomes a mess when you want to reconstruct the map.
    The mess gets messier if you call the function like func1 %f, three, 3. How will you know what came from where?

  7. Cryptic RegEx handling: When you do a regular expression match, it automatically assigns some variables like $&, $`, $' etc. They are useful when you know them to be honest. But, when you just read the code, specially when you are from another background, it looks like a mess.

  8. Less Searchability: Consider the previous point. You are reading a perl program. You suddenly found use of undeclared variables like $& or $'. So, you googled about it - "what does $' means in perl". Alas! while you search something on the search engines, they generally stripes out spaces and punctuation. You will still have relevant results. But, they won't be as great as if you search - "what does dir mean in python".

  9. Pathetic debugging support: The debugging support for perl is in a word pathetic. It only supports some basic commands and the error messages are cryptic. Once you are stuck in somewhere, you are DONE!

  10. Too much implicit error handling: While the shown error messages are cryptic, there are a lot of errors that are not shown at all. Say, we have an array @a and we want to print it. Now, mistakenly we have typed print $a. It will just print nothing just like if the array was empty. In my opinion it either should through an error or print the memory address of @a. It does nothing. And you will never know that you have an error there.

  11. Inconsistent behavior: Say, we have a function like this

    sub one {
        return 'two';
    }
    

    Now we define two maps like the following

    %m1 = (one => 1);
    %m2 = (1 => one);
    print %m1;
    print %m2;
    

    It will print one1 and 1two. Can you make any sense of it? Well, I could not for a while. Turns out if your map's value coincides with one of the functions, it will call that function and use the function's return value as the map's value. But, it will not do such if your map's key coincides with a function.

  12. Poor IDE support: So far I have not seen any perl IDE that satisfies me. You can add plugin to VS Code or JetBrains IDEs to support perl. But, they are buggy and are not feature-rich.

  13. I just hate it: This is the full and final reason. And, I guess, this is sufficient reason to hate a language that I just hate it.

John Lennon dreamed of a world without religion. I dream of a world without perl.

Making Single-binary Release with pp

dev.to #perl

Published by Kang-min Liu on Thursday 21 October 2021 15:01

pp comes with PAR::Packer, which is a tool for "compiling" a bunch of modules and codes and makes a single binary.

perldoc pp already contains a good amount of documentation one can refer to.

While it works with system perl, I found it even easier to first prepare a directory of local::lib, then just package that entire directory.

pp tries its best to determine the list of dependencies of the given program in various ways but none of those are guaranteed to be 100% accurate. As matter of fact that guarantee is impossible to make. This is partially due to the fact that a running program can load modules in ways that cannot be easily determined by reading the program source code, or in a relative hidden code path that cannot be easily captured.

That is a good amount of flexibility, but definitely a pricey one. Although, arguably it is also an issue brought by the tool (pp, perlcc, perl2exe, etc.). I guess that is because the dynamic nature is so convenient as long as all the installation are done right. Having a tool that is able to automically complie all dependencies together was not needed that much. It has definidently needed, that is why we have those tools now, but in the last mile of their completion, lies an undecidable problem.

So we will need to manually add those missing depedencies to pp command, which is fine only when the list is small. Since we wish to just pack all the declared dependencies together, we don't care that much even if that's going to make the result a little bigger than it has to be. If we can have the same build script that works everywhere, it is as happy as in Christmas. (An pure metaphoric experssion. Pesonally I feel nothing spceial in Dec 25.)

Anyway...... it turns out to be much easier to decide the dependency at installation time, since that's all well-declared and tools like cpm, or cpanm already does this perfectly. If we install dependencies in a self-contained directory, we could just archive the entire directory together with the program we are packing, and that should be good to go.

Let's say we cd into the source code of foo and we are trying to compile the program foo as a binary. The executable is at bin/foo, while its own moulders such as Foo.pm, Foo/Bar.pm are put under the conventional directory lib.

Given that, this script should produce foo as a single binary that as if all dependencies are "statically-linked" inside:

#!/bin/bash

# Prepare local/ 
cpanm -L local -q --installdeps .
# or: cpm install

perlversion=$(perl -MConfig -e 'print $Config{version}')
pp -B \
    -I ./local/lib/perl5 \
    -a "./local/lib/perl5/;$perlversion/" \
    -a lib \
    -o foo \
    bin/foo

Alas, this is almost perfect -- except modules in corelist might still be missing. They won't be inside local/ and if they are somehow not discovered by pp then they'll be missing in the end result. We won't know this until we manually test the result foo thoroughly. Basically we should always add a bunch of -M flags in the build script instead of assuming pp would do the right thing.

For example, like so, when all of Getopt::Long, JSON::PP, and Sys::Hostname are required.

pp -B \
    -M Getopt::Long:: \
    -M JSON::PP:: \
    -M Sys::Hostname:: \
    -I local/lib/perl5 \
    -a "./local/lib/perl5/;$perlversion/" \
    -a lib \
    -o foo \
    bin/foo

A rather tedious modification as the list of dependent modules my exist in two places in the repo. Surely there is some way to refactor this.

I've verified the following script build-minicpan.sh that can download the tarball of CPAN::Mini and build a working minicpan out of it:

#!/bin/bash
set -e

curl --silent -O https://cpan.metacpan.org/authors/id/R/RJ/RJBS/CPAN-Mini-1.111016.tar.gz

tar -xzf CPAN-Mini-1.111016.tar.gz

cd CPAN-Mini-1.111016

cpanm -n -q -L local --installdeps .

perlversion=$(perl -MConfig -e 'print $Config{version}')

pp -B \
   -M Getopt::Long:: \
   -I ./local/lib/perl5 \
   -a "./local/lib/perl5/;$perlversion/" \
   -a lib \
   -o ../minicpan \
   bin/minicpan

echo "DONE: minicpan"

To me this seems to be an area worth exploring... I've been experimenting the automation of this in a side-project: pau, which is a collection of shell functions that can install app to their own self-contained directory and expose just the program it self. Very similar to what pipx does. pp support was added not long ago but still there is no good way to figure out all the missing modules and automatically add them as -M arguments.

Maybe as a lazy solution, we should just always produce a heavy-pack that includes the whole core lib directory (usually $INC[-1]) regardless whether any of them are used.

Maybe.

Originally posted at: gugod's blog -- Making single binary release with pp

My Favorite Modules: diagnostics

blogs.perl.org

Published by Tom Wyant on Thursday 21 October 2021 03:46

One of the things the Perl 5 Porters work hard on is issuing diagnostics that are actually diagnostic. I think they do a pretty good job at this, but sometimes I need a bit more explanation than the typical one-line message.

Now, there is documentation on all of these in perldiag, but paging through that looking for my message is a pain.

Fortunately, there is a module for that: diagnostics. This module causes diagnostics to be expanded into their full explanation as it appears in perldiag.

Typically you would not put a use diagnostics; in your Perl code, though of course you could. Instead, you would load it via a command-line option to perl, or maybe via environment variable PERL5OPT. That is, either

$ perl -Mdiagnostics my-flaky-perl.PL

or

$ env PERL5OPT=-Mdiagnostics perl my-flaky-perl.PL

The environment-variable example is a bit contrived, and U**x specific. It is more useful if you do not run Perl directly, and so can not change the command (if any) used to invoke Perl. In this case you would define the environment variable however it is done in your OS, before starting Perl. If your environment already defines this you will need to add '-Mdiagnostics' to the existing value, space delimited, using the quoting rules of your command shell. Note that this only affects Perls run in the same process that defined PERL5OPT, or in a subprocess of that process.

If for some reason you are unable to inject this module into your Perl, but you can capture your messages from stderr, the splain script will expand them after the fact. See the diagnostics POD for details.

A couple notes on this module:

  • This module was introduced in Perl 5.002.
  • The documentation describes this module as a pragma, which to me means lexical scope. But playing with it seems to say its scope is global.
  • Only the first instance of each diagnostic is expanded.
  • To tie this back to the warnings series, I wrote some Perl to report on what diagnostics are enabled by each warning category. This may involve too much ad-hocery to actually release to CPAN, but the curious can find the code on GitHub.

Previous entries in this series:

Perl Weekly Challenge 135: Middle 3-Digits and Validate SEDOL

blogs.perl.org

Published by laurent_r on Wednesday 20 October 2021 22:40

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

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on October 24, 2021 at 24:00). 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: Middle 3-digits

You are given an integer.

Write a script find out the middle 3-digits of the given integer, if possible otherwise throw sensible error.

Example 1:

Input: $n = 1234567
Output: 345

Example 2:

Input: $n = -123
Output: 123

Example 3:

Input: $n = 1
Output: too short

Example 4:

Input: $n = 10
Output: even number of digits

Middle 3-Digits in Raku

This is pretty simple. We write a mid-three subroutine that returns an error message if the input number has an even number of digits or if it is too small (less than 3 digits). Once this is done, the subroutine finds the mid-point of the sting and returns the substring starting one digit earlier and ending one digit later.

sub mid-three (Int $in is copy) {
    $in = abs($in);
    my $length = $in.chars;
    return "Even number of digits" if $length %% 2;
    return "Too short" if $length < 3;
    my $mid-point = ($length - 1) /2;
    return substr($in, $mid-point - 1, 3);
}
for <1234567 -123 1 10 -54321> -> $n {
    say "$n -> ", mid-three $n;
}

This program displays the following output:

$ raku ./mid-three.raku
1234567 -> 345
-123 -> 123
1 -> Too short
10 -> Even number of digits
-54321 -> 432

Middle 3-Digits in Perl

Again, we have a mid_three subroutine that returns an error message if the input number has an even number of digits or if it is too small (less than 3 digits). Once this is done, the subroutine finds the mid-point of the sting and returns the substring starting one digit earlier and ending one digit later.

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

sub mid_three {
    my $in = abs $_[0];
    my $length = length $in;
    return "Even number of digits" unless $length % 2;
    return "Too short" if $length < 3;
    my $mid_point = ($length - 1) /2;
    return substr($in, $mid_point - 1, 3);
}
for my $n (qw<1234567 -123 1 10 -54321>) {
    say "$n -> ", mid_three $n;
}

This program displays the following output:

$ perl mid-three.pl
1234567 -> 345
-123 -> 123
1 -> Too short
10 -> Even number of digits
-54321 -> 432

Task 2: Validate SEDOL

You are given 7-characters alphanumeric SEDOL.

Write a script to validate the given SEDOL. Print 1 if it is a valid SEDOL otherwise 0.

For more information about SEDOL, please checkout the Wikipedia page.

Example 1:

Input: $SEDOL = '2936921'
Output: 1

Example 2:

Input: $SEDOL = '1234567'
Output: 0

Example 3:

Input: $SEDOL = 'B0YBKL9'
Output: 1

Validate SEDOL in Raku

The sedol subroutine returns 0 if the input string contains a vowel or if it not made of 6 alphanumerical characters followed by 1 digit. After these checks, it splits the input string into a sequence of 6 characters and 1 digit (presumably the check digit). It then populates a %values hash with the numeric values for the 10 digits and 26 letters. It then computes the weighted sum of the input sequence of 6 characters and then computes the checksum. If the checksum thus calculated is equal to the checksum found in the input string (the last digit), then we have a valid Sedol and the subroutine can return 1. Otherwise the subroutine return 0.

sub sedol( Str $in ) {
    return 0 if $in  ~~ /<[AEIOU]>/;  # Vowels not allowed
    return 0 unless $in ~~ /^ <[0..9B..Z]>**6 <[0..9]> $/; # 6 alphanumericals + 1 digit
    my ($sedol, $check) = substr($in, 0, 6), substr($in, 6, 1);
    my %values; 
    my $count = 0;
    for ( 0..9, 'A'..'Z').flat -> $val {
        %values{$val} = $count++;
    }
    my @weights = 1, 3, 1, 7, 3, 9;
    my $sum = [+] @weights Z* map {%values{$_}}, $sedol.comb;
    my $check_digit = (10 - $sum % 10) % 10;
    return 1 if $check_digit == $check;
    0
}
for <456765 65AR345 2936921 1234567 B0YBKL9> -> $s {
    say "$s: ", sedol($s);
}

This program displays the following output:

$ raku ./sedol.raku
456765: 0
65AR345: 0
2936921: 1
1234567: 0
B0YBKL9: 1

Validate SEDOL in Perl

This is essentially the same algorithm as in the Raku solution above: the sedol subroutine returns 0 if the input string contains a vowel or if it not made of 6 alphanumerical characters followed by 1 digit. After these checks, it splits the input string into a sequence of 6 characters and 1 digit (presumably the check digit). It then populates a %values hash with the numeric values for the 10 digits and 26 letters. It then computes the weighted sum of the input sequence of 6 characters and then computes the checksum. If the checksum thus calculated is equal to the checksum found in the input string (the last digit), then we have a valid Sedol and the subroutine can return 1. Otherwise the subroutine return 0.

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

sub sedol {
    my $in = shift;
    return 0 if $in  =~ /[AEIOU]/i;  # Vowels not allowed
    return 0 unless $in =~ /^[A-Z0-9]{6}[0-9]$/; # 6 alphanumericals + 1 digit
    my ($sedol, $check) = (substr($in, 0, 6), substr($in, 6, 1));
    my %values; 
    my $count = 0;
    for my $val ( 0..9, 'A'..'Z') {
        $values{$val} = $count++;
    }
    my @weights = (1, 3, 1, 7, 3, 9);
    my $sum = 0;
    my @chars = split //, $sedol;
    for my $i (0..5) {
        $sum += $values{$chars[$i]} * $weights[$i];
    }
    my $check_digit = (10 - $sum % 10) % 10;
    return 1 if $check_digit == $check;
    0
}
for my $s (qw<456765 65AR345 2936921 1234567 B0YBKL9>) {
    say "$s: ", sedol($s);
}

This program displays the following output:

$ perl  ./sedol.pl
456765: 0
65AR345: 0
2936921: 1
1234567: 0
B0YBKL9: 1

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

The reports of Perl’s death have been greatly exaggerated

dev.to #perl

Published by Mark Gardner on Tuesday 19 October 2021 14:00

Look, I get it. You don’t like the Perl programming language or have otherwise disregarded it as “dead.” (Or perhaps you haven’t, in which case please check out my other blog posts!) It has weird noisy syntax, mixing regular expressions, sigils on variable names, various braces and brackets for data structures, and a menagerie of cryptic special variables. It’s old: 34 years in December, with a history of (sometimes amateur) developers that have used and abused that syntax to ship code of questionable quality. Maybe you grudgingly accept its utility but think it should die gracefully, maintained only to run legacy applications.

But you know what? Perl’s still going. It’s had a steady cadence of yearly releases for the past decade, introducing new features and fencing in bad behavior while maintaining an admirable level of backward compatibility. Yes, there was a too-long adventure developing what started as Perl 6, but that language now has its own identity as Raku and even has facilities for mixing Perl with its native code or vice versa.

And then there’s CPAN, the Comprehensive Perl Archive Network: a continually-updated collection of over 200,000 open-source modules written by over 14,000 authors, the best of which are well-tested and ‑documented (applying peer pressure to those that fall short), presented through a search engine and front-end built by scores of contributors. Through CPAN you can find distributions for things like:

All of this is available through a mature installation toolchain that doesn’t break from month to month.

Finally and most importantly, there’s the global Perl community. The COVID-19 pandemic has put a damper on the hundreds of global Perl Mongers groups’ meetups, but that hasn’t stopped the yearly Perl and Raku Conference from meeting virtually. (In the past there have also been yearly European and Asian conferences, occasional forays into South America and Russia, as well as hackathons and workshops worldwide.) There are IRC servers and channels for chat, mailing lists galore, blogs (yes, apart from this one), and a quirky social network that predates Facebook and Twitter.

So no, Perl isn’t dead or even dying, but if you don’t like it and favor something newer, that’s OK! Technologies can coexist on their own merits and advocates of one don’t have to beat down their contemporaries to be successful. Perl happens to be battle-tested (to borrow a term from my friend Curtis “Ovid” Poe), it runs large parts of the Web (speaking from direct and ongoing experience in the hosting business here), and it’s still evolving to meet the needs of its users.

Cover image by Alan Levine, licensed CC BY 2.0

I try match syntax using Syntax::Keyword::Match

blogs.perl.org

Published by Yuki Kimoto on Tuesday 19 October 2021 06:59


Syntax::Keyword::Match is a module to enable match syntax in the current Perl by Paul Evans who is one of the current Perl Steering Councils. See perlgov about the Perl Steering Council.

Syntax::Keyword::Match Examples

Syntax::Keyword::Match Examples

Number matching

Number matching. Match syntax is similar as a switch syntax of C language.

use v5.14;
use warnings;

use Syntax::Keyword::Match;

my $n = 4;

match($n : ==) {
case(1) { say "It's one" }
case(2) { say "It's two" }
case(3) { say "It's three" }
case(4),
case(5) {
say "It's four or five"
}
default { say "It's something else" }
}

Output:

It's four or five

Compared to current Perl, it is shorter and can be written without duplication.

use v5.14;
use warnings;

my $n = 4;

if ($n == 1) {
say "It's one";
}
elsif ($n == 2) {
say "It's two";
}
elsif ($n == 3) {
say "It's three";
}
elsif ($n == 4 || $n == 5) {
say "It's four or five";
}
else {
say "It's something else";
}

For integers, performance optimization may also be possible using a jump table or a binary tree.

String matching

String matching. Match syntax has also string matching.

use v5.14;
use warnings;

use Syntax::Keyword::Match;

my $n = 'a4';

match($n : eq) {
case('a1') { say "It's one" }
case('a2') { say "It's two" }
case('a3') { say "It's three" }
case('a4'),
case('a5') {
say "It's four or five"
}
default { say "It's something else" }
}

Output:

It's four or five

Regex matching

Regex matching. Match syntax has also regex matching.

use v5.14;
use warnings;

use Syntax::Keyword::Match;

my $n = 'a4bbbb';

match($n : =~) {
case(/a1/) { say "It's one" }
case(/a2/) { say "It's two" }
case(/a3/) { say "It's three" }
case(/a4/),
case(/a5/) {
say "It's four or five"
}
default { say "It's something else" }
}

Output:

It's four or five

What I feel using Syntax::Keyword::Match

Personally, I feel number, string, regex matching is enough completed at production level(although Paul said it isn't enough yet).

I'm looking forward to match syntax.

#534 - Are you CPAN contributor?

Perl Weekly

Published on Monday 18 October 2021 10:00

Hi there

How much have you contributed during the Hacktoberfest event yet?

CPAN needs a helping hand, not just during Hacktoberfest. I am raising the subject as Dave Cross recently blogged about his experience with one of the distributions hosted on CPAN in this blog post. It also reminds me of my early days when I created Perl a library around some of Google's public APIs. Two of them, WWW::Google::CustomSearch and WWW::Google::Places were used by many people, as I have had many queries related to them in the past. It is very common for an API provider to discontinue the service or move in a new direction any time without notice. It becomes an even bigger issue if the author of the CPAN distribution disappears from the scene. So the question is, how best to deal with such cases? Thanks to the PAUSE admins, there is a documented process to adopt a distribution and take it forward. You should get in touch with one of the PAUSE admins if you want to adopt a distribution and contribute.

For many years, MetaCPAN has been my playground. I used to spend 2-4 hours every day looking for low-hanging issues in the recently uploaded distributions. I even wrote a two-part blog post talking about how to become a CPAN contributor. Part 1 and Part 2. I also gave a talk at The Perl Conference in Glasgow 2018 on the same topic. You can watch the talk on YouTube, if you fancy.

I remember at one point, I was keen to contribute to MetaCPAN and be part of the Toolchain Gang. I couldn't get the local dev setup of MetaCPAN and was looking for help. I was told that someone from the gang is working on dockerisation of MetaCPAN to make it easier for anyone to contribute. I missed the opportunity to meet the gang when it was held in Marlow, not far from where I live (London) in 2019. I don't know if anyone is still working on that front.

I hardly contribute to CPAN these days but I still like to call myself CPAN contributor. However I do release a patch every now and then to some of my personal and adopted distributions. Being a member of the Pull Request Club, I do contribute to at least one distribution every month. I have never missed a month since I joined the club in Jan 2019.

If anyone is keen to become a CPAN contributor then please get in touch with me. We need fresh energy to make CPAN the central place to look for the best solutions.

Enjoy the rest of the newsletter.

A Couple of Brute Force Computations

RabbitFarm Perl

Published on Sunday 17 October 2021 13:03

The examples used here are from The Weekly Challenge problem statement and demonstrate the working solution.

Part 1

Write a script to generate first 5 Pandigital Numbers in base 10.

Solution


use strict;
use warnings;
##
# Write a script to generate first 5 Pandigital Numbers in base 10.
##
use boolean;

sub first_n_pandigitals {
    my ($n)         = @_;
    my $found       = false;
    my $pandigitals = [];
    my $x           = 1_000_000_000;
    do {
        my $test = $x;
        push @{$pandigitals}, $x
          if ( $test =~ tr/0//d ) > 0
          && ( $test =~ tr/1//d ) > 0
          && ( $test =~ tr/2//d ) > 0
          && ( $test =~ tr/3//d ) > 0
          && ( $test =~ tr/4//d ) > 0
          && ( $test =~ tr/5//d ) > 0
          && ( $test =~ tr/6//d ) > 0
          && ( $test =~ tr/7//d ) > 0
          && ( $test =~ tr/8//d ) > 0
          && ( $test =~ tr/9//d ) > 0;
        $found = ( @{$pandigitals} == $n );
        $x++;
    } while ( !$found );
    return $pandigitals;
}

sub first_5_pandigitals {
    return first_n_pandigitals(5);
}
MAIN: {
    my $pandigitals = first_5_pandigitals;
    for my $x ( @{$pandigitals} ) {
        print "$x\n";
    }
}

Sample Run


$ perl perl/ch-1.pl
1023456789
1023456798
1023456879
1023456897
1023456978

Notes

From the definition we know that we will need at least 10 digits and, intuitively, the first five pandigital numbers will start with 1. So then, we start with 1_000_000_000 and iterate upwards testing each candidate until we find the first five. The test used here is to determine if tr finds all the required digits.

Part 2

You are given 2 positive numbers, $m and $n. Write a script to generate multiplication table and display count of distinct terms.

Solution


use strict;
use warnings;
##
# You are given 2 positive numbers, $m and $n.
# Write a script to generate multiplcation table and display count of distinct terms.
##
sub compute_print {
    my ( $m, $n ) = @_;
    my $distinct = {};
    print " x | " . join( " ", ( 1 .. $n ) ) . "\n";
    print "---+-" . "-" x ( $n * 2 - 1 ) . "\n";
    for my $i ( 1 .. $m ) {
        print " $i | " . join( " ", map { $i * $_ } ( 1 .. $n ) ) . "\n";
        for my $j ( 1 .. $n ) {
            $distinct->{ $i * $j } = undef;
        }
    }
    return $distinct;
}
MAIN: {
    my $distinct = compute_print( 3, 3 );
    print "Distinct Terms: "
      . join( ", ", sort { $a <=> $b } keys %{$distinct} ) . "\n";
    print "Count: " . keys( %{$distinct} ) . "\n";
    print "\n\n";
    $distinct = compute_print( 3, 5 );
    print "Distinct Terms: "
      . join( ", ", sort { $a <=> $b } keys %{$distinct} ) . "\n";
    print "Count: " . keys( %{$distinct} ) . "\n";
}

Sample Run


$ perl perl/ch-2.pl
 x | 1 2 3
---+------
 1 | 1 2 3
 2 | 2 4 6
 3 | 3 6 9
Distinct Terms: 1, 2, 3, 4, 6, 9
Count: 6


 x | 1 2 3 4 5
---+----------
 1 | 1 2 3 4 5
 2 | 2 4 6 8 10
 3 | 3 6 9 12 15
Distinct Terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15
Count: 11

Notes

This is a perfectly Perl shaped problem. The computations can be handled in a straightforward way, especially with map. Getting rid of duplicates is done using the idiomatic method with hash keys. Finally, formatting the output cleanly is done without much undo stress. Compare what we do here to format the table with what was necessary to represent the same table in Prolog.

References

Challenge 134

Pandigital Numbers

Release 1.57 of perl-workflow, a bug fix release

dev.to #perl

Published by jonasbn on Sunday 17 October 2021 14:11

Due to extreme workload at my job, we have not made as much progress as we would like.

My tireless collaborator Erik Huelsmann have fixed a few bugs and they have made into release 1.57 released today.

We hope to pick up on the forthcoming 2.0 release as soon as things settle at a somewhat normal level again.

Here follows the change log of release 1.57.

Change Log

The original is available on GitHub

1.57 2021-10-17 Bug fix release, update recommended

  • PR #170 by @ehuelsmann addresses an issue where Workflow tries to log during the execution of use statements, at which time it's highly unlikely that the logger has already been initialized, resulting in warnings being printed on the console

  • PR #171 by @ehuelsmann adds initialization of context parameters passed at instantiation; currently, parameters need to be added explicitly and individually after instantiation

  • PR #173 by @ehuelsmann addresses issue #172, fixing failure to automatically run actions from the INITIAL state

(ccclxiii) 10 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 17 October 2021 09:56

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

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.050001 on 2021-10-12
    • Votes: 13
    • Previous version: 2.049009 was 6 days before
  2. CHI - Unified cache handling interface
    • Version: 0.61 on 2021-10-13
    • Votes: 51
    • Previous version: 0.60 was 6 years, 4 months, 6 days before
  3. Cpanel::JSON::XS - cPanel fork of JSON::XS, fast and correct serializing
    • Version: 4.27 on 2021-10-14
    • Votes: 39
    • Previous version: 4.26 was 6 months, 2 days before
  4. DateTime::TimeZone - Time zone object base class and factory
    • Version: 2.50 on 2021-10-15
    • Votes: 17
    • Previous version: 2.49 was 13 days before
  5. Encode - character encodings in Perl
    • Version: 3.16 on 2021-10-13
    • Votes: 54
    • Previous version: 3.15 was 5 days before
  6. Graph - graph data structures and algorithms
    • Version: 0.9725 on 2021-10-10
    • Votes: 26
    • Previous version: 0.9724 was 27 days before
  7. local::lib - create and use a local lib/ for perl modules with PERL5LIB
    • Version: 2.000027 on 2021-10-14
    • Votes: 84
    • Previous version: 2.000024 was 4 years, 6 days before
  8. Object::Pad - a simple syntax for lexical slot-based objects
    • Version: 0.55 on 2021-10-11
    • Votes: 20
    • Previous version: 0.54 was 4 days before
  9. PerlPowerTools - BSD utilities written in pure Perl
    • Version: 1.027 on 2021-10-11
    • Votes: 28
    • Previous version: 1.025 was 3 months, 25 days before
  10. Syntax::Keyword::Try - a try/catch/finally syntax for perl
    • Version: 0.26 on 2021-10-12
    • Votes: 35
    • Previous version: 0.25 was 4 months, 11 days before

(cdlxxxvii) metacpan weekly report

Niceperl

Published by Unknown on Sunday 17 October 2021 09:52

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

This week there isn't any remarkable distribution

Build date: 2021/10/17 07:52:38 GMT


Clicked for first time:


Increasing its reputation:

Perl Weekly Challenge 134: Pandigital Numbers and Distinct Term Count

blogs.perl.org

Published by laurent_r on Friday 15 October 2021 23:56

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

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

Task 1: Pandigital Numbers

  • Write a script to generate first 5 Pandigital Numbers in base 10.*

As per the https://en.wikipedia.org/wiki/Pandigital_number, it says:

A pandigital number is an integer that in a given base has among 
its significant digits each digit used in the base at least once.

In base 10, a pandigital number ought to have 10 digits. The first (smallest) pandigital numbers will start with the smallest digits upfront, except that the zero cannot be the first first digit, as it would disappear as non significant. So, to get the first pandigital number we need to start with 1, continue with 0 and then proceed the other digits in increasing order, which leads to 1023456789. The next pandigital number will have its two last digits swapped: 1023456798.

Since we need to find the first five pandigital numbers, they will all start with the sequence 1023456, with the three last digits being the permutations of 7, 8, and 9 in the proper increasing order. There are 6 permutations of three distinct digits, so that will be enough to find the first 5 pandigital numbers.

Pandigital Numbers in Raku

Based on the explanations above, we can hard-code the first seven digits as "1023456" and compute the permutations of the last 3 digits:

use v6;

my $start = "1023456";
my @ends = <7 8 9>.permutations[0..4]>>.join("");
say $start ~ $_ for @ends;

This script displays the following output:

raku ./pandigital.raku
1023456789
1023456798
1023456879
1023456897
1023456978

This script is so simple that we can easily turn it to a Raku one-liner:

$ raku -e 'say "1023456" ~ $_ for (7..9).permutations[0..4]>>.join'
1023456789
1023456798
1023456879
1023456897
1023456978

Pandigital Numbers in Perl

Based on the explanations in the task description section above, we can hard code the first seven digits as "1023456" and compute the permutations of the last 3 digits. For this, since we don’t like using external packages for coding challenges, we implement our own recursive permute subroutine.

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

my @permutations;

sub permute {
    my ($str, @vals) = @_;
    if (scalar @vals == 0) {
        push @permutations, $str;
        return;
    }
    permute("$str" . $vals[$_], @vals[0..$_-1], @vals[$_+1..$#vals]) for 0..$#vals;
}
permute "", 7, 8, 9;
say "1023456" . $_ for @permutations[0..4];

This script displays the following output:

$ perl ./pandigital.pl
1023456789
1023456798
1023456879
1023456897
1023456978

Task 2: Distinct Terms Count

You are given 2 positive numbers, $m and $n.

Write a script to generate multiplication table and display count of distinct terms.

Example 1:

Input: $m = 3, $n = 3
Output:

   x | 1 2 3
   --+------
   1 | 1 2 3
   2 | 2 4 6
   3 | 3 6 9

Distinct Terms: 1, 2, 3, 4, 6, 9
Count: 6

Example 2:

Input: $m = 3, $n = 5
Output:

   x | 1  2  3  4  5
   --+--------------
   1 | 1  2  3  4  5
   2 | 2  4  6  8 10
   3 | 3  6  9 12 15

Distinct Terms: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15
Count: 11

Distinct Terms Count in Raku

There is nothing complex about this task. We need to loop over all values between 1 and $m and all values between 1 and $n, perform the multiplications and properly format the output. In addition, we use a SetHash to store the distinct computed terms, display them and count them.

use v6;

sub multiplication-table (Int $m, Int $n) {
    my SetHash $distinct;
    say "x |", join " ", map {.fmt("%3d")}, 1..$n;
    for 1..$m -> $i {
        my @res = map { $i * $_ }, 1..$n;
        $distinct{$_} = True for @res;
        say "$i |", join " ", map {.fmt("%3d")}, @res;
    }
    say "Distinct terms: ", $distinct.keys.sort.join(" ");
    say "Count: ", $distinct.keys.elems;
}
multiplication-table(7, 5);

This program displays the following output:

$ raku ./distinct-terms.raku
x |  1   2   3   4   5
1 |  1   2   3   4   5
2 |  2   4   6   8  10
3 |  3   6   9  12  15
4 |  4   8  12  16  20
5 |  5  10  15  20  25
6 |  6  12  18  24  30
7 |  7  14  21  28  35
Distinct terms: 1 2 3 4 5 6 7 8 9 10 12 14 15 16 18 20 21 24 25 28 30 35
Count: 22

Distinct Terms Count in Perl

This is a port to Perl of the Raku program above. In Perl, we use a hash to store the distinct terms.

#!/usr/bin/perl
use strict;
use warnings;
use feature qw/say/;

sub multiplication_table {
    my ($m, $n) = @_;
    my %distinct;
    say "x |", join " ", map {sprintf "%3d", $_} 1..$n;
    for my $i (1..$m) {
        my @res = map $i * $_, 1..$n;
        $distinct{$_} = 1 for @res;
        say "$i |", join " ", map {sprintf "%3d", $_} @res;
    }
    say "Distinct terms: ", join " ", sort keys %distinct;
    say "Count: ", scalar keys %distinct;
}
multiplication_table(7, 5);

Output:

$ perl ./distinct-terms.pl
x |  1   2   3   4   5
1 |  1   2   3   4   5
2 |  2   4   6   8  10
3 |  3   6   9  12  15
4 |  4   8  12  16  20
5 |  5  10  15  20  25
6 |  6  12  18  24  30
7 |  7  14  21  28  35
Distinct terms: 1 10 12 14 15 16 18 2 20 21 24 25 28 3 30 35 4 5 6 7 8 9
Count: 22

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

#533 - Consulting work

Perl Weekly

Published on Monday 11 October 2021 10:00

Hi,

I just had a meeting with a company in the UK that were looking for some consulting in Perl. After our conversation I felt that what they are interested in is not really where my expertise is, so I referred them to two other people who have a lot more experience in those areas. However I realized I don't know who is providing consulting or development service these days. So let me know. Who knows next time I might be able to refer the clients to you.

On the other hand I just found out that my client, where I do some refactoring on a web-application with some machine-learning backend (written in Python). is likely to move the project to their parent company. This probably means I'll be free for other projects to introduce test automation, CI, and refactoring code.

Enjoy your week!

Raku CI Bot Grant Report for September 2021

Perl Foundation News

Published by Moritz Lenz on Monday 11 October 2021 03:36

Regarding his Raku CI bot grant, Patrick Böker writes:


In September I:

  • got the OBS interfacing component working, and
  • got the GitHub interfacing component working.

I hoped to manage to put a working system together this weekend. (Currently only integrating GitHub and OBS, so no separate Website and no interactive features yet.) That didn't quite work out, but there is not much missing. So I'm hopeful to do so in the coming days.

(ccclxii) 7 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 10 October 2021 00:41

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

  1. App::Netdisco - An open source web-based network management tool.
    • Version: 2.049009 on 2021-10-06
    • Votes: 13
    • Previous version: 2.049005 was 27 days before
  2. DateTime::TimeZone - Time zone object base class and factory
    • Version: 2.49 on 2021-10-02
    • Votes: 17
    • Previous version: 2.49 was before
  3. Encode - character encodings in Perl
    • Version: 3.15 on 2021-10-08
    • Votes: 54
    • Previous version: 3.12 was 1 month, 30 days before
  4. JSON::Validator - Validate data against a JSON schema
    • Version: 5.02 on 2021-10-06
    • Votes: 29
    • Previous version: 5.00 was 4 days before
  5. Mojo::mysql - Mojolicious and Async MySQL/MariaDB
    • Version: 1.24 on 2021-10-05
    • Votes: 35
    • Previous version: 1.23 was 24 days before
  6. Object::Pad - a simple syntax for lexical slot-based objects
    • Version: 0.54 on 2021-10-07
    • Votes: 20
    • Previous version: 0.53 was 9 days before
  7. Sub::Util - Common Scalar and List utility subroutines
    • Version: 1.60 on 2021-10-08
    • Votes: 157
    • Previous version: 1.59 was 26 days before

Jonathan completed the work on his grant. The changes were merged into Raku and will be productive in the next Raku release. We thank the sponsors for supporting this grant, Jonathan for his work; and also the other volunteers who helped with various tasks so this big change could be merged.


Raku Dispatch and Compiler Improvements Grant Update

During September, I completed the remaining hours on my current grant. The key aim of the grant - to bring my work on a new generalized dispatch mechanism to the point where it could be merged and delivered to Raku users - has been achieved, the merge taking place on 29th September. I wrote a blog post that provides some data on the improvements, as well as identifying future work that can build upon what has been achieved thus far.

During September, working under the grant, I:

  • Implemented specialization and inlining of dispatches that store resume initialization state, to allow the dispatches to be resumed (for example, if callsame is used). This was a critical part of getting back the level of inlining for method calls and multi dispatches that existed prior to this work, which is a critical factor in Raku performance.
  • Implemented caller-side removal of Scalar containers, which in turn avoids various duplicate guards, leading to much tighter code being produced after specialization and JIT compilation in many common situations.
  • Fixed Junction multi-dispatch failover for the case where the Junction was in a named argument, along the way tweaking the semantics to be more consistent with those of positional arguments (there were some unintended discrepancies in the previous implementation).
  • Changed dispatch program compilation to not emit type guards when the types were already proven during optimization, rather than adding them and relying on them to be optimized out later.
  • Reinstated all known missing optimizations from prior to the new dispatch work, and added JIT support for various new operations introduced during the work.
  • Did various modifications to improve startup time, which has regressed. The new dispatch model has many advantages, however does carry a higher warmup cost.
  • Fixed the profiler to work again in programs that use continuations, after changes to the continuation representation as part of callstack changes.
  • Did numerous smaller fixes for bugs identified by blin (which runs the tests of all modules in the ecosystem). In some cases where the modules relied on internals or unspecified behavior, I sent a PR to the module instead.

The time worked during September was 55 hours and 18 minutes, which was the remaining grant time available.

Immediate writing to file - flushing in Perl without buffering

Perl Maven

Published by Gabor Szabo on Monday 04 October 2021 12:11

When we say we read from a file or write to a file in Perl (or any other language for that matter), we don't actually access the file directly and immediately. Instead of that we what we really do is that we ask the operating system to read from the file or write to the file using a "system call". The Operating system (Linux, OSX, Windows, etc.) will do the work on our behalf, but it will try to optimize.

So it won't go and write to the disk immediately when we ask it to write a few characters. Instead of that it will keep the request in memory in a "buffer" and will write it to the disk later, when the buffer is full or when the file is closed.

#532 - Hacktoberfest 2021

Perl Weekly

Published on Monday 04 October 2021 10:00

Hi there

Have you joined the annual Hacktoberfest 2021 run by Digital Ocean?

If not then please join without any further delay. Hacktoberfest encourages participation in the open source community. You can earn a limited edition T-shirt by completing the challenge.

Not sure if you noticed, but this time they have made an interesting change by allowing open source maintainers to also take part in the contest. Ever since I started The Weekly Challenge, I have hardly found time to dedicate to Hacktoberfest. Last year I could only submit 6 PRs, enough to win the contest, since you only need to submit 4 PRs. This year, I am only taking part as the maintainer of an open source project - "The Weekly Challenge". The best year for me as contributor was 2019 when I submitted 160 PRs.

If you are looking for an open source project to contribute to then you can join "The Weekly Challenge" and win the competition by submitting 4 PRs in just one week.

How?

Well, you could submit 2 Perl and 2 Raku solutions to the weekly task. Just submit one solution per PR. I know it is cheating but a fair one in my humble opinion. Again, please don't limit yourself to just Perl and Raku. You are free to choose your favourite programming language. One more bit, please don't tie yourself to the current weekly challenge. You are free pick any past week challenges. Plenty of choices available. If you have any questions with regard to submitting a PR then please follow the blog post that explains every detail. If you still have any questions then please get in touch with me. You can find my details on the page. I am also accepting PRs to another open source project - The Weekly Challenge website which is also open source code.

If you are a CPAN contributor then you could pick and choose your favourite distribution and contribute. However there is a catch, the distribution may or may not be part of the contest. Having said that, you can contribute to my CPAN distributions if you fancy. I promise, I will make the distribution to be part of the contest so that your PR will count towards the target. Just yesterday, I received a Pull Request on one of my CPAN distributions, BankAccount::Validator::UK.

Happy Hacking !!!

Maintaining Perl 5 Core (Tony Cook): September 2021

Perl Foundation News

Published by Jason A. Crome on Sunday 03 October 2021 21:02

``` Approximately 40 tickets were reviewed, and 7 patches were applied

[Hours] [Activity] 7.45 #18606 produce another case where the implementation fails, comment, try to work on a fix #18606 research, code on making a new stub cv #18606 more try to make stub cv #18606 get it seemingly working, needs more tests 0.31 #18746 reply to comment #18746 review and apply to blead 4.26 #18820 reply to comment #18820 review new changes, look over related code #18820 try benchmarking #18820 more try benchmarking, can’t come to any conclusion either way 0.55 #18827 review and review discussion, research and comment 2.77 #18837 look into some alternative approaches, implement one and replace the PR #18837 fix some of my stupidity detected by CI 0.98 #18925 review and comments 0.05 #18936 review discussion and apply to blead 1.77 #18953 review response and work on a fix 0.12 #18968 re-check and apply to blead 0.65 #18972 review and close 2.04 #19005 rebase, testing and update PR #19005 rebase 0.97 #19014 review and comment 0.17 #19015 re-check and apply to blead 0.40 #19018 review, research and apply to blead 1.12 #19019 review, testing 1.15 #19020 research and comment 0.17 #19021 review 0.10 #19023 review 4.28 #19040 review and comment #19040 review, try and find any flaws, comment #19040 review the “now ready for review” PR #19040 comment #19040 review new changes 0.82 #19041 review and apply to blead 4.32 #19054 research, debugging #19054 debugging, research #19054 more testing, review EU::PXS code 0.35 #19059 comment 0.48 #19074 review 0.12 #19078 review and apply to blead 3.75 :utf8 - documentation :utf8 - documentation 0.33 :utf8 more testing, push for CI 1.00 :utf8 rebase, testing 0.22 check github notifications 0.22 find the correct code to fix for khw, and reproduce, sending preprocessed code as requested 1.30 list catch up list catch up 0.50 list catch up, comment on bool thread 0.22 more perldelta 0.65 perldelta 2.05 PR 19091 for one Coverity issue, other two appear to be false positives and marked so 2.67 reduce gcc warning noise, including setting up a newer gcc to check against 0.23 review a number of PRs, which generally have unresponded to comments 0.65 review Coverity reported defects 0.62 review github notifications 0.72 RFCs PR 3 review and comment 0.62 try to build khw’s test code with MSVC, update MSVC (with

a reboot) and try again

51.15 hours total ```

List of new CPAN distributions – Sep 2021

Perlancar

Published by perlancar on Sunday 03 October 2021 01:38

dist author first_version latest_version abstract
Acme-CPANModules-PAUSE PERLANCAR 0.001 0.001 Modules that interact with PAUSE, the Perl Authors Upload Server
Acme-PodOnly HAARG 0.001001 0.001003 A distribution that only contains Pod
Alien-PGPLOT DJERIUS 0.01 0.01 Build and Install the PGPLOT library
Alien-PortMidi JBARRETT 0.01 0.03 Install the Mixxx fork of PortMidi
App-Bitcoin-PaperWallet BRTASTIC 1.00 1.01 Generate printable cold storage of bitcoins
App-GhostWork INA 0.01 0.05 Barcode Logger(When,Where,Who,What,toWhich,Why)
App-ShellCompleter-YtDlp PERLANCAR 0.001 0.001 Shell completion for yt-dlp
App-TimeZoneUtils PERLANCAR 0.001 0.001 An assortment of time-zone-related CLI utilities
App-dumpbin SANKO 0.01 0.02 It's a PE Parser!
App-nioscli SSMN 0.001 0.001 CLI for NIOS
ArrayData-Lingua-Word-ID-KBBI PERLANCAR 0.003 0.003 Indonesian words from Kamus Besar Bahasa Indonesia
CLI-Meta-YtDlp PERLANCAR 0.001 0.001 Metadata for yt-dlp CLI
Chess-Plisco GUIDO 0.1 0.3 Representation of a chess position with move generator, legality checker etc.
Data-Text NHORNE 0.01 0.05 Class to handle text in an OO way
Dist-Zilla-MintingProfile-AlienBuild PLICEASE 0.01 0.03 A minimal Dist::Zilla minting profile for Aliens
Dist-Zilla-Plugin-TableData PERLANCAR 0.001 0.001 Plugin to use when building TableData::* distribution
Evo-QUIP KOBOLDWIZ v0.1.1 v0.1.1 Perl extension for QUIP (Quadratic Unconstrained Integer Program)
Game-FaceGenerator SCHROEDER 1 1.02 a web app to combina random images into faces
Game-HexDescribe SCHROEDER 1 1 a web app to add random table driven data to map data
Game-TextMapper SCHROEDER 1 1.03 a web app to generate maps based on text files
Games-TabNoun PERLANCAR 0.001 0.004 Select nouns from list of words, as fast as possible
Geonode-Free-ProxyList JULIODCS v0.0.1 v0.0.5 Get Free Geonode Proxies by using some filters
IO-Term-Status PEVANS 0.01 0.01 print log lines to a terminal with a running status bar
JSON-DJARE-Writer SARGIE 0.01 0.02 Write DJARE files
Media-Convert WOUTER v1.0.0 v1.0.0 a Moose-based library to work with media assets
Mojolicious-Plugin-TagHelpers-ContentBlock AKRON 0.11 0.11 Mojolicious Plugin for Content Blocks
Mojolicious-Plugin-Text-Minify RRWO v0.1.0 v0.2.2 remove HTML intendation on the fly
Net-ClamAV-Client BYTERAZOR 0.1 0.1 A client class for the ClamAV clamd virus scanner daemon
Netstack CARELINE 0.001 0.004 turns baubles into trinkets
Object-Util-Stringify PERLANCAR 0.001 0.001 Utility routines related to object stringification
Passwd-Keyring-Secret UHLE 1.00 1.01 Password storage implementation using the GObject-based Secret library.
Pod-Weaver-Plugin-TableData PERLANCAR 0.001 0.002 Plugin to use when building TableData::* distribution
Pod-Weaver-Role-RequireFromBuild PERLANCAR 0.001 0.001 Role to require() from Dist::Zilla build files
RT-Extension-FilterRules AJWOOD 0.01 0.01 Filter incoming tickets through rule sets
RT-Extension-TemplateTickets AJWOOD 0.01 0.01 Designate tickets as templates for new tickets
Sah-Schemas-JSON PERLANCAR 0.001 0.003 Various schemas related to JSON
Statistics-Descriptive-PDL SLAFFAN 0.02 0.12 A close to drop-in replacement for Statistics::Descriptive using PDL as the back-end
Syntax-Operator-Zip PEVANS 0.01 0.03 infix operator to compose two lists together
TableData-CPAN-Release-Static-2021 PERLANCAR 20210928.0 20210928.1 CPAN releases for the year 2021
TableDataBundle-CPAN-Release PERLANCAR 0.001 0.003 Collection of TableData:: modules that contain CPAN releases data
TableDataBundle-CPAN-Release-Static-Older PERLANCAR 20210927.0 20210927.0 Collection of TableData:: modules that contain older CPAN releases data
Task-AlienDev PLICEASE 0.01 0.02 Task bundle for Alien development
Test-Mock-LWP-Distilled SKINGTON 0.001_01 1.000 make and use LWP mocks, distilled to their essence
Test-Mock-LWP-Distilled-JSON SKINGTON 0.001_01 1.000 JSON support for Test::Mock::LWP::Distilled
Test-Module-Features PERLANCAR 0.001 0.002 Test feature set specifications and features declarations
Text-ANSI-Tabs UTASHIRO 0.06 0.07 Tab expand and unexpand with ANSI sequence
WordLists-EN-Adjective PERLANCAR 0.001 0.002 Collection of English adjectives
WordLists-EN-Noun PERLANCAR 0.001 0.003 Collection of English nouns
autocroak LEONT 0.001 0.001 Replace functions with ones that succeed or die with lexical scope
fka9sxOL SEGOMOS 0 0
mb-JSON INA 0.01 0.02 a simple JSON parser for multibyte string

Stats

Number of new CPAN distributions this period: 51

Number of authors releasing new CPAN distributions this period: 28

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 17
2 SCHROEDER 3
3 PEVANS 2
4 SKINGTON 2
5 AJWOOD 2
6 PLICEASE 2
7 INA 2
8 RRWO 1
9 UTASHIRO 1
10 GUIDO 1
11 SSMN 1
12 AKRON 1
13 SLAFFAN 1
14 KOBOLDWIZ 1
15 NHORNE 1
16 JBARRETT 1
17 BRTASTIC 1
18 BYTERAZOR 1
19 SANKO 1
20 CARELINE 1
21 SEGOMOS 1
22 SARGIE 1
23 WOUTER 1
24 UHLE 1
25 HAARG 1
26 LEONT 1
27 DJERIUS 1
28 JULIODCS 1

delete an element from a hash

Perl Maven

Published by Gabor Szabo on Thursday 30 September 2021 08:30

The delete function will remove the given key from a hash.

Season of Docs project supporting newcomers and perl docs team

Perl Foundation News

Published by Nic Evans on Thursday 30 September 2021 05:20

Work continues at pace on the comprehensive audit of Perl's core documentation collection, which is funded through Google’s Season of Docs. The project was announced and began in May. As planned, it is expected to complete before the end of November.

Technical writer and communications specialist, Khawar Latif Khan is working in stages and has completed a full content audit alongside members of the community who have helped to test and review the documents, followed by a gap analysis, reviewing what is missing and where documents should be held.

Khawar began work on the project in mid-May. He says: “I was intrigued by the project. I spent some time getting familiar with perl and saw a lot of good content that needed organisation. Jason McIntosh, Dan Book and I sat together and looked at the problems users were facing and this helped me understand the limitations of perl.doc. There are more than 240 documents on perl.doc. The major aim is to create a roadmap for the future. Divide what is required into projects and sub projects, assigning tasks so we have a user-friendly picture of the documentation of perl.”

Jason McIntosh, Project Manager for Google Season of Docs, says: “I think the project will work really well and I see it leading to a lot of projects for the docs team which will have its work cut out for it in the best way.”

Not only that, it is hoped that the project will be beneficial for newcomers to perl. There may be some new users who would look at the data as it is now and be put off trying out more in perl. This project will hopefully encourage them to stick with it and see just how great perl is.

Jason says: “A large part of this project is about reorganising the data set, making it easier for everyone to look for documents and information, in particular this will be a great benefit for newcomers who might find the existing data set quite daunting.”

Khawar experienced this himself saying: “Initially, I was confused where to begin but now I have started it is interesting. I love the project. I enjoy the feedback I am getting, especially from Jason. He has been really helpful and supportive throughout the process.”

Jason says: “Khawar is a delight to work with. At the end of this project, he will be one of the most familiar people in the world with perl documentation. It has been of real value to go outside of the perl community, to get someone who has an objective viewpoint. We’re fortunate he was available.”

#531 - Legacy code

Perl Weekly

Published on Monday 27 September 2021 10:00

Hi there

I like working on legacy code whether it is Perl, Python or some other language, because it is code that is already very valuable to the organization that uses it. It is great to help the maintainers understand the code better and to give them confidence in making changes to the code.

There are a number of language specific tools that can help you while dealing with legacy code. For example Perl Critic which is mentioned in at least two posts this edition. There are more generic things, like setting up a good CI system which is mentioned by Gugod.

The ideal situation is when both management and the engineers really want the change. They still probably need some external help from someone who has experience in similar situations and who has already seen systems where the engineers have no fear in making changes. It is a totally different world than what many people experience in organizations.

Enjoy your fearless week!