Interestingly, the Perl 5 and Perl 6 solutions to Challenge 24 task 1 in the Perl Weekly Challenge are identical.
Programming
Perl Weekly Challenge 12 – Euclid Numbers
This week’s Perl Weekly Challenge, problem 1, reads:
The numbers formed by adding one to the products of the smallest primes are called the Euclid Numbers (see wiki). Write a script that finds the smallest Euclid Number that is not prime. This challenge was proposed by Laurent Rosenfeld.
The first Euclid numbers are 3, 7, and 31. These are computed as follows:
We’ll take the first three prime numbers – 2, 3, and 5.
The corresponding Euclid number is the prime number multiplied by all the smaller prime numbers, with 1 added to it.
So the first one, 3, is just 2 (nothing to multiply it against) plus 1.
The second one is 3 * 2 plus 1, or 7.
The third one is 5 * 3 *2 + 1, which is 31.
How do you do this in code? Continue reading
Converting Decimal to Roman Numbers in Perl 6
This week’s (week 10) Perl Request Challenge, challenge 1, was:
Write a script to encode/decode Roman numerals. For example, given Roman numeral CCXLVI, it should return 246. Similarly, for decimal number 39, it should return XXXIX. Checkout wikipedia page for more informaiton.
For this blog, I’m going to talk about converting a decimal to a Roman numeral.
To start with, I read the Wikipedia page referenced in the challenge, and realized there were several different systems for writing Roman numerals – it wasn’t as standardized as I thought! That said, I stuck with the style used in the description of the challenge, specifically “subtractive” notation. Essentially, the symbols are written from the largest value to the smallest value, left to right, with no more than 3 of any symbol used. When four of a symbol would normally be used (for instance, IIII to mean 4), instead it would be written as IV, meaning one less than 4 (you see this because the smaller number is before the bigger number).
So that’s what I’ll talk about below – the part of the code that converts an integer to a Roman number.
Solving the Sparkpost Challenge
The Perl Weekly Challenge for week 9 includes an optional third challenge – essentially, use the Sparkpost service’s API to send an email. Sparkpost is a service that allows sending emails via an HTTP interface, just by posting a JSON form response.
I’ve noticed people have not known how to solve these API-usage challenges, so I will share my method of solving them, using Perl 6.
Anagrams – in O(N)
If you understand “big O” notation, skip on down to the “Solving Week 5 Problem 2” heading.
I’m going to discuss this using Perl 6, but I think an intermediate Perl 5 user will be able to figure out what the code does and how it would be able to be implemented in Perl 5.
“Big O” Notation
Most students of computer science have been exposed to “big O” notation. Essentially, algorithms can be classified by performance. N represents the size of the data being processed, while O() is shorthand for “execution time on the order of …”
Open Up Your Open Source Module – Part 4: Contributor Credit
This is Part 4 of a 5 part series. Links to other parts (as they become available) are below.
- Part 1: CONTRIBUTING File
- Part 2: TODO File
- Part 3: CODE_OF_CONDUCT File
- Part 4 (Below): Contributor Credit
- Part 5 (Future): BONUS TIPS!
We’ve previously talked about adding the CONTRIBUTING, TODO and CODE_OF_CONDUCT files. But how about giving contributors credit? This is a short, and easy, tip.
Open Up Your Open Source Module – Part 3: CODE_OF_CONDUCT File
This is Part 3 of a 5 part series. Links to other parts (as they become available) are below.
- Part 1: CONTRIBUTING File
- Part 2: TODO File
- Part 3 (Below): CODE_OF_CONDUCT File
- Part 4: Contributor Credit
- Part 5 (Future): BONUS TIPS!
We’ve previously talked about adding the CONTRIBUTING and TODO files, so now we’ll get to the post I’ve been dreading: the CODE_OF_CONDUCT file. I believe strongly in the value of codes of conduct, and think every project should have one.
So, why would I dread it?
Open Up Your Open Source Module – Part 2: TODO File
This is Part 2 of a 5 part series. Links to other parts (as they become available) are below.
- Part 1: CONTRIBUTING File
- Part 2 (Below): TODO File
- Part 3: CODE_OF_CONDUCT File
- Part 4: Contributor Credit
- Part 5 (Future): BONUS TIPS!
So, you’ve added a CONTRIBUTING file to your module (in part 1). That’s great! Now people know the ground rules for contributing to your module. But there is another thing you can do to encourage the contributions you want: Simply tell the potential developer what changes you might appreciate.
Open Up Your Open Source Module – Part 1: CONTRIBUTING File
You’ve written something awesome! You want to release it as open source software into the world. And, you hope other people will want to polish the rough edges, oil the squeaking hinge, and translate the help text into Klingon. Assuming that your module is interesting to people, how do you help them help you? I’ll give examples of how to do this in the context of Perl 5 modules, but they’ll work in other languages, too.
I talked about this in a lightning talk @ The Perl Conference 2018
But I also thought I could expand and organize my thoughts a bit better, so for the textually inclined, read on!
This is part one of a five part series. I’ll link them all here when they are up.
- Part 1 (Below): CONTRIBUTING File
- Part 2: TODO File
- Part 3: CODE_OF_CONDUCT File
- Part 4: Contributor Credit
- Part 5 (Future): BONUS TIPS!
Making PAR::Packer Work with RPM
I needed to distribute some RPMs with a PAR::Packer created (using pp) executable.
If you don’t know what PAR::Packer is, it is the incredibly awesome Perl 5 utility that allows you to create an executable that contains your Perl interpreter, your code, and any libraries you need. It’s basically one of the ways you have to escape dependency hell with Perl – you can use all the wonderful CPAN modules without fear. You can use the new features of recent versions of Perl (such as subroutine signatures and enhanced performance), without worrying about what version of Perl is installed on someone else’s machine. You don’t need to worry about missing core modules in Fedora and other platforms (Fedora is missing autodie – an essential module for lazy programmers). So building an archived executable is a great way to distribute Perl apps to people not comfortable with the Perl toolchain.
You can think of it like a Perl compiler (it’s not, but the distinction isn’t terribly important for this context).
It’s a somewhat finicky beast, and can take some effort to get it to package things the way you need them, but it’s a standard trick of the trade when I can’t just use perlbrew to build what I want on a machine. It certainly is a lot quicker to install a single executable than to compile and test hundreds of CPAN modules!
So, it seems natural to combine this with RPM. This way, users can install my stuff just by doing a simple rpm --install <file>.rpm – that’s awesome. Well, it would be, but building an RPM with a PAR::Packer built executable doesn’t actually work, at least not on Red Hat Enterprise Linux 5 (RHEL5) or RHEL6.
Let me explain….
Take this script, hello.pl:
#!/usr/bin/env perl use v5.22; # Use perl 5.22's features use strict; use warnings; use autodie; # This causes issues on Fedora out of the box MAIN: { say reverse (split //, "!dlroW olleH"); }
If I run it on most distributions, line 3 will give me an error (the OS Perl isn’t new enough). On Red Hat/Fedora installs, if I changed line 3 to support older perl interpreters, the inclusion of autodie in line 7 will error out, unless that module has already been installed.
For instance:
perldemo:demo$ ./hello.pl Perl v5.22.0 required--this is only v5.18.2, stopped at hello.pl line 3. BEGIN failed--compilation aborted at hello.pl line 3.
Of course it works fine when I use my local perl interpreter (a perlbrew-built 5.22.1):
perldemo:demo$ perl hello.pl Hello World!
So, I can create a packed executable, which runs great (at least on other systems with the same system libraries – the same limitations a an executable you dynamically link and build using C):
perldemo:demo$ pp -o hello hello.pl perldemo:demo$ ./hello Hello World!
Perfect! Note that I ran the executable hello, not hello.pl. The hello file is a self-contained executable that doesn’t depend on the system perl.
So what happens when I put this in an RPM package? I won’t go through the steps of building an RPM, but will let you see what error you will get when you try running the executable:
perldemo:demo$ ./hello Usage: ./hello [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ] ./hello [ -B|-b ] [-Ooutfile] src.par
What the heck? It’s expecting a PAR file to be passed to it – the PAR, or Perl ARchive, of course contains the perl interpreter, your code, and your modules – for some reason the file can’t find it.
You can duplicate this without RPM by using strip on the output of pp on Linux:
perldemo:demo$ pp -o hello hello.pl perldemo:demo$ ./hello Hello World! perldemo:demo$ strip ./hello perldemo:demo$ ./hello Usage: ./hello [ -Alib.par ] [ -Idir ] [ -Mmodule ] [ src.par ] [ program.pl ] ./hello [ -B|-b ] [-Ooutfile] src.par
What is going on? The strip removes debugging information and the like, but generally isn’t expected to change how your program runs – but in this case it seems to be removing a lot more. Running this same strip on OSX (Apple) is enlightening:
perldemo:demo$ strip hello /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip: the __LINKEDIT segment does not cover the end of the file (can't be processed) in: /Users/jmaslak/pp/hello perldemo:demo$ ./hello Hello World!
So it appears Macs won’t strip the archive out of the extraction executable produced by pp – but Linux has no problem happily stripping it.
It turns out that standard configurations of rpmbuild on at least RHEL5 and RHEL6 automatically strip all binaries in the binary package (that’s the “standard” package you would install).
So how do you disable this evil? It turns out it’s not easy. On RHEL6, you add this near the top of your SPEC file (the SPEC file rpmbuild uses to create the RPM):
%global __os_install_post %{nil}
Now, rpmbuild won’t strip the file. But this doesn’t help RHEL5. So I added another line, that did what I want (assuming I don’t need a debug package, which I don’t in this case):
%define debug_package %{nil} %global __os_install_post %{nil}
Sure enough, now my code does exactly what I want, even when I install the PAR executable via RPM:
perldemo:demo$ ./hello Hello World!
Whew!