wxPerl Revival

dev.to #perl

Published by Johan Vromans on Saturday 12 October 2024 19:09

For several years now, development and support of wxPerl, the interface library between Perl and wxWidgets, has stalled. The latest release was based on Perl 5.16 and wxWidgets 2.9.

Meanwhile some active users have made attempts to port wxPerl to newer versions of Perl and wxWidgets, with varying results. Microsoft Windows and Apple macOS provide additional challenges.

I believe in user-friendly desktop based GUI applications written in Perl and wxPerl is an excellent tool to develop these applications that are deployable across different desktop platforms. I hate to see wxPerl rusting away in the archives.

If you are using wxPerl and want to keep using it with recent
versions of Perl and wxWidgets, please join the mailing list.

As a start, I've set up a new, independent repo for wxPerl on GitHub.

It currently has two branches: wx30 and master.

Branch wx30 contains an updated version of the last 'official' release 0.9932, fixed for modern Perl and wxWidgets 3.0. I have released it on GitHub as Wx-0.9933.

The master branch has been updated with all necessary changes for wxWidgets 3.2. Also some constants and methods have been added to deploy some 3.2 functionality. I have released it on GitHub as Wx-3.001. More will be added in the future but will require help from Perl/XS experts.

Yes, you read that right. Just install Straberry Perl and gcc will be properly installed in your Windows machine.

Double Luhn

dev.to #perl

Published by Simon Green on Saturday 12 October 2024 03:11

Weekly Challenge 290

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Double Exist

Tasks

You are given an array of integers, @ints.

Write a script to find if there exist two indices $i and $j such that:

  1. $i != $j
  2. 0 <= ($i, $j) < scalar @ints
  3. $ints[$i] == 2 * $ints[$j]

My solution

This seems relatively straight forward, but there is a massive gotcha that hopefully other Team PWC members also noticed. For this task, I loop through the list and see if a value that is twice its value exist.

However, if the value is '0' (and thus 0 × 2 = 0), I need to check that there were at least two zeros in the list.

def double_exists(ints: list) -> bool:

    for i in ints:
        if i * 2 in ints:
            if i != 0 or ints.count(0) > 1:
                return True

    return False

Examples

$ ./ch-1.py 6 2 3 3
true

$ ./ch-1.py 3 1 4 13
false

$ ./ch-1.py 2 1 4 2
true

$ ./ch-1.py 1 3 0
false

$ ./ch-1.py 1 0 3 0
true

Task 2: Luhn’s Algorithm

Task

You are given a string $str containing digits (and possibly other characters which can be ignored). The last digit is the payload; consider it separately. Counting from the right, double the value of the first, third, etc. of the remaining digits.

For each value now greater than 9, sum its digits.

The correct check digit is that which, added to the sum of all values, would bring the total mod 10 to zero.

Return true if and only if the payload is equal to the correct check digit.

My solution

I start this task by removing non-digit characters from the string, and turn the reversed string into a list of integers.

I then use the supplied formula, alternating between adding the value to count or multiplying it by two and removing 9. If the resulting count is divisible by 10, I return True, otherwise I return False.

def luhn_algorithm(s: str) -> bool:
    s = re.sub('[^0-9]', '', s)
    ints = [int(n) for n in s[::-1]]

    count = 0
    for pos, i in enumerate(ints):
        if pos % 2 == 1:
            i *= 2
            if i > 9:
                i -= 9
        count += i
    return count % 10 == 0

Examples

$ ./ch-2.py  17893729974
true

$ ./ch-2.py  "4137 8947 1175 5904"
true

$ ./ch-2.py "4137 8974 1175 5904"
false

Finding Double Existence and Applying Luhn's Algorithm

dev.to #perl

Published by André Plöger on Friday 11 October 2024 19:50

In this article, we will address two engaging tasks from the Perl Weekly Challenge #290: checking for double existence in an array and implementing Luhn's Algorithm for validation. We'll implement solutions in both Perl and Go.

Table of Contents

  • Double Existence
  • Luhn's Algorithm
  • Conclusion

Double Existence

The first task involves finding if there exist two indices $i and $j such that:

1. $i != $j
2. 0 <= ($i, $j) < scalar @ints
3. $ints[i] = 2 * $ints[j]

Task Description

Input: An array of integers, @ints.

Output: true if the condition is met; otherwise, false.

Examples:

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

For $i = 0, $j = 2
$ints[$i] = 6 => 2 * 3 =>  2 * $ints[$j]
Input: @ints = (3, 1, 4, 13)
Output: false
Input: @ints = (2, 1, 4, 2)
Output: true

For $i = 2, $j = 3
$ints[$i] = 4 => 2 * 2 =>  2 * $ints[$j]

Solution

Perl Implementation
In the Perl implementation, we use a hash to track seen integers and check if either half or double of the current number exists in the hash.

sub double_exist {
    my %seen;

    foreach my $num (@_) {
        return 1 if exists $seen{$num / 2} || exists $seen{$num * 2};
        $seen{$num} = 1;
    }

    return 0;
}

Go Implementation
The Go implementation follows a similar logic, using a map to keep track of unique integers.

func doubleExist(ints []int) bool {
    seen := make(map[int]bool)

    for _, num := range ints {
        if (num%2 == 0 && seen[num/2]) || seen[num*2] {
            return true
        }
        seen[num] = true
    }

    return false
}

Luhn's Algorithm

The second task involves implementing Luhn's Algorithm to validate a string of digits, ignoring non-digit characters. The last digit is considered separately as the payload.

Task Description

You are given a string str containing digits (and possibly other characters which can be ignored). The last digit is considered as the payload and handled separately.

  1. Counting from the right, double the value of the first, third, etc., of the remaining digits.
  2. For each value now greater than 9, sum its digits.
  3. The correct check digit is the one that, when added to the sum of all values, brings the total modulo 10 to zero.

Return true if the payload equals the correct check digit; otherwise, return false.

Examples:

Input: "17893729974"
Output: true

Payload is 4.

Digits from the right:

7 * 2 = 14, sum = 5
9 = 9
9 * 2 = 18, sum = 9
2 = 2
7 * 2 = 14, sum = 5
3 = 3
9 * 2 = 18, sum = 9
8 = 8
7 * 2 = 14, sum = 5
1 = 1

Sum of all values = 56, so 4 must be added to bring the total mod 10 to zero. The payload is indeed 4.
Input: "4137 8947 1175 5904"
Output: true
Input: "4137 8974 1175 5904"
Output: false

Solution

Perl Implementation
The Perl implementation processes the input string to ignore non-digit characters, then applies Luhn's algorithm to validate the number.

sub luhn_check {
    my ($str) = @_;
    $str =~ s/[^0-9]//g;

    my $payload = substr($str, -1);
    my $sum = 0;
    my $length = length($str);

    for (my $i = 0; $i < $length - 1; $i++) {
        my $digit = substr($str, $length - 2 - $i, 1);
        if ($i % 2 == 0) {
            $digit *= 2;
            $digit -= 9 if $digit > 9;
        }
        $sum += $digit;
    }

    my $check_digit = (10 - ($sum % 10)) % 10;

    return $payload == $check_digit ? 1 : 0;
}

Go Implementation
The Go version implements the same logic, utilizing the unicode package to filter out non-digit characters.

func luhnCheck(str string) bool {
    sum := 0
    payload := 0
    digits := []int{}

    for _, char := range str {
        if unicode.IsDigit(char) {
            digit := int(char - '0')
            digits = append(digits, digit)
        }
    }

    if len(digits) == 0 {
        return false
    }

    payload = digits[len(digits)-1]

    for i := 0; i < len(digits)-1; i++ {
        digit := digits[i]
        if (len(digits)-2-i)%2 == 0 {
            digit *= 2
            if digit > 9 {
                digit -= 9
            }
        }
        sum += digit
    }

    checkDigit := (10 - (sum % 10)) % 10

    return payload == checkDigit
}

Conclusion

In this article, we explored two interesting programming challenges: finding double existence in an array and implementing Luhn's Algorithm for validation. These tasks highlight how different programming languages can tackle similar problems with their own unique approaches. I hope these examples inspire you to delve deeper into both Perl and Go!

You can find the complete code, including tests, on GitHub.

perlfunc - update each documentation with foreach examples

Also mention multiple-value foreach as a new alternative, and fix a hash dereference in a previous example.

Silence clang compilation warning

Perl commits on GitHub

Published by khwilliamson on Friday 11 October 2024 15:41

Silence clang compilation warning

Commit 9acaa9844a1adc113059335846a097b435800a22 introduced a compilation
warning that I only have seen with clang.  Casting appropriately gets
rid of it.

London Perl & Raku Workshop 2024 Silver Sponsors

blogs.perl.org

Published by London Perl Workshop on Friday 11 October 2024 14:30

This year's London Perl and Raku Workshop will take place on 26th Oct 2024. Without our sponsors this event would not happen and we would like to thank them.

geekuni.png

Perl developers are hard to get. As the leading language of the dotcom boom, Perl is one of the best-paid languages worldwide, yet Perl training seldom features on university curricula. But that doesn't have to cause a headache for employers trying to expand their Perl team.

Geekuni can give software developers with no previous Perl experience the training they need, as they need it. So, whether you’re looking to provide new recruits with online Perl training from day one of the onboarding process or upskill existing talent, Geekuni has the training package to empower your staff with Perl.

To find out more, go here: https://geekuni.com/corporate-perl-training or email andrew@geekuni.com

geizhals.png

Geizhals Preisvergleich is one of the largest product and price comparison platforms in the German-speaking area.

For now over 20 years, our company has proven itself in a highly competitive, dynamic industry.

We attribute our success to an uncompromising implementation of our company philosophy: transparency, objective and user-oriented information, and the quality of our content.

The Geizhals Preisvergleich teach team has been a proud user and supporter of the Perl programming language since the founding of the company. In the last months this includes directly supporting development for the "Corinna in Core" project.

datensegler.png

Datensegler e.U. is a small team of Perl enthusiasts specialized in agile software development and PostgreSQL consulting from Vienna, Austria and are happy to sponsor the LPW2024.

We use Perl in the majority of our projects both for web applications (shout-out to the formidable Mojolicious framework) and backend tasks from ETL to web scraping since, well basically forever.

We also offer PostgreSQL consulting, including developer support, optimization and operating. If you want to migrate from Oracle or MySQL to PostgreSQL we can lend a helping hand too.

spareroom.png

Founded in 2004 and based in Manchester, SpareRoom is the largest flatmate finding service in the UK and globally. Sharing isn’t just at the heart of our business - it IS our business. We are dedicated to helping people find more than just a room; we help them find the right people to live with and turn their flatshare into their home.

A Perl company from the start, we continue to enhance our services using modern Perl, thanks to our small but talented team of seasoned Perl developers and our commitment to training junior developers as they embark on their Perl journey. We are usually on the lookout for Perl talent, so feel free to contact us through our jobs page.

Our commitment to Perl and open-source software is strong. You can often find our team members either attending or speaking at Perl events, or contributing to CPAN and other open-source projects. Thus, we are proud to sponsor the London Perl Workshop as it makes its return, an event we have eagerly awaited and supported.

This week in PSC (163) | 2024-10-10

blogs.perl.org

Published by Perl Steering Council on Friday 11 October 2024 04:21

We had a guest this week: Olaf Alders.

  • We exchanged Perl (re)branding ideas with Olaf. We will be keeping in touch on that front.
  • We discussed the feedback on feature-guarding and unbundling apostrophe. We came up with a strategy to propose that we think should work, which will be posted on the relevant thread.
  • We discussed the fact that keeping the current smartmatch operator (as a feature) means we can’t have a meaningful air gap to prevent subtle bugs when moving to a future “good” smartmatch. This probably implies that we would be giving up on any future smart match operator, but there are usually better replacements.

[P5P posting of this summary]

Perl Weekly Challenge 290: Double Exist

blogs.perl.org

Published by laurent_r on Friday 11 October 2024 03:20

These are some answers to the Week 290, Task 1, 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 13, 2024, at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Double Exist

You are given an array of integers, @ints.

Write a script to find if there exist two indices $i and $j such that:

