The Joy of Perl (1998)
salon.com
salon.com
There are a few big issues with Perl 5 but the biggest is easily the mess of references vs flat values. Python, Ruby, JavaScript and many other dynamic languages do not make the programmer think about whether you are going to pass a data structure like an array or hash as a reference or direct value. Perl does. A lot of built in operators expect direct values, eg array ops like join, push. This is because the ops existed before Perl added complex data structures — arrays of arrays, hashes of arrays, etc. References were bolted on in Perl 5 to support such structures. And any code using them will handle references not direct values. So you have a split. And then a lot of energy is spent navigating between these two types of variables.
As Steve Yegge said:
“Perl's references are basically pointers. As in, C-style pointers. You know. Addresses. Machine addresses. What in the flip-flop are machine addresses doing in a "very high-level language (VHLL)", might you ask? Well, gosh, what they're doing is taking up about 30% of the space in all Perl documentation worldwide.”
https://sites.google.com/site/steveyegge2/ancient-languages-...
For a taste of this here is how you join an array inside a hash:
join(‘,’,@{$foo->{‘bar’}})
Update - I forgot to say my favorite thing about Perl. The CPAN community. People talk about the sheer scale of CPAN but my favorite thing about it is the quality of documentation, at least back when I was using it. Really good uniform high quality docs. Almost always a great synopsis with multiple good examples covering real uses cases and gotchas. Then thorough documentation of functions/methods. My theory is this culture developed because CPAN predates StackOverflow, github, Google, maybe even search engines. The docs had to be good.
For example:
my $a = [10, 20, 30];
my $b = { array => $a };
my $c = { array => $a };
$b->{array}[0] = 99;
print $c->{array}[0];
To me, anything the syntax can do to make it clear that the above code prints "99" (and not "10") is a net win. I don't care how cluttered it looks or how much extra typing it requires. If a language hides this from me in the name of cleanliness, then it's creating a leaky abstraction that is going to cause bugs and other forms of suffering.If you're in a language which has immutable arrays, then this doesn't matter. But Perl isn't that, so that's not really relevant here.
To me, languages that add reference types (like C++'s) or language features that allow passing things by reference just create an extra cognitive burden. I look at some code and wonder, "Is this going to have ripple effects in distant places?", and I have to work through some rule in my head such as, if it's an integer, then no, but if it's an array, then yes.
Contrast that with the Perl (or C) way. I look at some code and the syntax tells me. There's no mistaking what's going on. So less cognitive burden and less opportunity for error.
> join(‘,’,@{$foo->{‘bar’}})
You might write it this way. I prefer to use the features of the language developed in the last decade: join ',', $foo->{'bar'}->@*
Which if that looks spooky, the * simply means everything in the array. You can just as easily slice: join ',', $foo->{'bar'}->@[2..5]If you don't think about these things in python, you're going to be scratching your head when you see something like this:
>>> foo = ['a','b','c']
>>> bar = foo
>>> bar[1] = 'z'
>>> foo
['a', 'z', 'c'] def foo(some_list=[]):
...
some_list.append(3)
...
Since the default is constructed when the function is evaluated, it's the same list, but only when the default is used.Or the n00b's attempt to use lambdas:
def list_of_lambdas(x):
result = []
for n in range(x):
result.append(lambda m: n + m)
return result
for func in list_of_lambdas(3):
print(func(3))
5
5
5
(All the closures share the same "cell", meaning the same "n", which is 2 at the end of that loop. Worse, if you 'yield lambda ...', that example would look like it worked. So, yes, Python absolutely has references.)Perl and JavaScript both get default arguments right: They make a new array on each call.
Perl and JavaScript also get the for-loop closures right as well. In Perl, "for (my $n = ...)" and in JavaScript "for (let n = ...)" will both create a new "cell" each time around the loop, so closures work as expected.
(However, MSIE's version of "let" doesn't create a new "cell" each time, and this can be a source of difficult to see event callback bugs; best transpiled out.)
use experimental qw(signatures);
sub plus_one($x = 100) {
return $x + 1;
}
# Says 6.
say plus_one(5);
# Says 101.
say plus_one();
(The subroutine signatures feature is still marked experimental, which is a shame.
I use it in virtually all my code, unless I want pre-5.20 compatibility.)Good to see it still evolving!
In python, $foo is a reference. It might be a reference to a scalar value, or list, or hash, etc, but it is a reference. The code you wrote might cause confusion for people who don't understand the python model.
In perl, $foo might be a scalar value, or it might be a reference to a value of some kind. Perl has this exact same type of problem demonstrated by your python code, but in addition it has the problem of "is $foo a scalar value or a reference?"
In Python, variable "foo" behaves like its value is a non-reference if the value is what some languages call "unboxed", for example numbers and strings.
That's exactly the same as Perl.
Technically, Python shares objects even in the case of numbers being copied around, and the object's address is visible with the "id()" function.
(I emphasise address because that was a criticism of Perl in another comment, but everything in Python is memory with an address as well and the criticism ought to apply more strongly because even numbers need memory allocation.)
However, the fact that numbers are immutably-shared when assigned in Python doesn't make their behaviour any different from numbers being assigned in Perl (apart from the obscure id()). It's hard to imagine what "problem" is created in Perl by the fact that numbers and strings are non-references. Most other languages do like Perl.
With strings, Perl does both according to a performance heuristic: Sometimes it copies, sometimes it shares. This is completely safe because you can't tell the difference at language semantics level anyway.
Yes, the "Python" model (or Java, JavaScript) of referring to everything by reference is uniform and simple--except it still shares the issue of having to care if you add mutation into the mix. Due to its apparent smoothness it might even make it easier to run into that. In a sense Perl is honest here in saying I use local arrays via @ prefix and I know this array "lives here", like in the C/C++ world where you have to care about where the storage is so you don't pass references to stack objects etc.; in this world, when you take a reference, it's a heads-up that you may have to care about something. In Perl, unlike in C/C++, you don't have to care about memory safety, but you still, like in all imperative languages, you have to care about sharing of mutations. An explicit reference makes this explicit. If you return an array flat (without taking a reference) in Perl, it is being copied, and while that's slow, it is at least safe. It's an unclean solution for the issue, but in a sense it's at least pointing your head towards the issue.
The clean solution for this is functional programming. Lisp was first to use a uniform "everything is a reference, implicitly" model. But it also preferred a functional programming model where you don't mutate your data structures. Java and Python took the reference model but mixed it with an imperative data update model. Meh.
And I agree that I like the "just use references for everything implicitly" approach. But I also like to combine it with a functional one. And I ended up creating a project to achieve exactly that in Perl, and will shamelessly plug it here: https://metacpan.org/pod/FunctionalPerl (Code written in it co-exists with code that still uses non-reference variables, so feel free to argue that "now you have both worlds mixed", but for one it aims at existing Perl programmers who know how to deal with the non-reference model, and secondly functional programming matters most in the upper levels of an application; it's fine to use imperative code in inner loops / enclosed in an otherwise pure function, and it's fine to use array/hash variables there; FunctionalPerl comes in where you'd traditionally take a reference via `\`; so it's kind of a split between imperative and functional world now).
> The clean solution for this is functional programming
or another model that guarantees that modifications are never seen by code that isn't explicitly meant to receive them--the prominent other model that's making waves nowadays is of course linear types (and extensions as used by Rust).
> join(‘,’,@{$foo->{‘bar’}})
Thank you for that example. I guess the equivalent in JavaScript is: foo.bar.join(',') $foo->{bar}->join(',')
I've done that in FunctionalPerl[1]: use FunctionalPerl ":autobox";
my $foo= {bar=> ["hi", "there"]};
is $foo->{bar}->join(','),
'hi,there';
[1] https://metacpan.org/pod/FunctionalPerlI do too. I use it for solving data-analysis problems in a portable and long-stable way. To this day, I can still run Perl that I wrote a long time ago. That's a good investment. I can build data structures in Perl OO that are much more efficient in memory consumption than other interpreted languages.
Good code and bad code exist in every language -- anyone who has been in the business for a while knows this.
I would just add that the rejection of sigils and braces is also the rejection of other very useful and efficient tooling, such as bash and awk.
I’m ok with it but it is hard to read, I think because there are so many ways to do everything. it takes a bit to get used to some of the syntax ($@~). I was told my perl was very c like during a review.
It’s great for text manipulation though.
I just remember Rasmus (of php) talking about how he always expected any language to take over php but perl made some design decisions that made it unpalatable to hosting providers.
It’s still my go to for processing large text files.
I still write perl5 sometimes but none of perl6 features convinced me to install an interpreter anywhere when I already have ruby or python on the machine.
I am fluent in a lot of languages and cannot really imagine anything that could motivate me to upgrade my perl5 black belt to perl6 except for a well-paid gig that requires it.
As I recall, back in the mid-late 90s the phrase "there's more than one way to do it" was used a lot in reference to Perl, and that was generally true and made it pleasure to learn and use.
There soon came to be two very divided camps of perl users. There were guys like Randal Schwartz that considered themselves as elite geniuses and hacks like me who asked stupid questions and "made crap".
Coming from knowing nothing about writing code I bought books by Selena Sol and Lincoln Stein and learned a lot. They were very accessible with lots of example code. But Randall's O`Reilly books were just way too perplexing for me to get anything out of them.
I also joined some of the official Perl and Perl CGI mailing lists. Those lists were public but had just few hard core users and then guys like me, who knew almost nothing, came flooding in with lot's of newbie questions and things got pretty vicious. "RTFM" was a common snotty response that gave no help at all.
I made an effort to answer those newbies fast and courteous but they'd still often get just beat to shit by the snobs there. In fairness, Larry Wall was always very welcoming and encouraging to dabblers and beginners like me, and he did work hard to discourage snobbiness, but somehow those perl mailing list just attracted hardasses. Larry was never on any of the lists I joined.
If you go read some of those old emails you can see it.. I started the perl.macosx mailing list around March 2001 after getting chased off the "macperl" list for asking a question about perl on OSX when it first came out. I tried to keep things friendly on the new list and it was a lot of fun until the snobs showed up there too about a year later. I finally just unsubscribed after a just few more years.
It wasn't long after I left that participation in those email lists started really falling off. Now they're barely used at all. Can't blame it on Larry Wall though. I still love that guy.
I learned long ago to not call my programs scripts, because many people interpreted (sorry) this negatively.
There's a good reason why parser generators were part of UNIX.
I ended up using what I knew instead: Turbo Pascal + some oddball "wincgi" interface.
Later I caved and started using Perl, since everyone else was using it. It was a pretty weird experience. I did my first paid "consulting", for a company from the tiny place where I grew up, building a "web app" using Perl. This happened during the first year of university studies. I got paid $12/hour. That was so much money to me, back then! (I was like 18 or 19.)
This experience is where I grew to hate Perl and learned to love more structured languages.
A year later in 1997, I ended up working full-time with the https://en.wikipedia.org/wiki/Pike_(programming_language) instead. This was essentially a precursor of Dart.
“It’s my second language”, he said.
“What’s your first?”
“English.”
Also, I find it humorous how the term “hacker” is used here to refer to literally anyone who works on computers. I suppose the title of this site retains that meaning...
""" "I realized at that point that there was a huge ecological niche between the C language and Unix shells," says Wall.
...
"People are always looking for the interstices," says Wall. "They are always looking for the new ecological niches. And the speed with which you can move into those ecological niches is really important, because the first person into a niche is often the winner." """
I don’t know why you’d want to use it over other popular scripting languages like JS/Ruby/Python. All have more active communities.
AWS don’t even support Perl
It wasn’t until I was “forced” to learn Python last year and started working heavily with AWS that I actually enjoyed scripting languages again for smallish glue type scripts.
This year I finally started using Node.
But yeah for career reasons, I wouldn’t tie my horse to Perl in 2019.
Python's nice for gluing more performant native code together (perl XS isn't as straightforward IME). But for text processing I'll take perl every time.
It’s not the most performant of languages (although it’s definitely getting better).
https://www.digitalocean.com/community/tutorials/configurati...
Other just use whatever, fix problems, and make money.
-As a web developer, I use it to write all sorts of small webservices and file conversion utilities;
-As a embedded system developer, I used it to integrate with other services in the network;
-As a sysadmin and DBA, I use it a lot to parse all sorts of data.
The downside is that I have to put up with the little jokes and criticisms. Then again, more than once I've been called because I was the only one who could do some job fast enough.
But why fool with Perl at all - especially Raku since it’s basically a new language that doesn’t have the widespread support of Python or God forbid PHP?
https://steelkiwi.com/blog/top-10-python-web-frameworks-to-l...
I'd rather use Perl 5 than Raku at the moment. At least Perl 5 has CPAN which is still somewhat alive.
Still, I agree, there's no real AST and string eval is unsafe and parsing is a real issue. I've started https://metacpan.org/pod/FP::AST::Perl (very unfinished) to solve the code generation issue and hope to generate an AST from the op tree (not sure how feasible, will see). Feel free to tell me (here or offline) what your use case is and whether that module might suit you.
Perl cannot be statically parsed!
> Theorem: Parsing Perl 5 is Undecidable
My usage (modifying syntax / extending the compiler when running Perl programs) doesn't need static parsing. What I need is a way to leverage the existing infrastructure in the interpreter for parsing in a way that's compatible with most modules/usages. AFAIK the parser in perl goes directly from source to an OP tree (modulo running other Perl code on the go that modifies the parsing state, which is the reason for the undecidability), it would be cool if it didn't go to an OP tree but something more AST instead, but it might not be feasible to change perl to do that because of modules working on the op tree (if anyone wants to help figure out how much this is true, please do); because of that I'll instead look into converting the op tree into an AST. I've been told the op tree does have additional info that might make that feasible. Notabene, B::Deparse exists, which is somewhat of a proof that this works, although there are limitations, whether they matter is part of what I need to find out.
It is. Very much so.
But the thing that shocks me most about how completely Perl has fallen out of fashion is that nowadays sysadmins will write a hundred-line bash script rather than a five-line Perl script because of the theory that Perl is hard to read.
(Of course, using bash for the shell isn't a good choice because you can't rely on bash being installed).
Personally I reach for Perl as soon as any sort of arithmetic is involved. And even if starting with find(1) is the first choice, it's worth getting to know modules like File::Find because they're way more powerful.
Even alpine has awk installed. docker run --rm alpine awk