
Desert ...
Proud and stately stands by the Perl Desert. He began his journey back in 1987, having walked thousands of deserts over many years, he saw wonderful and caressing oases full of water here and there, as the rainy seasons began alternating with prolonged droughts. Deserts are different, more than once there was trouble with him, when an imprudent rider led him deeper and deeper into the arid desert where there is no place for even hope. On the contrary, there were cases when whole megacities full of life and people appeared in the middle of the desert, it seemed that it was a mirage, but no - it was a reality. Perl never wondered at the creative talent of people. He did not impose a path on a man, trusting in his will followed the depths of the desert to the unknown. He was disappointed by
1 “wild” riders - people from big cities who got used to moving around in difficult machines. Here, in the desert, even the most attractive thorn cannot make them move forward even by a meter. Out of habit, they take a lot of rubbish with them, and constantly push them in, forcing them to run faster and faster. The beauty of the desert, its philosophy, rushes past them, but not many of them reach the goal, leaving behind them all the same lifeless desert. On the contrary, there were other people who perceived the desert as something new, free, unlimited space for creativity. Keeping track with such satellites has always been a great pleasure. The path led them through the bizarre, full of life islets of the desert. Sometimes a group of such people could collect whole caravans of camels, not hastily wandering through the desert. The desert was drunk, and somehow in a special way, magically acted on the young minds of riders who had not got stronger. Perl often saw poor fellows go crazy starting to build sand castles that were not destined to become something big. Others drew in the sand do not even understand him doodle. Mirages, who never really existed, either destroyed them. Unfortunately, Perl could not help these poor fellows, just as he couldn’t refuse to travel, because Perl felt great about traveling, it was for this that he was born.
')
And here he is in front of you, happily kicking with his foot, offering to make a fascinating walk through this still lifeless desert, to the distance where you think you should go.
... camel 2
(*) Perl's philosophy is that it is easy to solve simple tasks, while still being able to solve difficult ones. These are the tasks that we solve every day. You do not need to pronounce many preliminary words before saying what you are going to do. Perl is traditionally included in the delivery of almost all * nix distributions, which makes starting especially easy. In fact, after installing the operating system, Perl is ready for work (of course, we are talking about * nix).
(*) When developing every new version of Perl, special attention is paid to maintaining backward compatibility. Which is very important, considering how much is written in Perl.
(*) CPAN . A distribution network for Perl modules, something like (
maven ,
ivy ) / Java,
RubyGems ,
npm /Node.JS. The tablecloth is a groundwork, a storehouse of ready-made solutions for all occasions. Currently one of the largest among languages ​​(more than
121,000 modules). Thanks to CPAN, many complex problems are solved by a trivial search for a suitable module. However, the comparison with maven is somewhat strained, CPAN is much simpler in terms of dependency management. It does not require any pre-set up magic, it is more like
apt from Debian / Ubuntu.
(*) Perl compiles text programs into an intermediate representation before interpreting them. That allows, though not often, to detect errors in the program at
the compilation stage . This, above all, includes checking the correctness of syntactic constructions, checking the correctness of the names and arguments of subprograms (only if there is a prototype), checking the correctness of references to the fields of a class. Of course, this is not a C ++ compiler, but for a dynamic language it’s not bad at all. It's interesting, but in some ways even the C ++ compiler can leave behind, so the Perl compiler can define incorrect calls to mathematical operations (for example: a root from a negative number causes a compilation error). Here are some examples:
Perl always follows
its own principle , and it costs nothing to turn off most of these checks, but more on that later.
(*) Function prototypes allow you to pre-declare subprograms and a list of their arguments, something like a
forward declaration in C ++, if there is a prototype, the compiler checks the correctness of the subprograms call, and also does not require paired brackets when calling the subprogram.
sub feed($$); feed 'Sharik', 'Fruit';
(*) $ @% . Perl separates the variables by purpose: the '
$ ' scalar (number, string, link), the '
@ ' array (sequence of scalars), '
% ' hash (associative array of scalars). As you can see, classic primitive types are represented by scalar. However, they are strictly separated from the containers, which allows the compiler to perform additional checks, saving us from the hassle. Perl does not allow its types to be introduced (for the OOP, indulgence is introduced - any of the built-in types can be blessed into the class). Thanks to such a clear separation, in the same area you can have non-conflicting variables of all types:
Each operation in Perl is non-separable and associated with the execution context. Perl understands three types of context: empty (without context), scalar and list (for example, assigning a value to a scalar variable forms a scalar context, and assigning to an array or hash is a list context). Perl routines are able to determine the execution context and, accordingly, can behave differently in different contexts, which gives room for creativity.
There is no pointer arithmetic in the language, but there are links. Arguments in the subroutines are passed by reference, but the assignment operator performs the copying of the variable value itself (not only scalars are copied, but also containers). Thus, passing arguments to a subroutine by value is easily implemented. Moreover, the classic Perl subroutine record involves passing by value, i.e. does not introduce side effects for its arguments.
(*) Operator overloading (for rare cases when it is necessary). You can overload almost everything except spaces, commas, and perhaps I have not heard that someone could reload the comment. The only language (known to me) that allows you to overload constants (numbers, letters, words). This can be used, for example, to replace all numbers entered as constants with equivalent objects representing complex numbers. Or use numbers of unlimited size:
Perl allows you to overload the standard language routines.
(*) Regular expressions are deeply integrated into Perl. In addition to the usual regular expression patterns, Perl supports its extensions. For example, Perl allows you to use direct Perl code in search patterns and replacement patterns:
my $math = '100 + 200 = 300'; $math =~ s/(\d+)/$1 * 2/ge;
Regular expressions support
Unicode properties and even allow you to enter your own character properties. Allowing you to enter your abbreviations for complex patterns (like \ s, \ w, etc.). Naturally, regular expressions in Perl support both greedy and non-greedy searches.
(*) Perl, in the absence of the
return keyword in the subroutine, returns the last calculated expression (it looks like it is fashionable now). In addition, when calling subroutines, you can omit brackets if you understand what you are doing.
(*) Blocks in Perl. A block is a pair of curly braces
{...} , such constructions as
while ,
if ,
for accept a block, although a block may exist by itself. The most interesting is that any block supports the operators
next ,
last and
redo . Those. Quite a legal entry:
{ print "Yeah\n"; last; print "Unreachable code\n"; } { print "Forever loop\n"; redo; }
In addition, subroutines can take blocks as arguments, which allows richly expanding the language with its syntactic constructions. This makes it possible to write beautiful self-documented programs on Perl, of course the presence of fantasy is necessary.
use strict;
Perl does not support a
try /
catch /
finally block , but it is easily implemented through subroutines, receiving blocks. Just because
if /
else accepts a block, in Perl the
if /
else if /
else syntax cannot exist,
if /
elsif /
else is used instead. Similarly, there is no
switch /
case , it is implemented trivially.
(*) The while loop can define a
continue section, which is executed regardless of whether
next ,
last or redo was called
(ie it is always executed) (as rightly noted by the
alienator , the redo call skips the continue section).
while (1) { next; } continue { print "Yet another loop done \n"; }
(*) Three scopes for variables: global, lexical and local. Local scope extends the value of a variable to the current block and to all subroutine calls from this block, useful for redefining the values ​​of global variables in a particular block. The local scope is determined at runtime, and lexical at the compilation stage (this is the most common scope, inside the block).
use strict; our $a = 'global scope';
(*) Perl implements closures, it is good that the syntax for declaring an anonymous subroutine does not differ from a regular declaration, as it happens in some other languages.
(*) Already since 2002 Perl has supported a mechanism for calculating constant subroutines, and replacing their call locations with the values ​​of a calculated constant (
constexpr ).
(*) Convenient file scan operators (-
rwxoRWXOezsfdlpSbctugkTBMAC ).
use strict; if (-e '/tmp' and -d '/tmp') { print '/tmp is directory', "\n"; }
(*) Operator
<> . Performs multiple functions. First, it can be used to search for files by a pattern in the current directory (by the way, the search method can be changed,
glob is used by default).
print join ',', <*.pl>, "\n";
Secondly, it is an operator to read data from a file descriptor. Moreover, in a scalar context, it reads the data line by line, and in the list context, it reads the file lines completely into an array.
open F, '<somefile' or die; my @random = <F>;
Finally, the empty
<> operator reads from files whose names were passed in program launch arguments. It does this explicitly, as if you are working with one large file. If the program was launched without arguments, it reads from
STDIN . This is very convenient for developing programs for pipelines that will be joined through |, since you do not need to worry about opening and closing files. Applying this statement, the analogue of the
cat command is implemented in one line.
print while (<>);
(*) Useful default variable
$ _ . Most standard subroutines and Perl operators can work with it, and assume that it is used if the input argument of the function is omitted. Sometimes it allows you to write more concise code.
use strict; while (<>) { print if (s/^print\s*(.*)/$1/); }
(*) In Perl, the result of an assignment is an
lvalue . Therefore, in Perl, it is possible to change the value during assignment.
($new = $old) =~ s/bad/good/g;
(*) The increment operator applied to the string returns the next permutation from the character set.
my $a = 'aa'; print ++$a, "\n";
(*) Automatic expansion of hashes and arrays to an arbitrary depth. Those. when accessing a hash on a key that has not yet been added, this element is automatically created. And Perl guesses the type of element to be created, for example, it can create an anonymous hash, an anonymous array, or a scalar.
my $hash = {}; $hash->{first}->{second}->{third} = 5; print $hash->{first}->{second}->{third}, "\n";
An interesting feature is the behavior of negative indices in arrays. A negative index selects elements from the end of the array.
(*) Strings and quotes. It's nice that Perl supports entering multi-line documents in a single assignment:
my $doc1 = 'There's More Than One Way To Do It -- 2012'; my $doc2 =<<"_DOC2_"; There's More Than One Way To Do It -- 2012 _DOC2_ print<<"_DOC3_"; There's More Than One Way To Do It -- 2012 _DOC3_
Using the operator
= << allows you to conveniently perform operations with a multi-line document in the same line where the assignment is performed. It is also convenient to use this operator to transfer documents to functions.
use strict; sub printAll(@) { print join '', @_; } (my $quote =<<'__QUOTE__')=~s/^\s+//gm; The Road goes ever on and on, down from the door where it began. __QUOTE__ printAll(<<'__GOOD__',<<'__BAD__', $quote); There's More Than One Way To Do It __GOOD__ TIMTOWTDI __BAD__
Perl distinguishes between two ways to enter lines — with and without interpretation. If you use single quotes
' , the string is assigned to the variable as is (without changes), even the characters \ n are not converted to line breaks. On the other hand, if you use double quotes, the string is interpreted - Perl detects and replaces variable names with their values, and does it quite skillfully, you can even make a function call directly from the string.
use strict; my $car = { brend => 'Lada', name => 'Kalina', drive => sub { "WEEEEEE!\n"; } };
However, Perl gives you the right to choose a character for escaping strings and regular expressions.
print q { ! }; (my $text = "ab c") =~ s{\s}{}g;
Another very useful feature of Perl is the behavior of strings when using `as the escape character of a string. In this case, Perl executes this string in a shell and returns the result of the command.
print `uptime`;
(*) Perl supports an interesting subroutine attribute mechanism. You can draw an analogy with
annotations from Java. Attributes are specified in the declaration of the subroutine with a colon. You can declare as many multiplayer attributes as you want. There are also built-in attributes
method and
lvalue . The remarkable
lvalue attribute allows a subroutine to participate in operations like an
lvalue . For example, you can implement the
get and
set methods in a single subroutine.
my $_name = '?'; sub name(;$): lvalue { $_name = shift || $_name } name = 'caiiiycuk'; print name(), "\n";
(*) The remarkable
AUTOLOAD mechanism allows processing calls to non-declared subroutines, which is often used to dynamically load a program in parts. This means that if Perl does not find the declaration of the subroutine, it calls the
AUTOLOAD call with the signature of the function and only if it turns out to be unsuccessful will throw an error. Using
AUTOLOAD , for example, you can achieve a more clear call of system functions, as if they themselves are Perl operators (as the
Shell module does).
use strict; sub AUTOLOAD { my $program = our $AUTOLOAD; $program =~ s/.*:://; system($program, @_); } sub uptime(); sub echo(@); uptime; echo "AUTOLOAD";
(*) tie - a mechanism for replacing the internal implementation of scalars, arrays and hashes. Using this mechanism, you can associate an array or hash directly with the database in such a way that any read and write from / to it will automatically be mapped to the database. Another possible application of this technology may be the calculation of allocated resources.
(*) Perl supports two models of multithreading: the thread model and the process model. The process model implies the creation of a new system process with a full copy of the parent process data for parallel data processing. This is done by the
fork , with heroic efforts, the process model is fully supported in Windows, although this parallelization model is more typical of * nix. It is not quite convenient to use the bare fork function, CPAN is full of modules for easier use of
fork , for example, the code could look like this:
use strict; use Proc::Fork; run_fork { child { print "Process 1\n" while 1; } parent { print "Process 2\n" while 1; } }
In contrast to the process model, the thread model is used; these threads share access to all data resources, such threads are more like Java threads. The thread support module is called
Thread , it provides a very convenient async function, which helps to write clear code.
use Thread 'async'; my $thread1 = async { sleep 5; return 1; }; my $thread2 = async { sleep 2; return 2; }; print $thread1->join(), "\n"; print $thread2->join(), "\n";
The mechanisms of synchronization of streams are supported: mutexes, semaphores, falling asleep and awakening streams by condition.
(*) The powerful
pack /
unpack functions allow you to convert Perl structures into an array of bytes and vice versa. A very useful thing when reading binary data and for their arbitrary conversion.
(*) OOP and Perl, this is probably the only thing that makes me have mixed feelings. This is very similar to what we have in JavaScript, as such, there is no special support for OOP capabilities in the language; nevertheless, all the paradigms of OOP are realizable and quite viable. However, sometimes there comes a feeling of some kind of a chilliness. An object can be any scalar, array, or hash data structure.
With the help of a special command, the reference to the data structure is blessed into an object ( bless ), after this action Perl knows that this reference is an object. The methods of this object should be sought in the package in which the link was blessed. Accordingly, there is no classic concept of a constructor; any subprogram that returns blessed data structures can be a constructor. Perl supports the indirect form of calling the object's methods; in this form, the method comes first, then the object reference, and only then the method arguments. Because of this, the call to the new method may look like you expect, but when calling the usual methods, this form of writing may seem strange. { package Dog; sub new { my $class = shift; return bless { name => shift }, $class; } sub gav { my $self = shift; print "$self->{name}: gav\n"; } } { my $dog = Dog->new('Mona'); $dog->gav(); } { my $dog = new Dog 'Sharik'; gav $dog; }
Perl OOP supports multiple inheritance. When using the use fields pragma, it is possible to check references to the fields of a class at the compilation stage using pseudo hashes, as well as implementing private class data. { package Foo; use fields qw(foo); sub new { my Foo $self = shift; $self = fields::new($self); $self->{foo} = 10; return $self; } } my Foo $var = Foo->new; $var->{foo} = 42;
Unfortunately, class methods cannot have prototypes, so we lose the ability to check the correctness of calling methods and passing arguments, this is regrettable. Perl supports object destructors.(*) The special label __DATA__ indicates the end of the script, all the text after this label is available to the program through a special file descriptor DATA. This is very convenient for writing small tests when the data and the test itself are not separable from each other. But the whole system of testing in Perl is more than convenient, which is inherent in all dynamic languages. use strict; my @content = <DATA>; print join '', @content; __DATA__ A B C
(*) A huge number of Perl command flags allow you to write the shortest one-liners to process files. For example, the -n flag encloses the script in a while (<>) loop , which we considered earlier. That is, an analogue cat can be written like this: perl -ne "print;" file1 file2 ... fileN
(*) A very interesting opportunity to write code generators. After compiling the code, the Perl program is a graph of operators. This graph is normally transmitted to the Perl interpreter, but you can change this behavior by performing your actions with this graph. For example, you can simply serialize the entire graph to a file, and then read it on another computer and transfer it to Perl interpretation, omitting the compilation phase. A more complex application of this technology is the generation of C or C ++ code from a Perl program. Generators B :: C and B :: CCthey are directed at this; when using them, the Perl program is converted to source codes in the target language, then they are compiled into machine codes and can be run without the Perl interpreter. In addition to the code generators in Perl, there are also code filters, they allow you to arbitrarily convert the source code of a program before compiling and interpreting, you can write your own language if you want.(*)Labeled data mode. While in this mode, Perl takes special precautions to avoid obvious and hidden security holes. The principle is simple: you cannot use data obtained from outside the program being executed to influence anything else outside of it. Any data entering the program from the outside becomes “marked” as data of dubious origin. Labeled data cannot be used directly or indirectly in any operation that causes a "shell", as well as in any operations modifying files, directories or processes. Therefore, many security problems are avoided. The use of labeled data mode is a good way to run scripts on the server. There are modules that go even further in improving security, for example, the Safe module.
(*) PSGI / Plack is a specification designed to separate the web server environment from the web framework code. Simply put, this is something like a container servlet from the world of Java. We write a web application using this specification and run it on any of the servers supporting PSGI, of which there are a great many. More details .
(*) And Perl is a sea of ​​pleasant emotions, which is only a set of ACME modules. For example, the ACME :: EyeDrops module allows you to convert Perl programs into ASCII art that works. There is a buffy fan module , using which programs can only be written using the word buffy. Well, the ACME :: ChuckNorris module speaks for itself. In addition, there is Perl poetry - this is a valid syntactic program from the point of view of Perl, and poetry from the point of view of man is one of those in the title of this article.Bon Voyage!1 So thinks my Perl, yours might think differently TIMTOWTDI2 Interesting possibilities in my opinion Perl