1) $i != $j
2) 0 <= ($i, $j) < scalar @ints
3) $ints[$i] == 2 * $ints[$j]

Example 1

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

For $i = 0, $j = 2
$ints[$i] = 6 => 2 * 3 =>  2 * $ints[$j]

Example 2

Input: @ints = (3, 1, 4, 13)
Output: false

Example 3

Input: @ints = (2, 1, 4, 2)
Output: true

For $i = 2, $j = 3
$ints[$i] = 4 => 2 * 2 =>  2 * $ints[$j]

I initially didn't understand condition (2). This ($i, $j) expression didn't make sense to me, until I understood that it meant that both $i and $j have to be greater than or equal to zero, and smaller than the number of items in the array.

Note that the first condition, $i != $j, is unnecessary since, if $i == $j, then we cannot meet condition (3), $ints[$i] == 2 * $ints[$j]. Well, that is except if the value is 0, but zeros should be avoided anyway because we could have 0 = 2 * 0, which is technically true, but that's not really the meaning of the task. I'll therefore consider that the input should be an array of non-zero integers because what we should do with the zero special case is unclear and not specified in the task. Thus, there is no need to check condition (1) in our code (this applies only to the Perl implementation, as we don't have this issue with the Raku implementation).

Double Exist in Raku

In Raku, the built-in combinations routine make it possible to generate automatically all combinations of two items of an array. Combinations are unordered. In other words, with an input such as <1 2 3>, the combinations method will generate the following combinations: (1 2) (1 3) (2 3), but not (2, 1), (3, 1), or (3, 2). Therefore, for each combination, we need to compare both ways: is the first item the double of the second, and is the second item the double of the first.

sub double-exists (@in) {
    for @in.combinations: 2 -> $comb {
        return True if $comb[0] == 2 * $comb[1] or 
            $comb[1] == 2 * $comb[0];
    }
    False;
}

my @tests = <1 2 3 4>, <6 2 3 3>, <3 1 4 13>, <2 1 4 2>;
for @tests -> @test {
    printf "%-10s => ", "@test[]";
    say double-exists @test;
}

This program displays the following output:

$ raku ./double-exists.raku
1 2 3 4    => True
6 2 3 3    => True
3 1 4 13   => False
2 1 4 2    => True

Double Exist in Perl

Perl doesn't have a built-in combinations subroutine, so we will apply the canonical method of generating them (as well as those reversing the value order) using two nested loops. Please read my comments at the beginning of this post concerning the first condition ($i != $j) and the need to avoid zero values in the input. If you disagree with my view, it is very easy to add a code list such as:

next if $i == $j;

in the inner loop of the code below.

sub double_exists {
    for my $i (0..$#_) {
        for my $j (0..$#_) {
            return "True" if $_[$i] == 2 * $_[$j];
        }
    }
    return "False";
}

my @tests = ( [1, 2, 3, 4], [6, 2, 3, 3 ], 
              [3, 1, 4, 13], [2, 1, 4, 2] );
for my $test (@tests) {
    printf "%-10s => ", "@$test";
    say double_exists @$test;
}

This program displays the following output:

$ perl ./double-exists.pl
1 2 3 4    => True
6 2 3 3    => True
3 1 4 13   => False
2 1 4 2    => True

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

Weather::OWM released on CPAN

blogs.perl.org

Published by Dimitrios Kechagias on Friday 11 October 2024 00:15

I am in the process of adding OpenWeatherMap support to Xasteria Weather for iOS and the proxy I built is in Perl. Since there was only an old module on CPAN which did not support the current API and was not easily updatable, I released Weather::OWM. It's a very simple module, similar to two other Weather modules I've released in the past (Weather::WeatherKit and Weather::Astro7Timer).
The OpenWeather API has a Free tier with both current weather and forecast, which makes the module useful to anyone interested in fetching weather for any location. E.g.


use Weather::OWM;
 
my $owm = Weather::OWM->new(key => 'Your API key');

# Get current weather for the Stonehenge area using lat/lon...
my %r = $owm->get_weather(lat => 51.18, lon => -1.83);

# ...and print temperature, humidity, wind speed
say "$r{main}->{temp}C $r{main}->{humidity}% $r{wind}->{speed}m/s"
unless $r{error};

# Get 3h/5d forecast for London, UK...
%r = $owm->get_weather(product => 'forecast', loc => 'London,UK');

# ...print the temperature for every 3 hours over the next 5 days
say scalar(localtime($_->{dt}))." $_->{main}->{temp}C"
for @{$r{list}};

Perl Weekly Challenge 290: Luhn's Algorithm

blogs.perl.org

Published by laurent_r on Thursday 10 October 2024 17:30

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

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

Task 2: Luhn’s Algorithm

You are given a string $str containing digits (and possibly other characters which can be ignored). The last digit is the payload; consider it separately. Counting from the right, double the value of the first, third, etc. of the remaining digits.

For each value now greater than 9, sum its digits.

The correct check digit is that which, added to the sum of all values, would bring the total mod 10 to zero.

Return true if and only if the payload is equal to the correct check digit.

It was originally posted on reddit.

Example 1

Input: "17893729974"
Output: true

Payload is 4.

Digits from the right:

7 * 2 = 14, sum = 5
9 = 9
9 * 2 = 18, sum = 9
2 = 2
7 * 2 = 14, sum = 5
3 = 3
9 * 2 = 18, sum = 9
8 = 8
7 * 2 = 14, sum = 5
1 = 1

Sum of all values = 56, so 4 must be added to bring the total mod 10 to zero. The payload is indeed 4.

Example 2

Input: "4137 8947 1175 5904"
Output: true

Example 3

Input: "4137 8974 1175 5904"
Output: false

The Luhn algorithm is a simple check digit formula (or checksum) used to validate a variety of identification numbers.

The algorithm was invented in 1960 and is in wide use today. It is aimed at protecting against accidental typing errors. Most credit cards and many government identification numbers use the algorithm as a simple method of distinguishing valid numbers from mistyped or otherwise incorrect numbers.

This task has real life applications. In my professional career as a contractor for a tier-one cell phone operator for 26 years, I implemented the Luhn algorithm at least three times (in three different programming languages, including Perl, but I no longer have the code developed then, so I had to re-implement it from scratch for this task). In the mobile phone industry, the Luhn formula is used for validating at least two identification numbers: the International Mobile Equipment Identity (IMEI), an identifier for the phone itself, and the Integrated Circuit Card Identifier (ICCID) for the SIM card (or eSIM profile).

The algorithm described above can be simplified. Rather than performing the calculations on the identification number without the trailing check digit, we can do it directly on the whole number (with the check digit). This modified algorithm goes as follows:

  • Reverse the order of the digits in the number.

  • Take the second, fourth ... and every other even digit in the reversed digits, multiply them by two and sum the digits if the answer is greater than nine.

  • Add all the digits; if the sum is a multiple of 10 (ends in zero), then the original number is a valid identification number.

Luhn’s Algorithm in Raku

This program implements the modified algorithm described just above. First, the program uses a regex to remove characters that are not digits from the input string. Then it reverses the resulting string, using the flip method, and splitted into an array of individual characters (@digits), using the comb method. Then, it multiplies by 2 the values of @digits with and even index, and sums the digits of the resulting number (using a comb and sum combination. Finally, the original number is validl if the sum of all digits can be evenly divided by 10.

sub luhn ($in is copy) {
    $in ~~ s:g/\D+//;  # remove non-digits
    my @digits = $in.flip.comb;  # reverse and split
    for 0..@digits.end -> $i {
        # values for even indices don't change
        @digits[$i] = (2 * @digits[$i]).comb.sum unless $i %% 2;
    }
    return @digits.sum %% 10; # valid if sum end with a 0
}

for "17893729974", "178az93r729974", "178 9372 9 9  74",
    "4137 8947 1175 5904", "4137 8974 1175 5904" -> $test {
    printf "%-25s => ", $test;
    say luhn $test;
}

This program displays the following output:

$ raku ./luhn.raku
17893729974               => True
178az93r729974            => True
178 9372 9 9  74          => True
4137 8947 1175 5904       => True
4137 8974 1175 5904       => False

Luhn’s Algorithm in Perl

This is a port to Perl of the above Raku program. Please refer to the previous sections if you need explanations. The comb built-in is replaced by split and we implemented our own sum and sum_digits auxiliary subroutines.

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

sub sum {
    my $sum = 0;
    for my $n (@_) {
        $sum += $n;
    }
    return $sum;
}
sub sum_digits {
    return sum split //, shift;
}

sub luhn {
    my $in = shift;
    $in =~ s/\D+//g;             # remove non-digits
    my @digits = reverse split //, $in; # reverse and split
    for my $i (0..$#digits) {
        next unless $i % 2;   #skip even indices
        my $val = 2 * $digits[$i];
        $digits[$i] = sum_digits $val;
    }
    # valid luhn if sum ends with a 0 (multiple of 10)
    return (sum @digits) % 10 == 0 ? "True" : "False"; 
}

for my $test ("17893729974", "178a93r729974", "178 9372 9 9 74",
    "4137 8947 1175 5904", "4137 8974 1175 5904") {
    printf "%-25s => ", $test;
    say luhn $test;
}

This program displays the following output:

$ perl  ./luhn.pl
17893729974               => True
178a93r729974             => True
178 9372 9 9 74           => True
4137 8947 1175 5904       => True
4137 8974 1175 5904       => False

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

IPC::Run and Applescript

Perl questions on StackOverflow

Published by simone on Thursday 10 October 2024 15:52

My end-goal is to:

  • get PNG data from the clipboard on MacOS
  • do stuff with it (typically with ImageMagick)
  • put it back onto the clipboard

and I'm trying to do that with IPC::Run in perl

It looks like the minimal example in AppleScript works:

set in_clip to get the clipboard as «class PNGf»
set the clipboard to in_clip as «class PNGf»

generates no error, and leaves the clipboard alone.

When I try to do what I think is the same in perl:

use IPC::Run qw/run/;
use utf8;

$\ = "\n"; $, = "\t";

my ($stdin, $stdout, $stderr);

run ["osascript", "-e", "get the clipboard as «class PNGf»"], \$stdin, \$stdout, \$stderr;
print ("original data:", (substr $stdout, 0, 100) . "..." . (substr $stdout, -200)) ;

run ["osascript", "-e", (sprintf qq(set the clipboard to "%s" as «class PNGf»), ($stdout =~ s/\n//gmrs))], \$stdin, \$stdout, \$stderr;

print ("convert error:", (substr $stderr, 0, 100) . (substr $stderr, -200)) ;

I get errors: the script throws:

convert 64548:64560: execution error: Can’t make "«data PNGf89504E4...26082»" into type «class PNGf»

What's going on here?

I understand this is messy and at a perilous borderline, but why?

bytes_to_utf8: Don't redo work

Perl commits on GitHub

Published by khwilliamson on Thursday 10 October 2024 14:13

bytes_to_utf8: Don't redo work

We have gone to some trouble to find the first UTF-8 variant character
in the input string.  There is no need to look again for variants in the
portion of the string that we have already determined doesn't have any
such variants.

This missing statement appears to have been an oversight.

Fix compilation warnings about UTF8_\w+_PERL_EXTENDED

Perl commits on GitHub

Published by khwilliamson on Thursday 10 October 2024 13:49

Fix compilation warnings about UTF8_\w+_PERL_EXTENDED

Commit b66abe3878e48c99de059364b052d96c7be8ee75 added these symbols to
two #defines, but neglected to remove the special casing that had been
used when it wasn't in them.

I'm suddenly unable to run any Perl scripts under Cygwin. Every script I try to run crashes like this:

phil@TAICHI /cygdrive/h/bakE/new/virChecked
$ findFiles -s . -t /cygdrive/D/data-comp/text -u /cygdrive/E/new/virChecked/text -d -a .3
Can't load '/home/phil/perl5/lib/perl5/x86_64-cygwin-threads-multi/auto/Win32/File/File.dll' for module Win32::File: No such file or directory at /usr/lib/perl5/5.36/x86_64-cygwin-threads/DynaLoader.pm line 206.
 at /usr/local/bin/findFiles line 24.
Compilation failed in require at /usr/local/bin/findFiles line 24.
BEGIN failed--compilation aborted at /usr/local/bin/findFiles line 24.

phil@TAICHI /cygdrive/h/bakE/new/virChecked
$ pushd /home/phil/perl5/lib/perl5/x86_64-cygwin-threads-multi/auto/Win32/File/
~/perl5/lib/perl5/x86_64-cygwin-threads-multi/auto/Win32/File /cygdrive/h/bakE/new/virChecked

phil@TAICHI ~/perl5/lib/perl5/x86_64-cygwin-threads-multi/auto/Win32/File
$ ls -l File.dll
-r-xr-xr-x 1 phil None 178K Jul 14  2021 File.dll*

Sometimes perl won't open File.dll; sometimes it won't open IO.dll. In either case, the DLL is always exactly where Perl is looking for it, with world read privs; but Perl won't load it.

Line 206 of Dynaloader.pm is

my $libref = dl_load_file($file, $flags) or croak("Can't load '$file' for module $module: ".dl_error());

A comment near the start of Dynaloader says:

The load function that dl_load_file() calls may require an absolute pathname.

I can't find where dl_load_file() is defined. It isn't in Dynaloader.pm; and the only module Dynaloader includes is Config, which also doesn't have it, and includes no other files.

I suspect that some Perl module has changed, with the result that dl_load_file doesn't convert Cygwin absolute pathnames to Windows absolute pathnames. I tried reinstalling Perl 5.36.3-1, but it didn't help. I also made a new Cygwin installation and installed Perl 5.40, but it behaved the same way.

Questions:

  • Is anyone else currently able to use Perl in Cygwin using the lastest Cygwin packages?
  • Any idea what might have changed recently to make Cygwin Perl unable to use full Cygwin paths?
  • Where can I find a Cygwin perl distribution prior to Perl 5.32?

How to pass JSON using WWW::Mechanize in perl

Perl questions on StackOverflow

Published by Nilesh on Wednesday 09 October 2024 18:44

We are using WWW::Mechanize to send json data to our api.

My code is below.

#!/usr/local/bin/perl

use WWW::Mechanize;

sub get_csrf_token {
    my $sso = shift;
    my $referer = shift;
    my @cookie_items;
    my $rsp = $sso->get($referer);
    my $set_cookie = $rsp->header('set-cookie');
    if ($set_cookie =~ /csrftoken=(\S+);/) {
        push(@cookie_items, $1);
    }
    if ($set_cookie =~ /sessionid=(\S+);/) {
        push(@cookie_items, $1);
    }
    else {
        die 'Failed to get CSRF Token';
    }
    return @cookie_items;
}

my $sso = WWW::Mechanize->new(
        keep_alive  => 0,
        timeout     => 3000,
        stack_depth => 1,
        debug       => 1,
        verbose     => 1,
        key         => "/home/user/.athenz/key",
        cert        => "/home/user/.athenz/cert",
    );

my $referer = "https://myapi.domain.com/athenz/api/healthcheck/";
my @cookies = get_csrf_token($sso, $referer);
$sso->add_header('Referer' => $referer);
$sso->add_header('X-CSRFToken' => $cookies[0]);
$sso->add_header('Cookie' => "sessionid=$cookies[1]; csrftoken=$cookies[0]");

my %content = (
          'value' => '127.0.0.1',
          'key_name' => 'NTP_SERVERS'
);

my $response = $sso->put("https://myapi.domain.com/athenz/api/NTP_SERVERS/", \%content);

print "^^^^^^^^^^^^^^^^^^^^^^^^^\n";
print $response->code();
print "\n^^^^^^^^^^^^^^^^^^^^^^^^^\n";

its give me error Error PUTing https://myapi.domain.com/athenz/api/NTP_SERVERS/: Bad Request at /tmp/test.pm line 53

When I check server logs, its seems, the payload which I am sending, is deliver to server as HASH instead of json.

Below is apache logs.

[Mon Oct 07 18:32:27.987189 2024] [ssl:info] [pid 19745:tid 19745] [client 127.0.0.1:58372] AH01964: Connection to child 29 established (server myapi.domain.com:443)
[Mon Oct 07 18:32:27.987600 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [init-blocking] 0 readbytes
[Mon Oct 07 18:32:27.987964 2024] [ssl:debug] [pid 19745:tid 19745] ssl_engine_kernel.c(2393): [client 127.0.0.1:58372] AH02043: SSL virtual host for servername myapi.domain.com found
[Mon Oct 07 18:32:27.992817 2024] [ssl:debug] [pid 19745:tid 19745] ssl_engine_kernel.c(2256): [client 127.0.0.1:58372] AH02041: Protocol: TLSv1.2, Cipher: ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)
[Mon Oct 07 18:32:27.992936 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.993929 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 53 bytes
[Mon Oct 07 18:32:27.993964 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): PUT /athenz/api/NTP_SERVERS/ HTTP/1.1

[Mon Oct 07 18:32:27.994033 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994047 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 24 bytes
[Mon Oct 07 18:32:27.994056 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): TE: deflate,gzip;q=0.3

[Mon Oct 07 18:32:27.994065 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994089 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 23 bytes
[Mon Oct 07 18:32:27.994093 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): Connection: TE, close

[Mon Oct 07 18:32:27.994100 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994104 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 23 bytes
[Mon Oct 07 18:32:27.994123 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): Accept-Encoding: gzip

[Mon Oct 07 18:32:27.994127 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994132 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 45 bytes
[Mon Oct 07 18:32:27.994135 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): Host: myapi.domain.com

[Mon Oct 07 18:32:27.994139 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994143 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 84 bytes
[Mon Oct 07 18:32:27.994147 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): Referer: https://myapi.domain.com/athenz/api/healthcheck/

[Mon Oct 07 18:32:27.994151 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994155 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 32 bytes
[Mon Oct 07 18:32:27.994158 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): User-Agent: WWW-Mechanize/1.72

[Mon Oct 07 18:32:27.994185 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994190 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 128 bytes
[Mon Oct 07 18:32:27.994193 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): Cookie: sessionid=XXXXXXX; csrftoken=YYYYYYY

[Mon Oct 07 18:32:27.994198 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994201 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 19 bytes
[Mon Oct 07 18:32:27.994205 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): HASH(0x1d5b760):

[Mon Oct 07 18:32:27.994209 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(140): [client 127.0.0.1:58372] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:32:27.994213 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(63): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): 79 bytes
[Mon Oct 07 18:32:27.994217 2024] [dumpio:trace7] [pid 19745:tid 19745] mod_dumpio.c(103): [client 127.0.0.1:58372] mod_dumpio:  dumpio_in (data-TRANSIENT): X-CSRFToken: YYYYYYY

[Mon Oct 07 18:32:27.994223 2024] [core:debug] [pid 19745:tid 19745] protocol.c(1290): [client 127.0.0.1:58372 {YRA:127.0.0.1:58372, YPA:127.0.0.1:58372}] AH02426: Request header field name is malformed: HASH(0x1d5b760):, referer: https://myapi.domain.com/athenz/api/healthcheck/
[Mon Oct 07 18:32:27.994328 2024] [core:debug] [pid 19745:tid 19745] protocol.c(1482): [client 127.0.0.1:58372 {YRA:127.0.0.1:58372, YPA:127.0.0.1:58372}] AH00567: request failed: error reading the headers, referer: https://myapi.domain.com/athenz/api/healthcheck/

If I use same API with curl, it works fine and apache logs gives no error.

curl --cert ~/.athenz/cert --key ~/.athenz/key -H "Content-type: application/json" -H "X-CSRFToken: $TOKEN" --referer "https://myapi.domain.com/athenz/api/healthcheck/" --cookie "csrftoken=$TOKEN;sessionid=$SESSIONID;" "https://myapi.domain.com/athenz/api/NTP_SERVERS/" -X PUT -d '{"key_name": "NTP_SERVERS", "value": "98.139.133.27"}' -i
HTTP/1.1 200 OK
Date: Mon, 07 Oct 2024 18:26:50 GMT
P3P: policyref="https://policies.domain.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE LOC GOV"
Allow: GET, PUT, DELETE, HEAD, OPTIONS
X-Frame-Options: DENY
Vary: Cookie
Content-Length: 0
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS
Access-Control-Allow-Credentials: true
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Set-Cookie: csrftoken=YYYYYYYYYYY; Domain=.domain.com; expires=Mon, 06 Oct 2025 18:26:53 GMT; Max-Age=31449600; Path=/; SameSite=Lax
Set-Cookie: sessionid=XXXXXXXXXXXX; expires=Mon, 21 Oct 2024 18:26:53 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
Cache-Control: private
Connection: close

The apache logs, which print the json I passed in the curl.

[Mon Oct 07 18:26:50.576736 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935742 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 53 bytes
[Mon Oct 07 18:26:50.935767 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): PUT /athenz/api/NTP_SERVERS/ HTTP/1.1

[Mon Oct 07 18:26:50.935821 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935840 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 31 bytes
[Mon Oct 07 18:26:50.935844 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Host: myapi.domain.com

[Mon Oct 07 18:26:50.935848 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935852 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 24 bytes
[Mon Oct 07 18:26:50.935857 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): User-Agent: curl/8.7.1

[Mon Oct 07 18:26:50.935863 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935867 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 13 bytes
[Mon Oct 07 18:26:50.935871 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Accept: */*

[Mon Oct 07 18:26:50.935875 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935880 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 43 bytes
[Mon Oct 07 18:26:50.935883 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Referer: https://myapi.domain.com/api/healthcheck/

[Mon Oct 07 18:26:50.935887 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935890 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 128 bytes
[Mon Oct 07 18:26:50.935894 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Cookie: csrftoken=YYYYYYYY;sessionid=XXXXXXX;

[Mon Oct 07 18:26:50.935908 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935913 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 32 bytes
[Mon Oct 07 18:26:50.935917 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Content-type: application/json

[Mon Oct 07 18:26:50.935922 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935926 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 79 bytes
[Mon Oct 07 18:26:50.935930 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): X-CSRFToken: YYYYYYYYY

[Mon Oct 07 18:26:50.935934 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935937 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 20 bytes
[Mon Oct 07 18:26:50.935942 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): Content-Length: 91

[Mon Oct 07 18:26:50.935946 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [getline-blocking] 0 readbytes
[Mon Oct 07 18:26:50.935949 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 2 bytes
[Mon Oct 07 18:26:50.935953 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT):

[Mon Oct 07 18:26:50.937521 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(140): [client 127.0.0.1:57073] mod_dumpio: dumpio_in [readbytes-blocking] 91 readbytes
[Mon Oct 07 18:26:50.937532 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(63): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): 91 bytes
[Mon Oct 07 18:26:50.937537 2024] [dumpio:trace7] [pid 19725:tid 19725] mod_dumpio.c(103): [client 127.0.0.1:57073] mod_dumpio:  dumpio_in (data-TRANSIENT): {"key_name": "NTP_SERVERS", "value": "98.139.133.27"}
[Mon Oct 07 18:26:50.937558 2024] [ssl:info] [pid 19725:tid 19725] [client 127.0.0.1:57073 {YRA:127.0.0.1:57073, YPA:127.0.0.1:57073}] AH02221: Requesting connection re-negotiation, referer: https://myapi.domain.com/api/healthcheck/

How can I make sure, perl script pass json data to the apache server? I tried setting Content-Type: application/json, that didnt work.

Perl search and replace words in file

Perl questions on StackOverflow

Published by Trey B on Wednesday 09 October 2024 17:01

I am not sure how to search and replace word from Perl.

I have .txt that contains image file names in random order.

Animals.txt

There is an image Dog_Image_85.jpg
Cat has an image Cat_Image_front.jpg
Here is another image Dog_Image_61.jpg
Cat has another image Cat_Image_back.jpg
Next image Dog_Image_55.jpg
Next Image Cat_Image_side.jpg
Next Image Dog_Image_200.jpg

I only want to change the Dog image names to a counter so it goes:

There is an image Dog_Image_1.jpg
Cat has an image Cat_Image_front.jpg
Here is another image Dog_Image_2.jpg
Cat has another image Cat_Image_back.jpg
Next image Dog_Image_3.jpg
Next Image Cat_Image_side.jpg
Next Image Dog_Image_4.jpg

I have tried these but I get an error each time:

#!/usr/local/bin/perl -w -I ../lib -I ./

use strict;

my $Animals = "Animals";

my $file = "$Animals.txt";

perl -pi -e 's/Dog_Image_.*.jpg/"Dog_Image_.++$i.jpg"/ge' $file;

This gives me an error: Can't use bareword perl.

I also tried with:

system('s/Dog_Image_.*.jpg/"Dog_Image_.++$i.jpg"/ge' $file);'

It still gives an error.

I have a syntax error in a Perl script that I don't understand:

# map BLOCK LIST
map { "/$_" => 1 } qw(foo bar baz);   # syntax error at .. line 1, near "} qw(foo bar baz)"

I have to rewrite it like this:

map { '/' . $_ => 1 } qw(foo bar baz);  # no error

This piece of code works on the other hand:

# Hash reference.
{ "/$_" => 1 };

I am using Perl 5.34.0.

TOTP with Perl and Authen::OATH

r/perl

Published by /u/pmz on Wednesday 09 October 2024 12:44

Maintaining Perl 5 Core (Dave Mitchell): September 2024

Perl Foundation News

Published by alh on Wednesday 09 October 2024 07:35


Dave writes:

This is my monthly report on work done during September 2024 covered by my TPF perl core maintenance grant.

I spent most of last month continuing to do various bits of code refactoring and test-adding on Extutils::ParseXS, as a precursor to adding reference-counted stack (PERL_RC_STACK) abilities to XS.

SUMMARY:

  • 5:02 process p5p mailbox
  • 2:06 reduce smoke failures
  • 54:15 refactor Extutils::ParseXS

Total: * 61:23 TOTAL (HH::MM)

How to create a parallel echo server using goroutines in SPVM?

dev.to #perl

Published by Yuki Kimoto on Wednesday 09 October 2024 05:59

How to create a parallel echo server using goroutines in SPVM?

I write a parallel echo server using SPVM::IO::Socket::IP and goroutines, channels, select in SPVM::Go.

See the following test code.

run_echo_server_go

Release of DateTime::Format::Intl

r/perl

Published by /u/jacktokyo on Wednesday 09 October 2024 02:45

I am quite thrilled to announce that after several months of hard work, I have released the perl module DateTime::Format::Intl. It mirrors its JavaScript equivalent of Intl.DateTimeFormat. The algorithm is quite elaborate, replicating how it works in web browsers. I also had to develop quite a few dependencies to make it work, notably Locale::Unicode and Locale::Unicode::Data, which provides access to all the Unicode CLDR (Common Locale Data Repository) data as an SQLite database via an extensive number of perl methods. I hope it will benefit you and supports you in the internationalisation of your projects in perl.

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

Why The Perl and Raku Foundation Supports The Open Source Pledge

Perl Foundation News

Published by Stuart J Mackintosh on Tuesday 08 October 2024 11:00

The Open Source Pledge

We at The Perl and Raku Foundation are supporting the Open Source Pledge initiative.

The Open Source Pledge consists of companies with a shared commitment to paying the maintainers of the open source software they consume, therefore aims to help address sustainability challenges facing the Open Source community.

The Sustainability Challenge in OSS

Open source software is the backbone of much of today’s technology, but it relies heavily on the unpaid work of maintainers. As these volunteers struggle with burnout, turnover among OSS maintainers is high. Without the necessary support, key projects face the risk of disruption, which has far-reaching implications for the broader tech ecosystem. We have already seen the devastating effects of underfunded projects.

The Perl and Raku Foundation's Role in OSS

The Perl and Raku Foundation goal is to build a strong, healthy and sustainable language ecosystem and community. We also understand the importance of sustained funding for OSS projects. Through our community and core maintenance grants, we will provide support to developers who maintain essential infrastructure. These few dedicated individuals keep key components running, which are relied upon by both commercial systems and the broader internet.

This funding is necessary not only for technical upkeep but also for the non-technical aspects of managing open source communities. Without this support, the risk of losing essential contributors and the valuable work they do is too great.

This model of sustainability funding goes beyond just code contributions and aligns with the goals of the Open Source Pledge. It shows how financial support can be leveraged to maintain not just software, but entire developer ecosystems. This reinforces the importance of initiatives like the Open Source Pledge in supporting the broader open source ecosystem.

The Case for Joining the Pledge

The Open Source Pledge sets a new standard for how companies can contribute to OSS sustainability. By joining, companies commit to paying at least $2,000 per year for each developer on staff, with transparency through an annual report that details their payments.

We encourage other organizations to join us in supporting the Open Source Pledge, and using this as a method to set the value of your donations. By doing so, you’ll help ensure that the Perl and Raku ecosystem as well as the wider Open Source efforts remain healthy and sustainable, and that developers are recognized for the critical work they do. For more information about the Open Source Pledge and how to participate, please visit https://osspledge.com/

This is a welcome step in the right direction. "The Open Source Pledge is a crucial step towards ensuring the long-term sustainability of the open source ecosystem and by participating in this pledge, businesses can play a role in fostering innovation and maintaining the digital infrastructure we all rely on." Stuart Mackintosh, President of The Perl and Raku Foundation.

You can support The Perl and Raku Foundation directly using the method described by the Open Source Pledge, or any other amount that you can afford, details on our donations page here.

How to generate an executable file for an AI program using SPVM ?

dev.to #perl

Published by Yuki Kimoto on Tuesday 08 October 2024 04:59

Wouldn't you like to output a single executable file from your AI program? Then, you can run the AI ​​program just by copying the executable file to the Raspberry Pi. Here's how to achieve this using SPVM. Here's an example of image recognition using MINIST as an example of AI using deep learning.

SPVM program

This is an AI program to recognize images using MINIST data.

It is writen by SPVM and SPVM::R.

Install dependent modules.

cpanm SPVM
cpanm SPVM::Errno
cpanm SPVM::File::Basename
cpanm SPVM::File::Spec
cpanm SPVM::FindBin
cpanm SPVM::Math
cpanm SPVM::Regex
cpanm SPVM::Sys
cpanm SPVM::Time::Local
cpanm SPVM::Time::Piece
cpanm SPVM::IO
cpanm SPVM::R

Execute an SPVM program.

spvm -I network_lib/SPVM my_minist_app.spvm

Generate an executable file and execute it.

spvmcc -I network_lib/SPVM -o my_minist_app my_minist_app.spvm

./my_minist_app

I'm not an AI expert, but if you are, I think you can modify this.

If you're interested in parallelization using threads and goroutines, see also:

Improving in perl

r/perl

Published by /u/Recent-Astronaut-240 on Monday 07 October 2024 13:58

Hey, I am writting in perl since few years I have written lots of stuff over the years however would consider myself more beginner, I love syntax and the fact that perl is almost on every linux. My main usecase is system scripting/parallelizing tasks/ some API clients.

I have felt in love threads::queue and inotify2 implementation and use them very frequently.

Module management - What is more nowadays standard to manage them?

I use cpan, or download module from cpan and execute perl makefile or later generated C Makefile.

However sometimes struggle:

Last example that comes to my mind:

I want to create simple app that interacts with cassandra and any module I try to gather is based on deprecated IO::Sockets::INET6 - also have disabled ipv6 and not able to build it. Is there any package manager that ships modules in some more portable formats?

If I build module that for example needs some .so that is bound to kABI [Inotify2] I push them to system perllib path. I understand that it is based on kABI and need to recompile with kernel-headers. But is there any more portable solution. My feeling is that on python side managing pkgs with pip is easier.

EDIT:

  • Shipping modules with APP, Is there like any equavilent for python-venv?

Is there any not code related method?

So far I use:

use FindBin; use lib "$FindBin::Bin/lib"; 

And bundle them locally.

  • Object model:

I tried writting OOP in pure perl and blessing every constructor seems strange for me.

I heard about Moo and Moose - are they still activly used? Are they simple to use for simple scripts?

  • Web development

Which frameworks are most popular nowadays? Do not have much requirements only MVC support and maybe some simple templating engine. Just for some small simple dashboards, project sites.

  • Web SAPI - How is invoked modern perl webapplication - apache mod_perl? Standalone perl? What is modern approach?
submitted by /u/Recent-Astronaut-240
[link] [comments]

Blog

The Weekly Challenge

Published on Monday 07 October 2024 05:16

TABLE OF CONTENTS 01. HEADLINES 02. STAR CONTRIBUTORS 03. CONTRIBUTION STATS 04. GUESTS 05. LANGUAGES 06. CENTURION CLUB 07. DAMIAN CONWAY’s CORNER 08. ANDREW SHITOV’s CORNER 09. PERL SOLUTIONS 10. RAKU SOLUTIONS 11. PERL & RAKU SOLUTIONS HEADLINES Thank you Team PWC for your continuous support and encouragement. STAR CONTRIBUTORS Following members shared solutions to both tasks in Perl and Raku as well as blogged about it.

The Weekly Challenge - Perl & Raku

The Weekly Challenge

Published on Monday 07 October 2024 05:16

The page you are looking for was moved, removed, renamed or might never existed.

Perl

The Weekly Challenge

Published on Monday 07 October 2024 05:16

TABLE OF CONTENTS 01. HEADLINES 02. STAR CONTRIBUTORS 03. CONTRIBUTION STATS 04. GUESTS 05. LANGUAGES 06. CENTURION CLUB 07. DAMIAN CONWAY’s CORNER 08. ANDREW SHITOV’s CORNER 09. PERL SOLUTIONS 10. RAKU SOLUTIONS 11. PERL & RAKU SOLUTIONS HEADLINES Thank you Team PWC for your continuous support and encouragement. STAR CONTRIBUTORS Following members shared solutions to both tasks in Perl and Raku as well as blogged about it.

RECAP - The Weekly Challenge - 163

The Weekly Challenge

Published on Monday 07 October 2024 05:16

Thank you Team PWC for your continuous support and encouragement.

The Weekly Challenge - 036

The Weekly Challenge

Published on Monday 07 October 2024 05:16

With great pleasure, we announce Steven Wilson as the winner of “The Weekly Challenge - 035”. Congratulations Steven, you should soon hear from Perl Careers about your reward. For rest of the participants, I would say Good Luck for next time. Keep sending in your solutions and share your knowledge with each other.

perlvars.h: remove extraneous semicolon

Perl commits on GitHub

Published by craigberry on Sunday 06 October 2024 22:49

perlvars.h: remove extraneous semicolon

None of the other PERLVARI declarations adds an extra semicolon,
so don't put one on the new shutdownhook either.  Removing it
prevents the following compiler message on VMS:

PERLVARI(G, shutdownhook, shutdown_proc_t, &Perl_noshutdownhook);
................................................................^
%CC-I-EXTRASEMI, Extraneous semicolon.
at line number 387 in file DKA0:[CRAIG.blead]perlvars.h;1

The message doesn't cause compile failures in and of itself, but
it pollutes the output of probes in some extensions and causes
capability detection to go off the rails in, for example,
Time::HiRes.

(dxvi) 13 great CPAN modules released last week

r/perl

Published by /u/niceperl on Sunday 06 October 2024 16:56

(dxvi) 13 great CPAN modules released last week

Niceperl

Published by Unknown on Sunday 06 October 2024 18:55

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::perlbrew - Manage perl installations in your $HOME
    • Version: 1.00 on 2024-10-04, with 178 votes
    • Previous CPAN version: 0.99 was 27 days before
    • Author: GUGOD
  2. Catmandu - a data toolkit
    • Version: 1.2022 on 2024-09-29, with 23 votes
    • Previous CPAN version: 1.2021 was 10 months, 23 days before
    • Author: HOCHSTEN
  3. Convert::Binary::C - Binary Data Conversion using C Types
    • Version: 0.85 on 2024-10-01, with 14 votes
    • Previous CPAN version: 0.84 was 3 years, 10 months, 8 days before
    • Author: MHX
  4. Data::DPath - DPath is not XPath!
    • Version: 0.60 on 2024-09-29, with 13 votes
    • Previous CPAN version: 0.59 was 1 year, 2 months, 5 days before
    • Author: SCHWIGON
  5. DateTime::Format::Flexible - DateTime::Format::Flexible - Flexibly parse strings and turn them into DateTime objects.
    • Version: 0.35 on 2024-10-06, with 14 votes
    • Previous CPAN version: 0.34 was 3 years, 2 months, 30 days before
    • Author: THINC
  6. HTTP::BrowserDetect - Determine Web browser, version, and platform from an HTTP user agent string
    • Version: 3.41 on 2024-10-02, with 23 votes
    • Previous CPAN version: 3.40 was 11 months, 14 days before
    • Author: OALDERS
  7. meta - meta-programming API
    • Version: 0.010 on 2024-10-01, with 13 votes
    • Previous CPAN version: 0.009 was 18 days before
    • Author: PEVANS
  8. Modern::Perl - enable all of the features of Modern Perl with one import
    • Version: 1.20241001 on 2024-10-01, with 51 votes
    • Previous CPAN version: 1.20240120 was 8 months, 12 days before
    • Author: CHROMATIC
  9. PDL - Perl Data Language
    • Version: 2.093 on 2024-09-29, with 58 votes
    • Previous CPAN version: 2.019 was 6 years, 4 months, 24 days before
    • Author: ETJ
  10. PerlPowerTools - BSD utilities written in pure Perl
    • Version: 1.047 on 2024-09-30, with 39 votes
    • Previous CPAN version: 1.046 was 2 months, 19 days before
    • Author: BRIANDFOY
  11. SPVM - The SPVM Language
    • Version: 0.990016 on 2024-10-04, with 33 votes
    • Previous CPAN version: 0.990012 was 8 days before
    • Author: KIMOTO
  12. Syntax::Construct - Explicitly state which non-feature constructs are used in the code.
    • Version: 1.038 on 2024-10-01, with 13 votes
    • Previous CPAN version: 1.037 was 3 months, 11 days before
    • Author: CHOROBA
  13. Type::Tiny - tiny, yet Moo(se)-compatible type constraint
    • Version: 2.006000 on 2024-09-29, with 140 votes
    • Previous CPAN version: 2.004000 was 1 year, 5 months, 24 days before
    • Author: TOBYINK

(dxci) metacpan weekly report - Parallel::ForkManager

Niceperl

Published by Unknown on Sunday 06 October 2024 18:53

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

Week's winner (+3): Parallel::ForkManager 

Build date: 2024/10/06 16:52:41 GMT


Clicked for first time:


Increasing its reputation:

(dcxix) stackoverflow perl report

Niceperl

Published by Unknown on Sunday 06 October 2024 18:52

Perl Community Conference Winter 2024

r/perl

Published by /u/ReplacementSlight413 on Sunday 06 October 2024 03:21

Perl Community Conference Winter 2024

When: December 18th (on the day of the 37th Birthday of Perl)

Where : Virtual

Dress Code : Whatever you want

Price : FREE

How to join : sign up for the mailing list (QR in image), or https://perlcommunity.org/science/#mailing_list)

Wanna know more : https://science.perlcommunity.org/spj#top

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

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

Part 1: Third Maximum

You are given an array of integers, @ints. Write a script to find the third distinct maximum in the given array. If a third maximum doesn’t exist then return the maximum number.

The majority of the work can be done in a couple of lines. We need only sort the distinct integers in the list and then return either the third largest number or, if none exists, the largest.

sort and return the third largest (or just the largest) 1 ⟩≡


sub third_maximum{
my %h;
do{ $h{$_} = undef } for @_;
my @sorted = sort {$b <=> $a} keys %h;
return $sorted[2] if @sorted >= 3;
return $sorted[0];
}

Fragment referenced in 2.

The rest of the code just tests this function.

"ch-1.pl" 2


preamble 3
sort and return the third largest (or just the largest) 1
main 4

preamble 3 ⟩≡


use v5.40;

Fragment referenced in 2, 9.

main 4 ⟩≡


MAIN:{
say third_maximum 5, 6, 4, 1;
say third_maximum 4, 5;
say third_maximum 1, 2, 2, 3;
}

Fragment referenced in 2.

Sample Run
$ perl perl/ch-1.pl 
4 
5 
1
    

Part 2: Jumbled Letters

Your task is to write a program that takes English text as its input and outputs a jumbled version

The rules for jumbling are given as follows:

  1. The first and last letter of every word must stay the same.
  2. The remaining letters in the word are scrambled in a random order (if that happens to be the original order, that is OK).
  3. Whitespace, punctuation, and capitalization must stay the same.
  4. The order of words does not change, only the letters inside the word.

Looking closer at these rules the main thing we need to concern ourselves with is jumbling the letters with the exception of the first and last. The use of map will ensure the words are processed in order. To make sure the first/last letters are unchanged also depends on detecting punctuation.

Punctuation is determined by a regex. We’ll keep track of the locations so we can add them back later, after jumbling.

strip punctuation 5 ⟩≡


my $stripped = [];
my $punctuation = [];
do{
$punctuation->[$_] = $w->[$_] if $w->[$_] =~ m/[[:punct:]]/;
push @{$stripped}, $w->[$_] if $w->[$_] !~ m/[[:punct:]]/;
} for 0 .. @{$w} - 1;

Fragment referenced in 8.

Defines: $punctuation 7, $stripped 6, 7.

Uses: $w 8.

Now that we have the punctuation accounted for let’s do the jumble. We’ll do this by generating permutations and randomly select one.

permutate the letters 6 ⟩≡


my $p = Algorithm::Permute->new(
[@{$stripped}[1 .. @{$stripped} - 2]]
);
my @p;
if(@{$stripped} > 2){
my @r = $p->next();
{
push @p, [@r];
@r = $p->next();
redo if @r;
}
$stripped = [$stripped->[0] ,
@{$p[rand @p]} ,
$stripped->[@{$stripped} - 1]];
}
$stripped = join q//, @{$stripped};

Fragment referenced in 8.

Uses: $stripped 5.

Finally, add the punctuation back in.

add punctuation back 7 ⟩≡


do{
substr $stripped, $_, 0, $punctuation->[$_]
if $punctuation->[$_];
} for 0 .. @{$punctuation} - 1;
$stripped . q/ /;

Fragment referenced in 8.

Uses: $punctuation 5, $stripped 5.

jumble the list of words 8 ⟩≡


sub jumble{
return map {
my $w = [split //, $_];
strip punctuation 5
permutate the letters 6
add punctuation back 7
} @_;
}

Fragment referenced in 9.

Defines: $w 5.

The rest of the code drives some tests.

"ch-2.pl" 9


preamble 3
use Algorithm::Permute;
jumble the list of words 8
main 10

main 10 ⟩≡


MAIN:{
say q/in the ASCII range match all non-controls./;
say jumble qw/in the ASCII range match all non-controls./;
say q//;
say q/This handy module makes performing permutation.../;
say jumble qw/This handy module makes performing permutation.../;
}

Fragment referenced in 9.

Sample Run
$ perl perl/ch-2.pl 
in the ASCII range match all non-controls. 
in the AISCI range macth all non-rloncots. 
 
This handy module makes performing permutation... 
Tihs handy mloude mkaes prifnremog prtaoimetun...
    

References

The Weekly Challenge 289
Generated Code


Paul writes:

With the 5.40 release well out of the way, and freed from my PSC commitments, I managed to find a bit more time this month to actually write some useful code.

Hours:

  • 2 = Improvements to op_dump() for custom operators

    • https://github.com/Perl/perl5/pull/22572
  • 1 = Improvements to op_dump() on existing UNOP_AUX operators

    • https://github.com/Perl/perl5/pull/22573
  • 11 = Additions to meta module: various "list"-type methods, set_prototype + set_subname on metasubroutines, add_named_sub helper method, is_class + is_method

    • https://metacpan.org/release/PEVANS/meta-0.009/source/Changes#L3
    • https://metacpan.org/release/PEVANS/meta-0.009/source/Changes#L12

Total: 14 hours

Thank you for the fundraising at YAPC::Hiroshima in Japan

Perl Foundation News

Published by Makoto Nozaki on Friday 04 October 2024 08:00

The Japan Perl Association made a generous donation to The Perl and Raku Foundation following their fundraising activity at YAPC::Hiroshima (article link). Here is a thank you message from Olaf Adler:

Thank you from TPF!

Japanese translation below:

日本語抄訳

こんにちは。Olaf Alderと申します。The Perl Foundationで後援者様向け広報の担当をしています。今日は日本のPerlコミュニティの皆様に感謝の意を表したく、ご連絡差し上げました。

Japan Perl AssociationとYAPC::Japanの皆様には、長年にわたるご支援を誠に「ありがとう」ございます。特に先日のYAPC::Hiroshimaの大盛況をお祝い申し上げます。写真で見た酒樽募金箱は印象的で、今後、私は日本酒を飲むたびにこのイベントを思い出すでしょう。

YAPCの継続的な成功は素晴らしいです。日本チームの秘訣を世界に伝えてほしいと願っています。私たちも多くを学びたいと思います。

Japan Perl AssociationはThe Perl Foundationの大切なパートナーです。今後とも協力し、Perlの発展に努めましょう。YAPC::Hakodateの盛会をお祈りしています。ありがとうございます!

Debugging Perl Scripts: Tools and Techniques

Perl on Medium

Published by Mayur Koshti on Wednesday 02 October 2024 16:07

Perl debugging tools and techniques to make debugging more manageable.

(dxv) 5 great CPAN modules released last week

Niceperl

Published by Unknown on Saturday 28 September 2024 22:40

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::cpm - a fast CPAN module installer
    • Version: 0.997018 on 2024-09-23, with 72 votes
    • Previous CPAN version: 0.997017 was 4 months, 25 days before
    • Author: SKAJI
  2. Mozilla::CA - Mozilla's CA cert bundle in PEM format
    • Version: 20240924 on 2024-09-24, with 19 votes
    • Previous CPAN version: 20240730 was 1 month, 25 days before
    • Author: LWP
  3. Plack::Middleware::Session - Middleware for session management
    • Version: 0.34 on 2024-09-23, with 16 votes
    • Previous CPAN version: 0.33 was 5 years, 6 months, 14 days before
    • Author: MIYAGAWA
  4. SPVM - The SPVM Language
    • Version: 0.990012 on 2024-09-26, with 33 votes
    • Previous CPAN version: 0.990010 was 8 days before
    • Author: KIMOTO
  5. XML::Hash::XS - Simple and fast hash to XML and XML to hash conversion written in C
    • Version: 0.57 on 2024-09-27, with 12 votes
    • Previous CPAN version: 0.56 was 3 years, 7 months, 14 days before
    • Author: YOREEK

my problems with CP2077 (and lots of RPGs)

rjbs forgot what he was saying

Published by Ricardo Signes on Saturday 28 September 2024 12:00

When Cyberpunk 2077 was announced, I was really excited. The teaser for it looked exactly like the Cyberpunk 2020 RPG that I’d like so much when I was a kid. When it came out, I tried it and it was a mess. Later, I heard they worked out lots of the problems, and I went back and I’ve been playing it. It still looks just about perfect, and gets lots of things right. It feels like a really good adaptation of Cyberpunk 2020. There are a lot of bugs and interface issues, still, but I don’t want to write about those, because it’s boring.

My problem is that the world of 2077 seems to have changed zero since 2013. From 1990 to 2013, in twenty three years: the USA collapses, space colonization (of the moon and Mars) begins in earnest, cybernetic prosthesis and mind uploading become practical, European nations collapse and reform, and powerful artificial general intelligence is developed. It’s an incredible amount of change to the world for twenty three years. Think back to 2001. How much has the world changed? Some, for sure, but really nothing like Cyberpunk proposes. That’s okay, because Cyberpunk is a game that proposes a world where everything is in a state of constant upheaval. But sixty five years later, the world hasn’t changed any further.

My problem is that CP2077 keeps reminding me of something that often bugged me about RPGs in the ’90s. Back then, I had a mailing list with some friends who were into RPGs. It was called “RPG Theory”, and that’s what we talked about. Here’s a (lightly edited) section of a post I made in August 2000, with the subject “Metaplot, Setting, Freedom, and Flavor”:


A role-playing game (RPG) is an interactive story-game created by a Game Designer, revolving mostly (although not exclusively) around the actions of Player Characters (PCs) largely told and entirely adjudicated by the Game Master (GM).

The game can be roughly defined by its theme, setting, and rules.

The game’s theme is composed of its mood, tone, and possibly an overall moral or message. The necessity of a particular mood to a game is hard to define. While slight variation is clearly possible (e.g. Vampire games centered chiefly around Humanitas or Jyhad), it may be that vast changes are not. (A Vampire game centered around fighting robots from Mars, or in the style of Paranoia.) I leave this question to the philosophers.

The games’s setting is the world in which the game takes place. This world exists in equilibrium or stasis. It is clearly not frozen in one moment, but it is frozen in one period. One can look at Casablanca and see a setting that is active, but also frozen. From the beginning to the end of the description (that is, the movie itself), the setting does not change. Only the characters change and take action.

Setting is the perogative of the Game Designer. They write the game’s chief book or books, which contain as basic description of rules and setting.

The perogative of the Player Character, chiefly and above all else, is action. Actions are easy to understand. When a PC speaks to another PC, shoots an NPC, or detonates a nucelar device, these are actions. They are undertaken by the PC as in-character (IC) tasks, generally with the implicit permission of the Game Master, which can use IC means to stop them, but will rarely rule out-of-hand that an attempt is impossible.

The perogative of the Game Master, chiefly and above all else, is motion. Motion is action taken by the setting. While the setting, as initially described, is static, during the course of the game it acts. This motion can be subtle: gangs working for the city’s mayor begin to muscle in on the PCs’ operation, which had in the Prelude (pre-game ‘time’) existed in equilibrium. It can also be drastic: all the women in America begin to grow wings. Through motion, the GM punctuates the equilibrium of the setting, communicates the theme, and forces the PCs to take action.

That is a campaign. (Or Chronicle, or Session, whatever.)

Metaplot is the superimposition of the Game Designer’s campaign onto the GM’s campaign. (The Game Designer, in his off time, presumably is able to act also as a GM.) The Game Designer’s motion must be accounted for by the Game Master, and this reduces his ability to communicate theme and act effectively. Or, at least, this is how many GMs perceive the problem. We could call the metaplot “metamotion.” (It is run by the Designer as ‘metaGM’ and stars ‘metacharacters.’)

The Golden Rule, “the GM can do whatever they want”, gives GMs the option to ignore any part of the Game Designer’s ideas. Generally this applies to setting, but it can be extended to rules, theme, and (of course) metaplot.

On the other hand, the Game Designer knows that GMs are unlikely to abandon “canon” rules. So, the Game Designer insidiously (or blithely) incorporates new metaplot into new rules, making it impossible for one to exist without the other. Or, only slightly less insidiously, they release books of metaplot which also contain useful or required information that can be discounted, which merely means that the GM will pay for material that they do want, as well as material that they do not.


The Cyberpunk RPG had its own metaplot. Books came out once in a while telling you what was new in the world. Night City is seized by the Metal Wars. Elziabeth Kress becomes President of the United States. The Fourth Corporate Wars happen. These books were generally of the “less insidious” type above: the book would tell you about how Arasaka and Militech were warring over an African land grab, and also introduce new weapons and cyberware being used there. You could use that story as a basis for your game, or you could ignore it and give the players access to the cool new tech just for fun.

Of course, as the years go by, more and more of this metaplot builds up. New books are released that build on the story of the last ten books. It’s harder and harder to carve out your game’s Night City from the currently canonical one. Cyberpunk was hardly the worst offender (if you consider this an offense) in this area. I wrote my post about White Wolf’s World of Darkness, which started off by describing the game world as a moment in time, and ended up releasing an enormous list of books detailing monumental in-game events that crowded out the Game Master’s own ideas.

Anyway, Cyberpunk 2077 feels enormously encumbered by this problem. Johnny Silverhand has been part of the Cyberpunk story since the original Cyberpunk RPG (set in 2013). His activities help define the setting, not just in the setting’s past, but in its present and future. His actions are so significant as to constrain the motion of the game.

This just becomes bizarre when we’re not thinking about the seven years from CP 2013 to CP 2020, but the 57 years from CP 2020 to CP 2077. Johnny blows up Arasaka tower in 2022, and then vanishes for fifty years. When he shows up again, nothing has changed. The world of 2077 is, I would say, literally indistinguishable from that of 2022. It’s not because Johnny isn’t there to do stuff, but because it’s not an option to really decontextualize Johnny by having the setting change out from under him.

Johnny complains about some fan of his from fifty years ago who’s living in the past, but actually nothing has changed since then. Johnny isn’t a creature of the past, he’s just as relevant in 2077 as he was in 2022. This world of constant upheaval and instability has become incredibly reliable. In sixty years, nothing really changed. The protagonist can’t really change anything, either. They’re just there to experience the show.

I wish the game had been set in 2022. They could’ve just let us play as Johnny Silverhand, carrying out the raid on Arasaka. But this would’ve given us agency over a character whose actions belong to the game designer, or maybe one of their friends in the canonical campaign of the game. They couldn’t let us have that agency, so they gave us the lesser agency of V, who lets us see that Johnny’s actions had no consequence, and neither will ours.

All of this is why I basically always throw away the setting that comes with an RPG. Anything that limits my ability to create a dynamic world of my own is antithetical to my idea of being a game master. The way that CP 2077 reflects a world defined by the game designer’s favorite NPCs and their millieu just makes me sad.

List of new CPAN distributions – Aug 2024

Perlancar

Published by perlancar on Friday 27 September 2024 04:29

dist author abstract date
Acme-CPANModules-MultipleDispatch PERLANCAR List of modules to do smart matching 2024-08-18T00:05:41
Acme-CPANModules-UnixCommandVariants PERLANCAR List of various CLIs that are some variants of traditional Unix commands 2024-08-26T09:48:48
Acme-Free-API-ChuckNorris OODLER Perl API client for the Chuck Norris Quote API service, https://api.chucknorris.io. 2024-08-29T18:39:41
Acme-Free-API-Stonks OODLER Perl API client for the, top 50 stocks discussed on le'Reddit subeddit – r/Wallstreetbets, https://tradestie.com/apps/reddit/api/. 2024-08-30T16:21:46
Acme-Free-API-Ye OODLER Perl API client for the Kanye Rest Quote API service, https://kanye.rest/. 2024-08-28T16:39:49
App-BookmarkFeed SCHROEDER Create a RSS feed from Markdown files 2024-08-05T16:33:07
App-optex-mask UTASHIRO optex data masking module 2024-08-16T10:14:16
App-prefixcat PERLANCAR Like Unix `cat` but by default prefix each line with filename 2024-08-09T12:33:04
Ascii-Text LNATION module for generating ASCII text in various fonts and styles 2024-08-29T10:49:18
Autoconf-Template BIGFOOT autoconfiscation help scripts 2024-08-06T09:26:35
Bio-EnsEMBL ABECKER Bio::EnsEMBL – Ensembl Core API 2024-08-29T16:32:54
Business-ID-VehiclePlate PERLANCAR Parse Indonesian vehicle plate number 2024-08-07T00:05:46
Catalyst-Plugin-Profile-DBI-Log BIGPRESH Capture queries executed during a Catalyst route with DBI::Log 2024-08-29T23:41:08
Circle-Block CHENGYU the block module for Circle::Chain SDK 2024-08-29T06:33:17
Circle-Chain CHENGYU The great new Circle::Chain! 2024-08-29T02:33:58
Circle-Common CHENGYU the common module for Circle::Chain SDK 2024-08-29T06:31:49
Circle-User CHENGYU the user module for Circle::Chain SDK 2024-08-29T06:36:47
Circle-Wallet CHENGYU the circle chain SDK in PERL 2024-08-29T06:36:58
DBIx-Squirrel CPANIC A module for working with databases 2024-08-08T20:01:38
Dancer2-Session-DBI EPISODEIV DBI based session engine for Dancer 2024-08-29T13:55:42
DateTime-Locale-FromCLDR JDEGUEST DateTime Localised Data from Unicode CLDR 2024-08-01T22:59:44
Dist-Build-XS-Alien LEONT Dist::Build extension to use Alien modules. 2024-08-31T19:19:30
File-ShareDir-Tiny LEONT Locate per-dist and per-module shared files 2024-08-25T13:07:29
Github-ReleaseFetcher TEODESIAN Fetch either the latest or a particular named version of a file in a release from github 2024-08-13T22:09:19
IO-SocketAlarm NERDVANA Perform asynchronous actions when a socket changes status 2024-08-27T06:08:13
IPC-MicroSocket PEVANS minimal request/response or pub/sub mechanism 2024-08-05T13:49:53
JIRA-REST-Lite SHINGO Lightweight wrapper around Jira's REST API 2024-08-16T01:20:46
Langertha GETTY The clan of fierce vikings with axe and shield to AId your rAId 2024-08-03T20:56:05
Locale-Unicode-Data JDEGUEST Unicode CLDR SQL Data 2024-08-01T22:43:58
Map-Tube-Rome GDT Interface to the Rome tube map 2024-08-27T16:01:05
MetaCPAN-Pod-HTML HAARG Format Pod as HTML for MetaCPAN 2024-08-26T14:55:52
MooseX-JSONSchema GETTY Adding JSON Schema capabilities to your Moose class 2024-08-03T20:36:33
Net-OpenSSH-More TEODESIAN Net::OpenSSH submodule with many useful features 2024-08-09T00:03:26
Object-Pad-Operator-Of PEVANS access fields of other instances 2024-08-22T11:30:12
OpenFeature-SDK CATOUC OpenFeature SDK for Perl 2024-08-17T19:40:04
Plack-App-Catmandu-OAI NJFRANCK drop in replacement for Dancer::Plugin::Catmandu::OAI 2024-08-23T07:58:26
Protocol-Sys-Virt-Devel EHUELS Development helper for Protocol::Sys::Virt and its dependants 2024-08-31T20:48:14
Protocol-Sys-Virt EHUELS Transport independent implementation of the remote LibVirt protocol 2024-08-31T21:36:13
Regex-Common ARFREITAS Provide commonly requested regular expressions 2024-08-12T22:48:17
Rope-Cmd LNATION Command Line Applications via Rope 2024-08-30T20:00:03
RxPerl-Extras KARJALA extra operators for RxPerl 2024-08-06T10:18:15
Sah-SchemaBundle-DNS PERLANCAR Schemas related to DNS 2024-08-04T00:05:19
Sah-SchemaBundle-Data-Sah PERLANCAR Sah schemas related to Data::Sah 2024-08-11T00:06:03
Sah-SchemaBundle-DataSizeSpeed PERLANCAR Sah schemas related to data sizes & speeds (filesize, transfer speed, etc) 2024-08-02T21:50:19
SlapbirdAPM-Agent-Dancer2 RAWLEYFOW Agent software for the Perl application performance monitor, Slapbird. slapbirdapm.com 2024-08-25T20:49:02
SlapbirdAPM-Agent-Mojo RAWLEYFOW Agent software for the Perl application performance monitor, Slapbird. slapbirdapm.com 2024-08-09T21:00:04
SlapbirdAPM-Agent-Plack RAWLEYFOW A Plack agent software for the Perl application performance monitor, Slapbird. slapbirdapm.com 2024-08-18T02:37:49
Syntax-Keyword-Assert KFLY assert keyword for Perl 2024-08-14T13:53:23
Task-MemManager CHRISARG A memory allocator for low level code in Perl. 2024-08-25T23:42:18
Term-ANSI-Sprintf LNATION sprintf with ANSI colors 2024-08-25T09:46:37
Tk-PodViewer HANJE Simple ROText based pod viewer. 2024-08-20T20:06:36
kura KFLY Store constraints for Data::Checks, Type::Tiny, Moose and more. 2024-08-18T13:31:06

Stats

Number of new CPAN distributions this period: 52

Number of authors releasing new CPAN distributions this period: 29

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 7
2 CHENGYU 5
3 RAWLEYFOW 3
4 LNATION 3
5 OODLER 3
6 LEONT 2
7 TEODESIAN 2
8 JDEGUEST 2
9 GETTY 2
10 KFLY 2
11 PEVANS 2
12 EHUELS 2
13 EPISODEIV 1
14 SCHROEDER 1
15 NERDVANA 1
16 BIGFOOT 1
17 CHRISARG 1
18 ABECKER 1
19 SHINGO 1
20 KARJALA 1
21 BIGPRESH 1
22 NJFRANCK 1
23 ARFREITAS 1
24 HAARG 1
25 HANJE 1
26 GDT 1
27 UTASHIRO 1
28 CPANIC 1
29 CATOUC 1

List of new CPAN distributions – Jul 2024

Perlancar

Published by perlancar on Friday 27 September 2024 04:28

dist author abstract date
Acme-CPANModules-ModifiedHashes PERLANCAR List of modules that provide hashes with modified behaviors 2024-07-13T02:14:33
App-GeometryUtils PERLANCAR Utilities related to geometry 2024-07-07T00:05:12
App-LastStats DAVECROSS A module to fetch and display Last.fm statistics 2024-07-28T17:34:18
App-PerlGzipScript SKAJI Gzip perl scripts to reduce their file size 2024-07-20T12:49:29
App-YtDlpUtils PERLANCAR Utilities (mostly wrappers) related to yt-dlp 2024-07-10T02:59:34
Astro-MoonPhase-Simple BLIAKO Calculate the phase of the Moon on a given time without too much blah blah 2024-07-14T14:14:36
Audio-Cuefile-Libcue GREGK Perl interface to the libcue cuesheet reading library 2024-07-19T19:43:23
Bencher-ScenarioBundle-SmartMatch PERLANCAR Scenarios to benchmark switch & smartmatch in Perl 2024-07-03T09:45:27
CVSS GDT CVSS (Common Vulnerability Scoring System) command line interface 2024-07-30T22:11:37
Catmandu-Store-OpenSearch NJFRANCK A searchable store backed by Opensearch 2024-07-03T07:23:38
Consumer-NonBlock EXODIST Send data between processes without blocking. 2024-07-02T19:53:48
Dancer2-Plugin-NYTProf GEEKRUTH NYTProf, in your Dancer2 application! 2024-07-02T13:03:01
Data-LnArray-XS LNATION Arrays 2024-07-12T09:58:12
Data-Random-Person SKIM Generate random person. 2024-07-05T00:10:57
Exercises-API NOBUNAGA API Ninja's Exercises API 2024-07-02T19:49:44
Extender DOMERO Dynamically enhance Perl objects with additional methods from other modules or custom subroutines 2024-07-17T10:06:50
Kanboard-API BARBARITO A Perl interface to the Kanboard API 2024-07-28T23:46:12
KelpX-Controller BRTASTIC Base custom controller for Kelp 2024-07-08T14:43:24
MIDI-RtMidi-ScorePlayer GENE Play a MIDI score in real-time 2024-07-10T23:51:51
Math-GSL-Alien HAKONH Easy installation of the GSL shared library 2024-07-17T09:42:10
Number-Iterator-XS LNATION iterate numbers faster 2024-07-26T03:56:33
OpenMP OODLER Metapackage for using OpenMP in Perl 2024-07-19T21:12:29
Perl-PrereqScanner-Scanner-DistBuild LEONT scan for Dist::Build dependencies 2024-07-12T12:03:35
Plack-App-Catmandu-SRU NJFRANCK drop in replacement for Dancer::Plugin::Catmandu::SRU 2024-07-30T09:27:07
SPVM-Resource-Eigen KIMOTO Resource for C++ Eigen library 2024-07-16T23:56:40
Sah-SchemaBundle-Country PERLANCAR Various Sah schemas related to country codes/names 2024-07-14T00:05:31
Sah-SchemaBundle-Currency PERLANCAR Various Sah currency schemas 2024-07-21T00:06:11
Sah-SchemaBundle-DBI PERLANCAR Schemas related to DBI 2024-07-28T00:06:12
Shannon-Entropy-XS LNATION Calculate the Shannon entropy H of a given input string faster. 2024-07-18T19:43:55
Slack-BlockKit RJBS a toolkit for building BlockKit blocks for Slack 2024-07-04T01:51:26
String-Mask-XS LNATION mask sensitive data faster 2024-07-03T21:44:29
Syntax-Operator-Is PEVANS match operator using Data::Checks constraints 2024-07-08T14:59:03
TableData-Business-ID-Kemenkes-RDA PERLANCAR Indonesian RDA (AKG, Angka Kecukupan Gizi) 2024-07-02T03:05:09
Text-Schmutz RRWO You̇r screen is quiṭe dirty, please cleȧn it. 2024-07-11T22:41:24
Text-Template-Tiny JV Variable substituting template processor 2024-07-05T11:10:37
Tk-Terminal HANJE Running system commands in a Tk::Text widget. 2024-07-03T09:24:21
Tradestie-WSBetsAPI NOBUNAGA Tradestie's Wallstreet Bets API 2024-07-01T19:57:16
WebService-GrowthBook DERIV 2024-07-02T11:17:20
Whelk BRTASTIC A friendly API framework based on Kelp 2024-07-03T13:59:32
Win32-Console-DotNet BRICKPOOL Win32 Console .NET interface 2024-07-29T07:05:25
Win32API-RecentFiles CORION recently accessed file API functions on Windows 2024-07-29T18:16:24

Stats

Number of new CPAN distributions this period: 41

Number of authors releasing new CPAN distributions this period: 28

Authors by number of new CPAN distributions this period:

No Author Distributions
1 PERLANCAR 8
2 LNATION 4
3 NJFRANCK 2
4 BRTASTIC 2
5 NOBUNAGA 2
6 OODLER 1
7 GENE 1
8 RJBS 1
9 SKAJI 1
10 DAVECROSS 1
11 GREGK 1
12 LEONT 1
13 GEEKRUTH 1
14 BARBARITO 1
15 EXODIST 1
16 HAKONH 1
17 GDT 1
18 DOMERO 1
19 BRICKPOOL 1
20 HANJE 1
21 SKIM 1
22 RRWO 1
23 JV 1
24 CORION 1
25 DERIV 1
26 BLIAKO 1
27 PEVANS 1
28 KIMOTO 1

Perl: The Language of Text Manipulation and Beyond

Perl on Medium

Published by Mwenda Kelvin on Thursday 26 September 2024 21:01

Explore how Perl, the language of text manipulation, empowers developers with powerful features for scripting, automation, and robust data…

Why Perl Is Faster Than Python

Perl on Medium

Published by Mayur Koshti on Thursday 26 September 2024 06:20

Perl can outperform Python, especially in tasks involving text manipulation, regular expressions, and certain I/O-bound operations.

Dancing with Copilot Workspace

Perl Hacks

Published by Dave Cross on Sunday 22 September 2024 16:00

Over the last few months, I’ve been dabbling in using AI to generate or improve code. I have a subscription to GitHub Copilot and I’m finding it a really useful tool for increasing my productivity. Copilot comes in several different flavours, and I’ve been making particular use of a couple of them.

  • Copilot Autocomplete was the first Copilot tool that GitHub released. Once you’ve configured your editor to use it, the AI will read the file you’re working on and will monitor what you’re typing. When it thinks it knows what you’re doing and what comes next, it will display a suggestion for the next chunk of code and if you like what you see, you can just hit the tab key to accept it. I’ve been pleasantly surprised by how well it does. I’ve had cases where I’ve just typed the name of a method and it has autocompleted the code for me.
  • Copilot Chat was the next version to be released. This is a chat box that sits alongside your code where you can talk to the AI about what you’re doing and ask it for suggestions. This is great for taking on larger projects. I’ve found it particularly useful for working on front-end code. I can usually make CSS and Javascript do what I want, but asking Copilot for suggestions makes me an order of magnitude quicker.

Those two tools alone make me a more efficient programmer. And they’re well worth the $10 a month I pay for my Copilot subscription. But recently I was invited to the preview of Copilot Workspace. And that’s a whole new level. Copilot Workspace takes a GitHub issue as its input and returns a complete, multifile pull request that implements the required change. I’ve been playing with it for small tweaks, but I decided the time was right to do something more substantial. I planned to write an entire Dancer app by defining issues and asking Copilot to implement the code. Here’s what happened. You can follow along at the GitHub repo.

I decided I would start from the standard, automatically generated Dancer2 app. So I ran dancer2 gen -a Example and committed the output from that. It was then time for the first issue. I decided to start by adding (empty) routes for user registration and login. I opened the issue in the Copilot Workspace and asked the AI for some suggested code. It didn’t really understand the idea of empty routes – but the pull request seemed pretty good. I merged the PR and moved on to the next issue – to add basic registration and login screens. Again, the pull request did a little more than I asked for – adding a bit more registration and login logic – but the code was good.

As an aside, you’ll notice that the PRs are all correctly linked to the correct issues and contain substantial information about the changes. This is all generated by the AI.

For the next step, we needed a database table to store the users. I asked Copilot to use SQLite and it gave me what I wanted – once again, going above and beyond. For the first time, its overenthusiasm was slightly annoying, because it added some database code to store new users and I hadn’t told it that we would be using DBIx::Class. So that was the next issue and the next pull request. Note that the pull request even includes adding DBIx::Class to the requisites in Makefile.PL.

Time for some unit tests (ok, maybe the best time was a few PRs ago!). The issue description was simple – “Write unit tests for everything we have so far“. Maybe it was too simple – as this was the first time the AI seemed to struggle a bit. I was merging the PRs without really checking them and the PR introduced a lot of useful tests – but many of them failed. Part of the problem here is that (as far as I can see) Copilot Workspace has no way to run the code it produces – so it was guessing how well it was doing. It took a few iterations to get that right – it basically boiled down to the database schema not being loaded into the database before the tests were run. At times while we were working through these problems, I was reminded of someone (I think it was Simon Willison) describing an AI programming assistant as “an overconfident, overenthusiastic intern”. Luckily, unlike an intern, Copilot never gets annoyed with you telling it to try again and providing more and more information to help it get to the bottom of a problem.

After a while, we had a working test suite and were back on track.

So we were back at adding features to the application. I decided the next thing we needed was to display the logged-in user’s username and email address on the main page. That seemed simple enough and worked first time. About this time I was getting annoyed with the standard Dancer2 web page, so we removed most of that. Then I switched from Dancer’s default “simple” templating system to the Template Toolkit [issue / PR].

While we were tidying up the look and feel, we added login and logout buttons [issue / PR] and a register button on the logged out page [issue / PR]. This led to some more confusion for a while as logging out didn’t work. It turned out the AI had used outdated code to destroy the session and I had to get very specific before it would do the right thing [issue / PR].

We then added some more tests [issue / PR], displayed registration and login errors [issue / PR] and ensured we were storing the passwords in encrypted form (to be honest, I’m slightly disappointed that the AI didn’t do that by default) [issue / PR].

At this point (and I don’t know why I didn’t do it sooner), we replaced the UI with something using Bootstrap [issue / PR]. That led to a bit more tweaking of the buttons [issue / PR].

At this point, I had basically got to where I wanted to be. I had an app that didn’t do anything useful, but let you register, login and log out. And I’d done it all pretty quickly and without writing very much code.

Then I decided to push it too far.

The thing that I actually wanted to achieve at this point was to add social registration and login to the site. I created an issue – Allow users to register and login using a Google account – and Copilot gave me some code. But at this point, it’s not just about code. You also need to configure stuff at Google in order to get this working. And, while Copilot gave me some information about what I needed to do, I haven’t yet been able to get it working. This is a good example of the limitations of AI-powered programming. It’s great at generating code, but (so far, at least) not so good at keeping up to date with how to interface with external systems. Oh, and there’s the problem we saw earlier about it not actually running the tests.

So, how do I think the experiment went? I was impressed. There was a lot of code generated that was as good or better than I would have written myself. There are certainly the problems that I mentioned above, but this stuff is improving at such an incredible rate that I really can’t see those problems still existing in a year.

I’ve started using Copilot Workspace for a lot more of my projects. And I’m happy with the results I’ve got.

What about you? Have you used any version of Copilot to help with your coding? How successful has it been?

The post Dancing with Copilot Workspace appeared first on Perl Hacks.

(dxiv) 14 great CPAN modules released last week

Niceperl

Published by Unknown on Saturday 21 September 2024 21:48

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

  1. DBD::mysql - A MySQL driver for the Perl5 Database Interface (DBI)
    • Version: 5.009 on 2024-09-19, with 56 votes
    • Previous CPAN version: 5.008 was 1 month, 20 days before
    • Author: DVEEDEN
  2. DBIx::Lite - Chained and minimal ORM
    • Version: 0.35 on 2024-09-18, with 26 votes
    • Previous CPAN version: 0.34 was 6 days before
    • Author: AAR
  3. Feersum - A PSGI engine for Perl based on EV/libev
    • Version: 1.503 on 2024-09-17, with 12 votes
    • Previous CPAN version: 1.502 was 8 days before
    • Author: EGOR
  4. Future::AsyncAwait - deferred subroutine syntax for futures
    • Version: 0.69 on 2024-09-18, with 48 votes
    • Previous CPAN version: 0.68 was 20 days before
    • Author: PEVANS
  5. Minion - Job queue
    • Version: 10.31 on 2024-09-21, with 106 votes
    • Previous CPAN version: 10.30 was 3 months, 16 days before
    • Author: SRI
  6. Module::CoreList - what modules shipped with versions of perl
    • Version: 5.20240920 on 2024-09-20, with 43 votes
    • Previous CPAN version: 5.20240829 was 22 days before
    • Author: BINGOS
  7. Net::DNS - Perl Interface to the Domain Name System
    • Version: 1.47 on 2024-09-18, with 27 votes
    • Previous CPAN version: 1.46 was 30 days before
    • Author: NLNETLABS
  8. Object::Pad - a simple syntax for lexical field-based objects
    • Version: 0.814 on 2024-09-20, with 45 votes
    • Previous CPAN version: 0.813 was 17 days before
    • Author: PEVANS
  9. Sub::Util - Common Scalar and List utility subroutines
    • Version: 1.66 on 2024-09-19, with 170 votes
    • Previous CPAN version: 1.65 was 1 month, 13 days before
    • Author: PEVANS
  10. SPVM - The SPVM Language
    • Version: 0.990010 on 2024-09-18, with 33 votes
    • Previous CPAN version: 0.990009 was 5 days before
    • Author: KIMOTO
  11. Test::Simple - Basic utilities for writing tests.
    • Version: 1.302204 on 2024-09-15, with 190 votes
    • Previous CPAN version: 1.302203 was 10 days before
    • Author: EXODIST
  12. Test::Vars - Detects unused variables in perl modules
    • Version: 0.017 on 2024-09-16, with 12 votes
    • Previous CPAN version: 0.015 was 3 years, 4 months, 26 days before
    • Author: JKEENAN
  13. WWW::Mechanize - Handy web browsing in a Perl object
    • Version: 2.19 on 2024-09-16, with 101 votes
    • Previous CPAN version: 2.18 was 7 months, 17 days before
    • Author: OALDERS
  14. YAML::LibYAML - Perl YAML Serialization using XS and libyaml
    • Version: v0.902.0 on 2024-09-20, with 55 votes
    • Previous CPAN version: v0.901.0 was 14 days before
    • Author: TINITA

Taking VelociPerl for a ride

Killing-It-with-PERL

Published on Saturday 21 September 2024 00:00

VelociPerl is a closed source fork of Perl that claims performance gains of 45% over the stock (“your dad’s Perl” in their parlance) based on some public benchmarks. I will not go into how they achieved this performance boost, or why they released it as closed source, or even “but why the heck did you release it as closed source?”, as you can follow the Reddit discussion. However, even a modest speed gain may be useful in some applications, so I decided to dive in a a little bit deeper.

Some of the benchmarks are numerical e.g. a linear system solver, generating random numbers but others are more relevant to garden variety Perl tasks, e.g. generating objects as blessed hashes. These tasks may appear in the context of some applications, so it is nice to know there are some benefits, but why not come up with a composite task and benchmark it? My usage of Perl involves random number generation, operations on tasks, creation of objects, string concatenation and function calling, so I figured there should be a way to combine all of them together and take VelociPerl for a ride.

Consider the following code that executes two benchmarks:

  • Generating a Hash (in which the keys are random strings and the values are obtained as a blessed reference to an anonymous scalar)
  • Accessing the said hash
use v5.38;
use Benchmark qw(timethis);    # for benchmarking

my $Length_of_accesstest = 1_000_000;
my $Length_of_gentest=100_000;
my $class = 'HashingAround';    
sub generate_random_string(@alphabet) {
    my $len = scalar @alphabet;
    my $length = int( rand(100) ) + 1;    # random length between 1 and 100
    return join '', @alphabet[ map { rand  $len } 1 .. $length ];
}

my %hash_of_seqs;

for ( 1 .. $Length_of_accesstest ) {
    my $key = generate_random_string(('A' .. 'Z'));
    my $val = bless \do { my $anon_scalar = $key }, $class;
    $hash_of_seqs{$key} = $val;
}

say "=" x 80;
say "\tTiming hash access using timethis";
timethis(
    20,
    sub {
        while ( my ( $seq_id, $seq ) = each %hash_of_seqs ) {
            ## worthless access to seq to force the sequence to be copied in memory
            my $sequence = $seq;
        }
    }
);

say "=" x 80;
say "\tTiming hash generation using timethis";
timethis(
    10,
    sub {
        my %hash_of_seqs;
        for ( 1 .. $Length_of_gentest ) {
    my $key = generate_random_string(('A' .. 'Z'));
    my $val = bless \do { my $anon_scalar = $key }, $class;
            $hash_of_seqs{$key} = $val;
        }
    }
);

To switch the Perl interpreter one simply changes the shebang line. In my oldish dual Xeon E5-2697 v4, I obtained the following results

  • Stock Perl : ```text (base) chrisarg@chrisarg-HP-Z840-Workstation:~/software-dev/velociperlHash$ ./testHash_speed.pl ================================================================================ Timing hash access using timethis timethis 20: 12 wallclock secs (11.61 usr + 0.00 sys = 11.61 CPU) @ 1.72/s (n=20) ================================================================================ Timing hash generation using timethis timethis 10: 12 wallclock secs (12.58 usr + 0.01 sys = 12.59 CPU) @ 0.79/s (n=10)

* **VelociPerl** :
```text
(base) chrisarg@chrisarg-HP-Z840-Workstation:~/software-dev/velociperlHash$ ./testHash_speed_vperl.pl 
================================================================================
	Timing hash access using timethis
timethis 20: 11 wallclock secs (11.04 usr +  0.00 sys = 11.04 CPU) @  1.81/s (n=20)
================================================================================
	Timing hash generation using timethis
timethis 10: 10 wallclock secs ( 9.80 usr +  0.01 sys =  9.81 CPU) @  1.02/s (n=10)

Walking the hash was not materially different between the two interpreters, but the more compute intense task that involved random numbers, string operation and blessing of objects was ~30% faster. This gain may or may not justify using a closed source version of Perl to you. But it is worth noting that one may be able to tweak the compilation of the Perl source (which appears to be a major source of the claimed gains) to generate faster executing Perl code. Perhaps an approach that one can try with an open sourced fork?

Maintaining Perl 5 Core (Dave Mitchell): August 2024

Perl Foundation News

Published by alh on Saturday 14 September 2024 08:15


Dave writes:

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

I spent most of last month doing various bits of code refactoring on Extutils::ParseXS, as a precursor to adding reference-counted stack (PERL_RC_STACK) abilities to XS.

The code for Extutils::ParseXS is exceedingly unpleasant, with for example the main method, process_file() being over 1700 lines of code. It's a random mishmash of bolted-on half-baked ideas, with no sensible separation of, for example, parsing and code generation. I'm trying to make it more sane.

SUMMARY: * 0:15 fix Deparse test failures * 8:49 process p5p mailbox * 2:35 reduce smoke failures * 60:13 refactor Extutils::ParseXS * 6:01 rework XS documentation

Total:

  • 77:53 TOTAL (HH::MM)

TL;DR

I found out how to retrieve the ntSecurityDescriptor in Active Directory, via LDAP.

Active Directory is a… beast and it’s not always easy to get what’s needed. This took me… some time.

One configuration that is supported for an account is the possibility to set a flag for preventing a user to change password. I’m not sure why there’s such a flag; I can only imagine that’s an easy way to lock an account (you just set a very random password, then prevent anyone from changing it).

There’s a promising flag PASSWD_CANT_CHANGE in userAccountControl, but alas:

You can’t assign this permission by directly modifying the UserAccountControl attribute. For information about how to set the permission programmatically, see the [Property flag descriptions][] section.

The link eventually lands us on page Modifying User Cannot Change Password (LDAP Provider), which is somehow helpful but not too much, because it includes code examples that assume the use of some Microsoft library for C++. I guess 🙄

Anyway, the page includes some interesting info:

  • the information that we’re after is in an Discretionary Access Control List (DACL)
  • it is included in property (/attribute) ntSecurityDescriptor in the LDAP record.

Only fact is that this attribute is nowhere to be found.

Wait a minute. What?!?

It turns out that depending on how you set the query parameters, this field will contain more or less information. By default it is supposed to contain everything, except that normal users are not supposed to see everything, so Active Directory does not include this attribute in the answer.

The trick consists in asking for less. This answer got me on the right track for a solution in Perl: we have to set the extension control LDAP_SERVER_SD_FLAGS_OID to a value that excludes the System Access Control List part from the answer, while keeping everything else. The answer also includes a quick and dirty way of building up the right value to pass for this control:

$sdFlags = 7;
...
   "value" => sprintf("%c%c%c%c%c", 48, 3, 2, 1, $sdFlags)

This even works in Perl, but it’s a bit too hackish and I’d like to know more.

This page contains the information I was after:

The LDAP_SERVER_SD_FLAGS_OID control is used with an LDAP Search request to control the portion of a Windows security descriptor to retrieve.

When sending this control to the DC, the controlValue field is set to the BER encoding of the following ASN.1 structure.

SDFlagsRequestValue ::= SEQUENCE {
    Flags    INTEGER
}

This makes it clearer the trick in the PHP code; it’s just a way to produce the BER encoding of the required data structure. In particular:

0x30 (48 decimal)    tag for a SEQUENCE
0x03 (3 decimal)     length of SEQUENCE (# of following octets)
    0X02 (2 decimal)     tag for an INTEGER
    0x01 (1 decimal)     length of INTEGER (# of following octets)
    0x07 ($sdFlags)      value of INTEGER

When using Perl, especially when using Net::LDAP, there’s a cleaner and more readable way of producing the same:

use Convert::ASN1;
use constant OWNER_SECURITY_INFORMATION => 0x01;
use constant GROUP_SECURITY_INFORMATION => 0x02;
use constant DACL_SECURITY_INFORMATION  => 0x04;
use constant SACL_SECURITY_INFORMATION  => 0x08;
my $asn = Convert::ASN1->new;
$asn->prepare(<<'END');
   SDFlagsRequestValue ::= SEQUENCE {
      Flags    INTEGER
   }
END
my $ldap_control_sd_flags = $asn->encode(Flags =>
     OWNER_SECURITY_INFORMATION
   | GROUP_SECURITY_INFORMATION
   | DACL_SECURITY_INFORMATION
);

Setting the control for the query is quite straightforward, as it’s part of the interface for the search method:

use Net::LDAP::Constant qw< LDAP_CONTROL_SD_FLAGS >;
use Net::LDAP::Control;
my $control = Net::LDAP::Control->new(
    critical => 1,
    type     => LDAP_CONTROL_SD_FLAGS,
    value    => $ldap_control_sd_flags,
);
...
my $res = $ldap->search(..., control => $control);
...

This should eventually give us the ntSecurityDescriptor we’re after (including the DACL), even when we’re not super-administrators.

Stay safe!