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.
-
The Perl Programming Language, http://www.perl.org
-
Are VHLLs Really High-Level? - O’Reilly Media, http://archive.oreilly.com/pub/a/oreilly//news/vhll_1299.html
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]