This article discusses different aspects of Perl the Practical Extraction and Report Language. Perl is a very high level language for building, testing and automating software. It is a extension to GNU Coreutils and Bash with modular scripts in C like syntax. Common use cases are websites and test suites for example. Debian GNU/Linux uses it for package management. Embedded in C/C++ the size of Perl is bigger than Lua but smaller than Python. It has a regular expressions engine and supports UTF-8. A lot of additional modules are availbable in CPAN network. With Tk or Qt graphical user interfaces can be added.

Perl OOP programming

Perl has a very simple type system. Objects are usually represented by associative arrays with additional type information. Types in Perl are represented by packages. Inheritance is possible with subroutines but not data. If a subroutine is invoked as a method the callers object is added as a first argument. This objects reference can be used as hash key with caution. Once the object reference is used as a key the object may no more blessed because bless changes the scalar representation of the reference. The parents data may be necessary in the method but objects inherit only functions but there are no member variables. Inherited data is only availbale if its the same objects. The Object reference including parent data can be used as argument to the constructor. Then the parent constructor can be called with SUPER before the object is blessed. This is similar to a inplace constructor in C++ where the constructor gets a pointer to the memory. C++ calls parents constructor/destructor automatically but Perl calls only the destructor of objects package. Neither constructors nor destructors of a parent package are called in Perl. The parent constructor need to be called manually with SUPER. Below is a sample program. This calls parents constructor first and parent destructor last unlike C++.

# This programs calls constructor and destructor of parent and child
# Output:
# CHILD::new
# PARENT::new
# CHILD::DESTROY
# PARENT::DESTROY

package PARENT;
sub new {
    print __PACKAGE__.'::new';
    my $base = pop;
    bless $base, __PACKAGE__;
}
sub DESTROY {
    print __PACKAGE__.'::DESTROY';
}

package CHILD;
use parent -norequire, PARENT;
sub new {
    print __PACKAGE__.'::new';
    my $base = pop;
    __PACKAGE__->SUPER::new($base);
    bless $base, __PACKAGE__;
}

sub DESTROY {
    print __PACKAGE__.'::DESTROY';
    (pop)->SUPER::DESTROY();
}

local $_ = {};
CHILD->new($_);
die unless $_->isa(CHILD);
die unless $_->isa(PARENT);

Perl data types and default variables

Perl data types are scalar, array and hash. Perl has a default variable for each. The default variables are $_, @\_ and %_. In subroutines the default array @_ contains the function arguments. The default scalar can be used as a local temporary value. Many functions like print or match use the default scalar if there is no other argument. Global data is may be stored in the default hash %_. This hash object can be blessed for inheritence. If many packages use the default hash there can be problems with name conflicts. Thats why a convention of the structure is needed. One way is to use the package name as the first element in the hash. This adds some kind of encapsulation although data can be accessed globally. The syntax $_{(__PACKAGE__)} is more verbose but the local $\_ may be used as alias. This looks as a variant of Inside-out objects so Inside-out packages.

Modules provide more data types

Common data structures in a script language are scalar, arrays and dictionaries. However in practice data is not strict linear and hierachical. Thats why relational databases are necessary. Primary keys may consist of multiple scalars. Sometime there can be many to many relationships. Thats why relational databases are necessary. Perl has module for many database management systems. PostgreSQL or SQLIite for example. The DBD::SQLite::VirtualTable::PerlData module combines built in data types with SQL syntax.

Perl enables functional programming

Perl has a functional elements when used with default variables only. In pure functional languages there are no variables. Reducing the number of variables reduces complexity. A loop over array is simpler without indexes. Errors can occur at a higher level. Empty lists for example returned in a SQL selection.

# Using the return value of a ternary operator looks like functional programming
# it requires less braces and

local $_ = /PATTERN/
? do {"OK"}
: do {"FAIL"};


local $_ = do {
    if ( /PATTERN/ ) { "OK" }
    else { "FAIL"}
};

In dlang pure functions can also use local variables. The concept of pipes connecting processes is suggested by Doug McIlroy at Bell Labs. In Perl the same concept is seen in the default variable $_.

Examples for Perl packages

apt install dh-make-perl
cpan2deb --version 2.2.13 --packagename libapache-eperl-perl --intrusive Apache::ePerl

# build a perl module for debian
modulemaker -I -n MyMod
mv MyMod libmymod-perl-0.01
cd libmymod-perl-0.01
perl Makefile.PL
make dist
mv MyMod-0.01.tar.gz ../libmymod-perl_0.01.orig.tar.gz
dh-make-perl dump-config > dh-make-perl.conf
dh-make-perl
dpkg-source --auto-commit --build .
debuild -uc -us

#make test is executed during build
HARNESS_PERL_SWITCHES="-I lib -I t"

## Build and install libjq-perl with cpan2deb
apt install cpan2deb perl libwww-curl-perl libipc-run-perl libjson-perl liburi-find-perl gridsite-clients -y
apt install dh-make-perl
aptitude install libtest-most-perl libio-pipely-perl

## dpkg: error processing archive /root/Jq-0.01/libjq-perl_0.01-1_all.deb (--install)
ln -s Jq-0.01/libjq-perl_0.01-1_all.deb
PERL_MM_USE_DEFAULT=1 cpan2deb Jq --install
EMAIL=postmaster@localhost PERL_MM_USE_DEFAULT=1 cpan2deb AI::FuzzyEngine --install


apt build-dep eperl
dh-make-perl make -n --build --cpan eperl \
--version 2.2.13 --packagename libapache-eperl-perl --intrusive
dh-make-perl --version 2.2.13 --packagename libapache-eperl-perl --intrusive
dch --newversion 2.2.13-1 ""
dpkg-source --auto-commit --build .

# Perl and Qt
apt install libqtgui4-perl
libpar-packer-perl perl-tk
libdbd-sqlite3-perl
libwww-dict-leo-org-perl
libfrontier-rpc-perl

# Dancer is a dynamic webapp
apt install libdancer-perl -y
dancer -a mywebapp
systemctl daemon-reload
systemctl enable mywebapp.service
systemctl start mywebapp

# perl parser
apt install perl-byacc

perl -e print + (split /,/, "1,2,3")[0]