I remember learning perl in the early 90s, it was perl 4 at the time, and it opened up a whole class of possibilities by its incredible expressivity, things you wouldn't otherwise do because they'd be far too tedious in C and not really doable in sh or awk. Then perl5 came and extended it into a fully fledged programming language with modules, data structures, closures, the whole lot. And CPAN was unequalled for very long.
Over time I picked up php, python and node, but to this day my personal scripts are done in perl, and lots of command-line file wrangling starts with "perl -En".
I think two very early decisions doomed perl's ultimate future, and they were too ingrained in the language to ever change without losing compatibility. One is the shifting sigils, accessing @x with $x[3] instead of the logical @x[3]. The second is auto-flattening, where foo(@a) passes the contents of @a as separate arguments instead of @a as a single thing. Fixing these was so incompatible that the attempt turned into Perl6/Raku, which went way overboard in terms of design and failed to catch on. Meanwhile other dynamic languages converged on the better design of having containers be objects, and flattening done by an explicit operator.
I think perl has done a very decent job at turning into a legacy language, which was the right direction given the constraints. The maintainers have prioritized compatibility to a high level, while still slowly fixing whatever pain points they could, including finally adding function signatures (!).
> One is the shifting sigils, accessing @x with $x[3] instead of the logical @x[3]
$x[3] is perfectly logical when you think of the sigil as typing the value and not the variable. They're basically one-char cast/convert operators. Auto-flattening is less defensible. It was easier for me to intuit because @foo looks like a list splice in lisp and MOO code, so anywhere you see @foo in args, you can assume it's spliced in ... but then there's prototypes that change that. Yeah.
These just made Perl weird but they didn't reduce its power or expressivity. It was things like only having a single scalar type, or not even having named args without crazy shit like Devel::Declare that always had me looking for greener pastures.
Nowadays I spend most of my time writing PHP and TS. PHP is reasonably pleasant since the 8.x days, but I wish it had generics. And talk about having to crawl out from under a pile of bad legacy decisions...
> > One is the shifting sigils, accessing @x with $x[3] instead of the logical @x[3]
> $x[3] is perfectly logical when you think of the sigil as typing the value and not the variable.
Unfortunately, that doesn't match the intuition of most programmers. It's more natural to think of the scalar variable as having the full name "$x" and the list variable having the full name "@x", since IIRC both can exist at the same time. Having "$x[3]" access the "@x" variable, when a "$x" variable already exists in the same place at the same time, is just plain confusing. Add to that the very similar looking "$x->[3]" syntax, which accesses the "$x" variable and not the "@x" variable (unless you made "$x" a reference to "@x"), and it becomes even less obvious.
Perl has lots of weirdness, that's not surprising to anyone. It's still quite consistent in how it interprets sigils though, even if it's irritating (I don't find stuff like "@{$foo->{bar}}" all that beautiful either). It's not like there was some universal norm around sigils, programmers intuition is informed by the languages they actually use.
List and scalar context make plenty of sense once you wrap your head around them.
Of course it took me learning XS and using Perl as an extension language (Lua was brand new and the Python GIL was a dealbreaker) to fully understand Perl lists, so yeah.
Over time I picked up php, python and node, but to this day my personal scripts are done in perl, and lots of command-line file wrangling starts with "perl -En".
I think two very early decisions doomed perl's ultimate future, and they were too ingrained in the language to ever change without losing compatibility. One is the shifting sigils, accessing @x with $x[3] instead of the logical @x[3]. The second is auto-flattening, where foo(@a) passes the contents of @a as separate arguments instead of @a as a single thing. Fixing these was so incompatible that the attempt turned into Perl6/Raku, which went way overboard in terms of design and failed to catch on. Meanwhile other dynamic languages converged on the better design of having containers be objects, and flattening done by an explicit operator.
I think perl has done a very decent job at turning into a legacy language, which was the right direction given the constraints. The maintainers have prioritized compatibility to a high level, while still slowly fixing whatever pain points they could, including finally adding function signatures (!).