Perhaps "sucks" is too gross a word, but by analogy with "Why C sucks" and "Why C ++ sucks" This is probably the appropriate heading.
First, let me say that Perl is currently my favorite language. programming. I love his power, I love his elegance, and, Most of all, I love its expressiveness. However, Perl, certainly not without flaws.
The tone of this article is not intended to be negative. I think it will be useful for us to know. about the weak points of used programming languages, especially popular ones, so that we are sure that these weaknesses will not fall into other languages. ')
So here is my list of problems in Perl:
No inheritance of objects.
Perl inheritance is implemented through an ISA array (pronounced as "Is a", as in "this is a problem"), which allows you to call methods from one package through a bless link to another package. For example, if SomeClass contains SomeOtherClass in its global ISA array, then you can call any SomeOtherClass method directly via bless link in SomeClass.
Unfortunately, there is no real way to inherit objects from another class in Perl, you can inherit only their methods. Usually the workaround used is from the constructor of the class that wants inherit, the constructor of the class that is inherited is called to get the object, add your own fields to the hash, and then Ove-bless-thread object into your class:
package SomeClass;
use SomeOtherClass;
@ISA = 'SomeOtherClass';
sub new {
my $ class = shift;
# create a new SomeOtherClass object:
my $ self = $ class-> SUPER :: new;
# mess with it:
$ self -> {'_ something'} = 1;
$ self -> {'_ something_else'} = 2;
# now bless it into SomeClass:
bless ($ self, $ class);
return $ self;
}
one;
The problem is that it violates the laws of encapsulation and abstraction: you need to know the details of the implementation of the object, which you inherit, and then you climb right inside and work with his fields directly. You can declare global variables in one package, write procedures to manipulate these variables, then inherit these procedures ... but it's all wrong.
Given the countless number of object-oriented modules on CPAN is easy to forget that Perl was originally designed as a pure structured programming language. Such moments make it absolutely clear: OO in Perl is really nothing more than bless links and a little bit syntactic sugar.
Reference count.
Perl uses a reference counter for the garbage collector, an easy way memory management which guarantees timely release unused resources. Every scalar, array, hash, something else has built-in reference counter, which starts from one. Everytime, when a reference is created to this variable, the reference count increases. When the link is deleted, the counter decreases. At some the moment when the last link is deleted and the counter reaches zero, the memory used for this variable is released. The problem occurs when you have two variables referencing each other friend, like the parent hash and child hash, which both contain links to each other. Since nobody's counter can be reduced until zero until the last link is destroyed, one cannot be released until the second is released, and as a result they both remain hang in the memory. This is what is known as "circular links". (see additional information: http://www.perl.com/pub/a/2002/08/07/proxyobject.html ).
This means that it is unexpectedly easy to fix Perl memory leaks. Many budding Perl hackers did this by chance. They thought: "Ha, it would be useful for this object to contain a reference to the parent, and vice versa, ”and, voila, a memory leak.
Perl is definitely not alone in using the reference count: VB it uses, Python still uses it, as does PHP.
Probably the greatest problem with link counters is the extra load on the authors of XS-extensions. Counters make them produce calls to SvREFCNT_inc () and SvREFCNT_dec () throughout the code, controlling what each SvREFCNT_inc () has a corresponding SvREFCNT_dec (). what leads me to the next annoyance ...
Not an intuitive API.
The Perl C API is pretty curious. First, there is no visible naming convention. Some procedure names are written in mixed case, for example newSViv (), while others contain underscore, for example newRV_noinc (). Many variable names and members of the structures have short, sometimes disorienting names, for example “Cur” for length and “len” for size.
The API is also awash with macros, many of which are not documented. in perlapi or any other man pages, for example HvKEYS ().
And, to make life even more interesting, for functions that documented, often not told whether they will change the counters references of their arguments.
Non-intuitive array / list behavior in scalar context.
I really don't like writing code with extra brackets like:
my ($ first_field) = split (/ \ t /, $ tab_delimited_fields);
to interfere with the list or array returned from some function, behave wrong.
In Perl, arrays return their size when used in scalar context and lists (eg "(70, 80, 90)" in the program text) return your last item. First, what for all introduced the difference between lists and arrays? Secondly, when and why I may need to use the list in scalar context to get his last item?
I think it would be much better if both the arrays and the lists worked in the same way and returned the first element in a scalar context, instead of length or last item. Then it would be possible to write code like:
my $ email_address = $ input = ~ / (\ S + \ @ \ S +) /;
and he would work.
How, you ask, then get the size of the array? Well, why not with using the length () function? A lot of newbies suggest that this should work that way.
Formats.
Perl formats were supposedly “Report” part of "Practical Extraction and Report Language" - of course "Perl" is no longer an acronym, and when, honestly, you can remember that you used formats? In fact, can you even remember how use them correctly?
This large, completely ignored part of Perl sucks in various ways. reasons.
First, the format definition syntax is awkward (how about 20 or so the characters "<" one-by-one?), global (you it will take a large, dotted block somewhere - more likely just under your code) and completely different from the usual syntax of Perl (increasing the likelihood that you will forget it, especially since you never used it).
Secondly, an attempt to do something full using formats leads to verbosity, often requires the use of the select () function and messing with $ ^ before calling write (), forcing you to use three expressions to achieve what one would be enough for. (Four expressions if you count and restore select ().)
Thirdly, all that formats can do is usually able to do and printf () with sprintf () ohm Even when the format syntax is really more flexible than printf (), using several printf () s is usually allows you to solve a problem, and this is a shorter and cleaner way. Perhaps the worst part of all this is that write () is used to output non-existent formats instead of executing I / O as read (), its English opposite:
“Note that write is * not * the opposite of 'read'. Unfortunately. "
from (perldoc -f write).
No constants or macros.
In fact, it should be two separate items, there is no Perl simple way to declare variables as constants or to define macros as an alternative to scattering magic numbers throughout code.
Yes, Perl has the “constant” pragma that should do both, and another, but this is really just a hack; agile but elegant hack nevertheless hack:
use constant PORT => 80;
PORT can now be used as an rvalue in assignments, as if it would be something like a constant, and any attempt to assign something in It will cause a fatal error. But, you see, PORT is actually not a constant, it's just a function with a prototype "without arguments." You can still block it by redefining the function, or through “Use sub”, or directly through the symbol table. More importantly, one of the goals of constants is efficiency; to make life is easier for the compiler eliminating the need to assign something in the variable. Here, instead of a small win, perl, interpreter, gets an indecent performance hit.
No type information.
In Perl, scalars can contain either a value or a reference to a value. Unfortunately, Perl does not provide operators to find out what type "Value" contains a scalar, the operator is only to determine the type links. This results in, for example, determining whether scalar number suitable for arithmetic calculations unexpectedly complicated. Yes, I understand that we, Perl hackers, used to think that numbers and the strings are interchangeable, but the problem still arises, and is ridiculous seek help from regular expressions to determine:
print "Not a number!" unless ($ thing = ~ / ^ \ d + $ /);
Of course, this expression does not work very well, since numbers can contain other characters like "+", "-" or "." to indicate the sign fractional part or exponent.
Even functions from ctype.h would be more useful than nothing.
This is even more annoying because Perl seems to have A pretty good guess is what type of value is in SV (S-shny typedef describing the value of the scalar) based on the value of the "flags" field, and can easily convert one into the other if necessary.
Autovivification.
The key / value pairs autovivify hashes (comment of the translator: I do not know how in one word translate autovivify, meaning - “are created automatically, on the fly ") in Perl. This means that you can specify A new key of the type “autovived” and it will arise:
It also means that you can be sealed in the name of the key, and he too will occur without any warning. It is not big problem when you use hashes as dictionaries, because your keys often come from somewhere else, but when you use a hash like structure or object, this leads to problems:
$ self = {
name => undef,
age => undef
...
sub name {
my $ self = shift;
$ self -> {Name} = shift if @_;
return $ self -> {name};
}
When I use hashes as objects, I always define and initialize each hash element inside the constructor is something at least “undef”. That only I would not give for the keyword "static", which would hurt New elements are added to the hash after initialization:
static my $ self = {
name => undef,
age => undef
...
$ self -> {Name} = shift; # fatal error
Other, weaker stimuli that come to mind include no equivalent for chop () before the line, impossibility to apply -x chained file tests (you need to write "-e $ filename && -T $ filename && -w $ filename "instead of" -e -T -w $ filename "or" -eTw $ filename "), strange convention to call binmode (), unstable signals, misleading names like local (), and the lack of the sizeof () function.
This 16-year-old language has been steadily swelling for some time. Many his aspects become non-intuitive, ineffective, or simply ugly. Implementation is difficult to change, and adding new features without breaking old it becomes extremely difficult.
Perl 6 is an attempt by the Perl community to fix many of these problems. The real object support will be added, the link count will go away, sigils ($, @,%) will be more intuitive, and many new features will be added.
This top-down rewriting is still far from complete, but I, along with many others, eagerly waiting for him. Up to this point, I think, I I will continue to use Perl 5 to do most of my work.