Used to spend a ton of time writing Perl (see username). Moved on to better designed languages. Which are not hard to find.
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.”
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.
I once did a lot of Perl too, and I agree that Perl has many design flaws, but I prefer it this way. The main reason is if the same array is contained inside two different data structures, I want this to be explicitly obvious in the syntax of the language.
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.
"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."
If you don't think about these things in python, you're going to be scratching your head when you see something like this:
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.)
Yes indeed, that's a bug-prone misfeature of Python.
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.)
No, it isn't the same. I'm no language lawyer, but this is my understanding of it.
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?"
Imho that's not really correct, or at least misleading.
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.
I think OP's point was that even in Python you have to be conscious where your "storage" is--that you're sharing it.
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).
I still write Perl to this day on my personal projects and try to contribute as much as I can to CPAN. After more than 10 years it’s still my go to language. I think a lot of people are afraid of learning Perl just because they heard is hard to write or they came across some horrible code, I believe PHP suffered from this not so long ago. If you want a taste of using a really good web framework have a look at Mojolicious, Moose and friends introduce some really nice concepts around objects, there are many other interesting packages. The consistent documentation and testing around most of the packages on CPAN makes working with modules a breeze. Other languages like Python or Node.JS could learn a lot from the Perl community even to this day. The are just a few rules for writing code in Perl, the expresivity of which a lot of people are complaining it’s actually the Perl’s strong points.
I 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.
We use perl to power some web services that have been running a long time. It’s a work horse.
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.
PHP rise is a lesson in systemic effects. linguistic wise it had nothing on perl, the module execution model was another 'less is more'. Crazy in retrospect.
If perl6 had not been the Duke Nukem Forever of programming languages, I'd probably still be coding in Perl, but Ruby just came along and offered a very similaly spirited playground. And then I found lisp and realized that my late perl code was very lisp-ish anyway.
Did Duke Nukem Forever change its name? Perl 6 has. It's called Raku now (https://raku.org using the #rakulang tag on social media). And it is very much alive and ready for production.
No, but it was so long in the making that I had discovered alternatives and mastered them.
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.
Too bad. And now it is too late, because Perl 6 has been renamed to Raku (https://raku.org using the #rakulang tag on social media). Which features would convince you to install Raku?
Which does it offer that are not covered by ruby, python or CL?
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.
I still use Perl for server side chores, but most all my web app code is JS now and runs entirely in the web browser.
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.
The Perl Cookbook was great for most basic questions and Perlmonks for anything beyond that. I still miss the discussions in Perlmonks, something that Stack Overflow is missing.
Perl isn't so bad once you learn all the little gotchas, but it's not something I would recommend to anyone unless they're scraping clis. It has too many foot guns, and the pool of engineers to choose from seems too small.
After I first got online in 1995, I had noticed that Perl was this thing that everyone was using to create dynamic HTTP server behavior.
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.
14 years later (2011) I ended up visiting/working with a team that had stayed with Perl for some time. That was a fascinating experience. They were using selected "good" parts of Perl, sort of how you can can use the good parts of any competent dynamic programming language and stay productive, in a small team. Afaik they're still going strong.
It soothes me to read that even back in 1998, people were criticizing Perl for being write only and were considering Python. Trends in programming seem a little slower, knowing that.
In that time period I remember it being very common to hear Python introduced in conversation as a perl alternative. That was how I first heard of it too.
Oh man, this brings back memories... when this article was written, I was a high school freshman, and I had just bought Teach Yourself Perl 5 in 21 Days so I could learn how to write my own custom CGI scripts for my geeky personal webpage. It was my first true programming language, after childhood flings with BASIC.
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...
One of the most insightful pieces from the article:
"""
"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."
"""
Perl singlehandedly turned me off of using scripting languages for almost two decades. I stayed with C, C++, and C# and of course used Javascript for the web.
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.
Non-web developer here... I've personally never seen any Ruby in anything I've ever worked on (only personal, limited anecdote, of course).
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.
Ruby definitely has its niche in web development mainly due to Rails, Jekyll and Sinatra. Quite a weird choice for other things. Pretty sure Homebrew on Mac uses it.
It’s not the most performant of languages (although it’s definitely getting better).
Homebrew is the only thing I think Ruby is perfect for. It's just a DSL for describing how to fetch and build a program, like Makefiles but more convenient.
As the other reply to you said, agreed on the DSL-construction thing. I used a fair bit of Puppet a couple of years ago and that was very much Ruby through and through. What I really liked about it was how easy it was to jump from DSL for general use cases to Ruby for specialized libraries or system Facts.
Perl has never been central to nor a requirement of my jobs, but it has always helped me immensely.
-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.
At least it's fun to write modern Perl code compared to Js which is kind of annoying. Raku is also a very nice language but it's still too slow and hasn't gained much traction. Someone who's proficient in Perl can probably become productive in Python in less than a month.
I was traditionally the farthest thing from a JS callback hell fanboy, but, using modern JS with async/await and “classes” (yes I realize it’s syntactic sugar, prototypical inheritances, yada yada yada), it’s not bad. I haven’t played with TypeScript in a few years, but I’m looking to get back into it.
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?
One fools with Perl if there's legacy Perl infrastructure in production. One does not simply rewrite 20+ kloc of working Perl code into something else just because it's cool. Mojolicious is a good and elegant web framework for modern Perl. I haven't seen anything comparable except maybe in Ruby.
I know. Django is quite different, maybe Flask is sinatraish but not async afaik. Tornado is async but plain different as well and from what I've read more suited for web APIs. I'd rather use just about any modern Node.js framework than older non async frameworks for Python.
I personally think Raku is a poor choice for new projects. I've never heard of anything relatively popular built with it. I get the feeling it's quite a hobbyist platform at this point.
I'd rather use Perl 5 than Raku at the moment. At least Perl 5 has CPAN which is still somewhat alive.
It's a bit like Julia, or Java 1.3, only without the marketing behind it. It's quite capable, definitely not a hobbyst project. Too slow and missing a lot of libraries though. And yes, Perl is still a better choice.
Because of the rational math. For what it's worth it could replace Cobol, although I don't know if that's such a great thing. And maybe because it's a well designed language and a joy to program in, but we already have Ruby for that.
Perl comes from the days when interpreted programming languages were invented as concrete solutions to general problems. Now we have reusable frameworks as concrete solutions, whereas high level languages have more general use cases.
The thing about perl I still miss is the metaprogramming. It's really amazing to be able to launch a program that writes the "last mile" of code before it starts taking requests.
You can do a lot in Perl with just closures and setting package slots etc., that you would need to use macros for in say Lisps.
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.
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.
Haha, my comment was definitely tongue in cheek ;) I fully expect most of properly written Perl code to be statically parseable into an AST, save for pathological cases (and I fully expect a proper rubocop-like Perl linter to highlight such ambiguities, and would reject them in any sensible project)
I bet some younger HN readers are looking at this and wondering if the popularity off Perl at this point is primarily sentimental associations that older devs have with the early days of the Web when they could find artsy ways to explore a new emerging medium.
I disagree completely, but I'll accept that that's partly a matter of taste.
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.
That could be, but I've also noticed a sort of purism where the shell script is ideal because it can be run on any system.
(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.
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.