Perl's "decline" saved it from a fate worst than death: popularity and splitting into dozens of incompatible versions from added/removed features (like python). Instead Perl is just available everywhere in the same stable form. Scripts always can just use the system perl interpreter. And most of the time a script written in $currentyear can run just as well on a perl system interpreter from 2 decades ago (and vice versa). It is the perfect language for system adminstration and personal use. Even if it isn't for machine learning and those kinds of bleeding edge things that need constant major changes. There are trade-offs.
This kind of ubiquitous availablility (from early popularity) combined with the huge drop-off in popularity due to raku/etc, lead to a unique and very valuable situation unmatched by any other comparable language. Perl just works everywhere. No containers, no dep hell, no specific versions of the language needed. Perl is Perl and it does what it always has reliably.
Perl's binary brings with it the ability to run every release of the language, from 5.8 onwards. You can mix and match Perl 5.30 code with 5.8 code with 5.20 code, whatever, just say "use v5.20.0;" at the start of each module or script.
By comparison, Python can barely go one version without both introducing new things and removing old things from the language, so anything written in Python is only safe for a a fragile, narrow window of versions, and anything written for it needs to keep being updated just to stay where it is.
Python interpreter: if you can tell "print" is being used as a keyword rather than a function call, in order to scold the programmer for doing that, you can equally just perform the function call.
> By comparison, Python can barely go one version without both introducing new things and removing old things from the language
Overwhelmingly, what gets removed is from the standard library, and it's extremely old stuff. As recently as 3.11 you could use `distutils` (the predecessor to Setuptools). And in 3.12 you could still use `pipes` (a predecessor to `subprocess` that nobody ever talked about even when `subprocess` was new; `subprocess` was viewed as directly replacing DIY with `os.system` and the `os.exec` family). And `sunau`. And `telnetlib`.
Can you show me a real-world package that was held back because the code needed a feature or semantics from the interpreter* of a 3.x Python version that was going EOL?
> Python interpreter: if you can tell "print" is being used as a keyword rather than a function call, in order to scold the programmer for doing that, you can equally just perform the function call.
No, that doesn't work because the statement form has radically different semantics. You'd need to keep the entire grammar for it (and decide what to do if someone tries to embed a "print statement" in a larger expression). Plus the function calls can usually be parsed as the statement form with entirely permissible parentheses, so you have to decide whether a file that uses the statement should switch everything over to the legacy parsing. Plus the function call affords syntax that doesn't work with the original statement form, so you have to decide whether to accept those as well, or else how to report the error. Plus in 2.7, surrounding parentheses are not redundant, and change the meaning:
$ py2.7
Python 2.7.18 (default, Feb 20 2025, 09:47:11)
[GCC 13.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print('foo', 'bar')
('foo', 'bar')
>>> print 'foo', 'bar'
foo bar
The incompatible bytes/string handling is also a fundamental shift. You would at least need a pragma.
> Can you show me a real-world package that was held back because the code needed a feature or semantics from the interpreter
That is not what I was getting at. What I was saying is that, if you write code for perl 5.20 and mark it "use 5.20.0;", then that's it, you're done, code never needs to change again. You can bring in newer perl interpreters, you can upgrade, it's almost certainly not going to break.
You can even write new code down the line in Perl 5.32 which wouldn't be possible in 5.20, and the 5.20 code wouldn't be valid in 5.32, but as they're both declaring which version of the language they're written in, they just seamlessly work together in the same interpreter.
Compared to Python's deliberate policy, which is they won't guarantee your code will still run after two minor releases, and they have a habit of actively removing things, and there's only one version the interpreter implements and all code in the same interpreter has to be be compatible with that version... it means a continual stream of having to update code just so it still runs. And you don't know what they're going to deprecate or remove until they do it, so it's not possible to write anything futureproof.
> in 2.7, surrounding parentheses are not redundant,
That is interesting, I wasn't aware of that. And indeed that would be a thorny problem, moreso than keeping a print statement in the grammar.
Fun fact: the parentheses for all function calls are redundant in perl. It also flattens plain arrays and does not have some mad tuple-list distinction. These are all the same call to the foo subroutine:
> Compared to Python's deliberate policy, which is they won't guarantee your code will still run after two minor releases
They don't guarantee that the entire standard library will be available to you two minor releases hence. Your code will still run if you just vendor those pieces (and thanks to how `sys.path` works, and the fact that the standard library was never namespaced, shadowing the standard library is trivial). And they tell you up front what will be removed. It is not because of a runtime change that anything breaks here.
Python 3 has essentially prevented any risk of semantic changes or syntax errors in older but 3.x-compatible code. That's what the `__future__` system is about. The only future feature that has become mandatory is `generator_stop` since 3.7 (see https://peps.python.org/pep-0479/), which is very much a corner case anyway. In particular, the 3.7-onward annotations system will not become mandatory, because it's being replaced by the 3.14-onward system (https://peps.python.org/pep-0649/). And aside from that again the only issue I'm aware of (or at least can think of at the moment) is the async-keyword one.
> And you don't know what they're going to deprecate or remove until they do it
This is simply untrue. Deprecation plans are discussed in public and now that they've been burned a few times, removal is scheduled up front (although it can happen that someone gives a compelling reason to undo the deprecation).
It's true that you can't make your own code, using the standard library (which is practically impossible to avoid), forwards-compatible to future standard libraries indefinitely. But that's just a matter of what other code you're pulling in, when you didn't write it in the first place. Vendoring is always an option. So are compatibility "forward-ports" like https://github.com/youknowone/python-deadlib. And in practice your users are expecting you to put out updates anyway.
And most of them are expecting to update their local Python installations eventually, because the core Python team won't support those forever, either. If you want to use old FOSS you'll have to accept that support resources are limited. (Not to mention all the other bitrot issues.)
Well isn't that nice. The boxes I care most about are 32 bit. The perl I use is 5.0 circa 2008. May you amiga386, or anyone else, thank you in advance, may be able to tell me what do I need to upgrade to perl 5.8?
Is it only perl 5.8 and whatever is the contemporaneous gcc? Will the rest of
my Suse 11.1 circa 2008, crunch? May I have two gcc's on the same box/distro version,
and give the path to the later one when I need it? The reason I am still with
Suse 11.1, is later releases broke other earlier things I care about, and I could not fix.
What incompatible versions of pythons do you mean? I'm entirely unaware of any forks, and the youngest version I have to supply at the moment is 3.9, which is over 5 years old and available in all supported platforms.
Try to run any random python program of moderate dep use on your python 3.9 system interpreter without using containers. Most likely you'll have to use a venv or the like and setup a special version of python just for that application. It's the standard now because system Python can't do it. In practice, pragmatically, there is no Python. Only pythons. And that's not even getting in to the major breakages in point version upgrades or the whole python 2 to 3 language switch.
> Most likely you'll have to use a venv or the like and setup a special version of python just for that application.
Using venvs is trivial (and orders of magnitude more lightweight than a container). And virtually every popular package has a policy of supporting at least all currently supported Python versions with each new release.
You need to set up a venv because of how the language is designed, and how it has always worked since the beginning. Python doesn't accommodate multiple versions of a package in the same runtime environment, full stop. The syntax doesn't provide for version numbers on imports. Imports are cached by symbolic name and everyone is explicitly expected to rely on this for program correctness (i.e., your library can have global state and the client will get a singleton module object). People just didn't notice/care because the entire "ecosystem" concept didn't exist yet.
I have at least one local from-source build of every Python from 3.3-3.14 inclusive (plus 2.7); it's easy to do. But I have them explicitly for testing, not because using someone else's project forces me to. The ecosystem is just not like that unless perhaps you are specifically using some sort of PyTorch/CUDA/Tensorflow related stack.
> It's the standard now because system Python can't do it.
Your system Python absolutely can have packages installed into it. The restrictions are because your Linux distro wants to be able to manage the system environment. The system package manager shouldn't have to grok files that it didn't put there, and system tools shouldn't have to risk picking up a dependency you put there. Please read https://peps.python.org/pep-0668/, especially the motivation and rationale sections.
> major breakages in point version upgrades
I can think of exactly one (`async` becoming a keyword, breaking Tensorflow that was using it as a parameter name). And they responded to that by introducing the concept of soft keywords. Beyond that, it's just not a thing for your code to become syntactically invalid or to change in semantics because of a 3.x point version change. It's just the standard library that has changes or removals. You can trivially fix this by vendoring the old code.
> And that's not even getting in to the major breakages in point version upgrades or the whole python 2 to 3 language switch.
Python doesn't use semver and never claimed to do so, but it's probably worth treating "x.y" releases as major versions in their own right (so like 2.7 -> 3.0 is a major version and so 3.10 -> 3.11). If you do that, the versioning makes a bit more sense
How old are you now? Mid fifties here. And 'vibe coding' in what exactly - it is not of interest from a programming perspective, but from a 'what does the AI know best perspective'? I've followed a similar, but not identical trajectory and now vibe in python/htmx/flask without needing to review the code in depth (NB internal apps, not public facing ones), with claude code max. Vibe coding in the last 6-8 weeks now also seems to make a decent fist of embedded coding - esp32/arduino/esp-32, also claude code.
35–44. Same thing, sometimes it makes planning errors, or misses context that should be obvious based on the files, but overall a huge booster. No need to review in depth, just set it against tests and let it iterate. So much potential, so exciting.
My feeling is the current suite of LLMs are "not smarter than US" they simply have far greater knowledge, unlimited focus, and unconstrained energy (modulo plan/credits/quotas of course!). I can't wait for the AIs that are actually smarter than us. Exciting to see what they'll do.
This kind of ubiquitous availablility (from early popularity) combined with the huge drop-off in popularity due to raku/etc, lead to a unique and very valuable situation unmatched by any other comparable language. Perl just works everywhere. No containers, no dep hell, no specific versions of the language needed. Perl is Perl and it does what it always has reliably.
I love it. The decline was a savior.