Hacker News new | ask | show | jobs
by drmeister 1677 days ago
I like the term "Eternal Language" - programming languages where if you write code now - you will be able to compile and use that code ten years from now (a software lifecycle eternity). Common Lisp, C, C++, Fortran, (edit: Java) are close to eternal languages. After losing a huge amount of Python 2 code (I wasn't going to rewrite it) I implemented Clasp, a Common Lisp implementation that interoperates with C++ (https://github.com/clasp-developers/clasp.git) so that I can write code that will hopefully live longer.

I am one of the few software developers with code that I wrote 27 years ago that is still in active use by thousands of computational chemistry researchers (Leap, a frontend for the computational chemistry molecular dynamics package AMBER, implemented in C).

15 comments

In the realm of spoken languages, they say for a language to become immortal, it has to die. Latin is the classic example of this. Languages that continue to evolve will continue to "break" so to speak.

In this vein, Standard ML (SML) is truly immortal, because the standard is set and it is "finished".

Just a fun thought!

Until "modern classics" education became a thing, Latin was arguably a still living language, if in limited use (mainly among the clergy, certain professions and educated circles, and effectively official language of certain countries).

Then ~17th century modern classics turned latin education into navel gazing on the topic of bunch of roman republic/empire era works, and disregarded actually using it.

If I remember correctly there were still some scientific works being published in Latin in the 1900s
I really enjoy modern translations like "night-club" -> "taberna nocturna".
Awesome also that this is perfect spanish.
"modern" language teaching killed Latin

before that they were teaching it without any stress on grammar, mostly memorizing phrases and short sentences and learning how to use it

Common Lisp's extreme extensibility thanks to macros means new features can be added without breaking the standard.
Firstly, programming languages are always extended when a program is written, because a program consists of new definitions. This is true of SML. Any SML program consists of the language, plus that program's definition of symbols, which effectively create a local SML dialect consisting of standard SML plus the program's vocabulary.

Secondly natural language evolution isn't controlled by people who know what the are doing, or care about language immortality. They sometimes break things just for the heck of it.

Random examples:

- the "great vowel shift" in the development of English: a linguistic buggery that caused what sounds like "a" in just about any language that uses the roman alphabet, to be written using "u".

- random reassignments of meaning. For instance, the concept called "sensitivity" today was connected to the word "sensibility" just around two hundred years ago. That's pretty gratuitous; I could easily live with a branch of English which had kept it the way it was.

I could happily live with an English that didn’t accept literally to mean “not literally”.

Informal: used for emphasis or to express strong feeling while not being literally true. "I was literally blown away by the response I got."

But that English may have never existed! "Literally" has a long history of being used to mean "a kind of figuratively that is almost perceived like it's really happening" or something like that; perhaps as long as the word itself.

What I could live without is the dialect of English in which "literally" is used to explain away some figure of speech as not being a figure of speech, whereby, oops, there is actually no figure of speech to explain away.

Like "I literally just moved to this town yesterday, so I don't know my way around yet".

What is that for? Nobody suspects that you figuratively moved into this town yesterday; if you moved here just yesterday, then "I moved to this town just yesterday" is perfectly adequate.

(Now being born yesterday is a genuine figure of speech; we could make a meme in which a speech balloon next to a newborn infant's mouth makes a joke about literally having been born yesterday: that would be a valid use of literally.)

Since being blown away is a genuine figure of speech, the expression of "literally blown away" which refers to a situation which is still only figurative is a well-entrenched use of the word: hundreds of years old, I think. It says that the figure of speech is so fitting that if you imagine me being literally blown away, that is actually fairly accurate, so much so that when the inevitable film adaptation is made of my life story, special effects will necessarily hav to be used to portray it that way.

It’s just become a word of exclamation, hyperbolic at that, no? If someone literally moved to a town yesterday, they probably mean neither literally nor figuratively, but rather, just highlighting their short tenure at the new place.

I’m a bit of a language pedant, but find it difficult to argue with the society assigning new meanings to words as the language evolves. Modern English is a tragically malformed and bastardised version of Saxon mixed with French, after all.

You'd have to go quite a ways back for that one.

Charles Dickens, "Nicholas Nickleby" -- "[h]is looks were haggard, and his limbs and body literally worn to the bone"

We can look at it like this: kidding and hyperbole aren't bad grammar. Limbs could literally be worn to the bone; that they are actually not isn't a matter of grammar.

The character is fictitious in the first place, so we could argue that "his looks were haggard" is misusing the word were, since were may only refer to a person that existed. :)

Damn, great vowel shift sucks.

Learning English in school was really weird.

Finnish as a language is almost entirely pronouncially composable. If you know how every single letter is pronounced, you can also pronounce any word.

In English there are all these silent letters, different pronounciations depending on the position of the letter etc. And the vowel shift: "a" written as "u", "ai" written as "i", "i" written as "e" etc.

>Finnish as a language is almost entirely pronouncially composable.

So is Sanskrit. It is supposed be one of the most logically-designed languages.

>If you know how every single letter is pronounced, you can also pronounce any word.

Again, similar in Sanskrit. Taking it further, it is perfectly acceptable to make up words of your own by combining two or more words.

I think I've recently read that the amount of Akkadian/Sumerian material is vastly more, than anything the Latin period has produced. Yet almost nobody is able to interpret it, in comparison to Latin.
There's actually been a decent amount of work on SuccessorML to add a few things to the language.
I hope that Rust joins the pantheon of eternal languages. I feel like it has a lot of the advantages of a language like C, but is just more modern and well thought through.

Also, you did not mention Java. I have very old Java code that still works fine.

Java is probably the biggest "eternal" language we have these days. Probably tied with C and C++.

There's <<so much>> Java code churned out that it's unbelievable. Business systems have a ton more code than infrastructure systems.

> Java is probably the biggest "eternal" language we have these days

Is it? I haven't followed it in years but i remember reading about people sticking with Java 8 because later versions broke backwards compatibility in some cases.

Its a bit complicated, technically java language never broke backward compatibility. you can run existing java programs fine in higher java jvm's by adding extra command line parameters to include all existing libraries in default module. But it becomes complicated by the use of intermediate tools which are not updated to handle this.
Yep, modules were a big break, however all the relevant libraries that actually matter on the Java ecosystem are available on latest versions.

Basically it is the same kind of effect like school/university teachers whose idea of C++ is C with extras, and if they teach something more close to C++98 proper even in 2021, one should consider themselves lucky.

> [java] Probably tied with C and C++.

i think java wins over c/c++, because there's very little low level, machine specific code you can do in java, where as you surely can do that in c/c++.

True, and instead of rewriting the whole stuff, if some C or C++ is actually required there is always JNI, JNA, or the upcoming Panama.
I would check on cobol first.
There's a ton more Java out there. Java is much newer but it's from a time when we're talking about tens of millions of developers worldwide, instead of tens of thousands. A lot more people have been churning out Java since 1996 than Cobol since 1955 or so.
Do you have a feeling for how many Java LOC are out there?
I've worked for a 10 person company where 5 were working on a Java backend, the app was about 10 years old. 250k lines.

I used to work for a mediocre multinational with about 50 people working on a big Java front end to their many servers. Just the frontend was about 3 million lines.

You've never heard of either of them, the multinational had a market cap of about half a billion.

I've worked for a bunch of bigger companies but I don't have numbers, I just know they had bigger systems.

I wouldn't be shocked if there are tens of billions to hundreds of billions of lines of Java in production right now. I imagine that something like half a billion are added each year.

There are so many big Java middleware companies nobody has heard of. You wouldn't even know they use Java if you wouldn't look at the job listings.

That's going to be quite a loaded metric considering how verbose Java is.
C# is also probably in a similar league, for the same reasons.
> I hope that Rust joins the pantheon of eternal languages.

I'm torn about this. On one hand, Rust is so much better than C it is ridiculous and I really hope it does become a language with decade-long longevity.

On the other hand, Rust is the first new "systems programming" language in forever and is finally prying the door open to something other than C/C++. I'm really hoping that Rust opening the door and paving the way means that now we can get something better.

What worries me about Rust is the impedance mismatch down at the very primitive hardware level--bytes and registers. The embedded guys are doing an amazing job papering over it, but the abstractions leak through quite a lot and you have to twist things around to satisfy them.

The problem is: that's a lot of fiddly code with all kinds of corner cases. So, you either have a lot of work or you throw up your hands and invoke C (like Zig does).

I'd give it another 2-5 years before the syntax settles. Some serious improvements have recently been pushed out and I wouldn't be surprised if further improvements are on the horizon.
editions still allow backwards compatibility though, it's not like the syntax changes will break it
Rare example of broken backward compatibility: `cargo install gltf-viewer` doesn't work today because of an error in gltf library. The error is fixed, but gltf-viewer is not updated to use the fix.

   Compiling gltf v0.11.3
  error[E0597]: `buf` does not live long enough
   --> /home/vlisivka/.cargo/registry/src/github.com-1ecc6299db9ec823/gltf-0.11.3/src/binary.rs:225:35
      |
  119 | impl<'a> Glb<'a> {
      |      -- lifetime `'a` defined here
  ...
  225 |                     Self::from_v2(&buf)
      |                     --------------^^^^-
      |                     |             |
      |                     |             borrowed value does not live long enough
      |                     argument requires that `buf` is borrowed for `'a`
  ...
  233 |             }
      |             - `buf` dropped here while still borrowed
I'd like it to be so, but i dont have faith for it. rust doesnt have a standard like lisp/c/c++ and it stands to those languages for their eternality, and at least with lisp and C their relative simplicity makes all the difference for something like that. they feel like, despite how opposite they are, discoveries rather than inventions when compared to something so complex like rust and c++
I don’t think Rust will (at least not in current form). It’s breaking too much ground in the (real world) PL-design space. We just don’t know what really work yet!
Eh; sum types, everything-is-an-expression, and composition over inheritance get you very very far toward optimal language design. Sure there are some potential economic improvements that could made to Rust, but the foundation is so strong that I don’t see anything that makes those same design decisions supplanting Rust. More likely that a new Rust edition would incorporate those kinds of changes.
Java is younger than Python.
But Java 1.0 code is still (mostly) compile-able on recent Java versions, not so much with Python where I'd worry about going back 5 years.
Many Python developers and users were burned when the Python project decided to set fire to billions of lines of code.

I have zero trust in Python as far as code longevity is concerned.

More like trillions of lines of code, from probably millions of developers, dating back to the 90's.

"The total code size of Zope 2 and its dependencies has decreased by over 200,000 lines of code as a result." - from the 2013 Zope documentation... how many lines of code was it before then?

Python really burned its bridges. It's shown that it's a toy language now, and demonstrably unfit for any real production-quality projects.

> how many lines of code was [Zope] before then?

Soooo many. Zope was a very formidable code base to delve into. I was trying to learn it because my company was using Plone, and Zope quickly surfaced through the abstractions.

Zope's codebase might have been more accessible if type annotations were a thing back then. Their implementation of "interfaces" for Python were very interesting back in the Python 2.3 days.

I disagree that Python is a "toy" language now. It started out as one, and has been stumbling awkwardly away from that ever since the mid 2000s - virtualenvs, pip, pyenv, pipenv/poetry, type annotations, mypy etc.

In my entirely unscientific opinion, I think it was Django that started this journey, then of course scikit, numpy leading into pandas etc.

Bullshit. 2 => 3 transition was mostly mechanical and programmers who are unable to do it should get better.

I haven't seen py2 code in several years. Granted, I would look away in disgust if I did.

Right right right. I'll let my CTO know.
I wrote code that worked with both interpreters simultaneously for many years. I don't know why you'd worry so much.
> programming languages where if you write code now - you will be able to compile and use that code ten years from now (a software lifecycle eternity)

Fun fact: code written in JavaScript in 1995 will work in 2021, after 26 years.

If you are talking about "good practices" - few weeks ago I worked with C code from 2001 and it was just awful. Yes, it compiles - but it wouldn't pass any modern code review.

> Fun fact: code written in JavaScript in 1995 will work in 2021, after 26 years.

Sure, as long as you run it in Netscape Navigator 2.0.

In 2021 you're lucky if a JavaScript web app that worked fine on Tuesday still works on Wednesday. And shocked if it works in any browser other than Chrome.

It's plainly untrue. I worked on ECMAScript proposals and TC39 takes backwards compatibility really seriously.

Browsers too take backwards compatibility very seriously and features stop working almost only if these are serious security holes.

You're right about backward compatibility - and yet so many things break anyway. And many web apps of the past only worked on Internet Explorer (much in the way that modern web apps only work on Chrome.)

However, the thing that broke Tuesday's app on Wednesday was probably a library or framework change.

That's the DOM manipulation and browser behaviors, not Javascript itself.
If you divorce JavaScript from the Dom you have removed it's entire reason for existence. So the dom is effectively part of the language. Just as the standard library is effectively part of C or Nim, etc. Without them they are considerably less useful.
You remove the reason -for its creation-. Not its reason for existence; Node is a thing, and doesn't touch the DOM. So, no, it's not effectively part of the language.
Ah, but code written in Common Lisp in 2021 will usually work in 1995, after -26 years.

:)

Aside from CL implementation bugs. The implementations had lots of them back then, even the commercial ones. Nowadays, they are much better. Decades of effort to make an implementation bug free and shiny will have its effect.
That really is amazing. Is it true, even "usually", for most types of code? Both forwards and backwards compatibility.. it's like the holy grail.
For most types of code, other than things like code which has dependencies on implementation internals (like extensions in SBCL for instance), or uses FFI to access platform libraries that didn't exist in 1995; that sort of thing.

ANSI CL was last ratified in 1994; there has been no standard language change, and the community language improvements are just macro libraries. You should be able to take your alexandria utilities library, or optima pattern matching or whatever back to 1995.

There are a few community improvements that are language extensions. The standard had no notion of multithreading, MOP was not in the standard, and packages really needed some way to avoid collisions of short package names (which lead to the de facto standardized package local nicknames.) Pathnames may also have seen some de facto standardization; they were poorly specified in the standard.
Maybe the C code was just badly written
Yep.

Use some of the -W* flags (-Wall -Wpedantic -Wconversion, ...) and specify the standard -std=c90.

Avoid undefined behaviors:

- https://en.cppreference.com/w/c/language/behavior

- https://wiki.sei.cmu.edu/confluence/display/c

(Also use cppcheck, valgrind, gdb, astyle, make, ...)

Done.

Fun fact: JS and C are both standardized by ISO.

And always use "-fwrapv -fno-strict-aliasing -fno-delete-null-pointer-checks". Those are source of the hardest to reason about UB and the small performance benefit is not worth the risk. I would love to always be certain I haven't accidentally hit UB, but that's equal to the halting problem, so for peace of mind, I just ask the compiler for a slightly safer variant of the language.

P.S. and old code definitely needs them, as at the time compilers didn't optimize so aggressively and lots of code does weird stuff with memory, shifts, etc.

Have a look at Apache 1 (C) or KDE 1 (C++); it'd be interesting to see what you think of those codebases, and they can certainly predate 2001.
Maybe it's next to impossible to write C code that isn't badly written
Or maybe we have too many developers that treat language of their choice as a religion.
>To encourage people to pay more attention to the official language rules, to detect legal but suspicious constructions, and to help find interface mismatches undetectable with simple mechanisms for separate compilation, Steve Johnson adapted his pcc compiler to produce lint [Johnson 79b], which scanned a set of files and remarked on dubious constructions.

-- https://www.bell-labs.com/usr/dmr/www/chist.html

Unfortunately since 1979, majority of C devs think they know better.

C code is of course close to the hardware, which as always, has benefits and drawbacks.
I was pretty sure that there were some subtle changes in ES5 and ES6 that were technically not backwards compatible (done because very little code depended on those behaviors)
Out of curiosity: would the 1995 JS code pass any modern code review?
I’d imagine it would get pinged for using var instead of let or const. And depending on who’s doing the review they might not like ‘new’.
>"I’d imagine it would get pinged for using var instead of let or const."

This single thing in isolation should never cast code as good or bad.

JS from 2003 passed code review for me a few months ago... so, yes... maybe.
Probably depends what it's doing. If it's interacting with HTML and manipulating the DOM then probably not
How do modern frameworks display content? Must be interacting with HTML and manipulating the DOM in some way.
It's not whether they do, it's how they do.

For instance, in 2003 there was no such thing as a mobile phone; passing code review today is probably going to entail either being responsive, or directing to a mobile version when accessed from a mobile device.

I think that to earn the title "Eternal Language" that should have to work in both directions.

If I am an expert in language X and take a solar powered laptop and go spend 10 years living as a hermit in some isolated place while working on some big X program, with no communication with the outside world other than idle non-technical chat with the people of the village I go to monthly to buy supplies, if X is an Eternal Language then

1. My code that I wrote as a hermit should build and run on the outside world's systems,

2. I should still be an expert in the language X, only needing to learn library changes, fashion changes (such as coding style changes), and tooling changes to be ready to take a job as an X programmer at the same level as I had before I became a hermit.

Alternatively, suppose I don't know X but wish to learn it. To earn the title "Eternal Language" I should be able to go into my library and read the "Learning X" book I bought 10 years ago but never got around to reading and that should mostly be equivalent to buying and reading a recently published book on X.

Go is another that strives for backwards compatibility: https://golang.org/doc/go1compat

After seeing the Perl5/6 schism, I was hopeful that the Python devs wouldn't make the same disastrous mistake, but.. the same happened with us with approximately 100k lines of Python 2 code (which we are now in the process of porting to Go and Rust), precisely for this reason.

It's exceedingly difficult to form trust in language developers who are willing to break working, production code in use all over the world for decades over a new unicode type and a few wishlist library items.

While Go strives for backwards compatibility, it's a bit too young for now at 12 years old, and already had a few changes around packaging and stuff like that. If we get to 20 years without Go 2 that will be a solid signal on the longevity of Go.
One of the newer (newer than C, C++, Common Lisp, ...) languages I feel comfortable about regarding this is Go. Definitely feels like I can write a simple Go program to generate a static website for example and it'll probably still work in that same state for a while.
It’s hard to say with any 1.x versions what’ll happen come 2.x
True, but... most languages wouldn't be on version 1.x after the amount of time (and progress) that Go has. Go has a track record by now, of being very careful about breaking things, and providing tools to help fix them when they do.

Sure, Go could introduce breaking changes in 2.x. Will they? Track record says "no".

As far as I can tell, the only reason for a Go 2 (as opposed to a Go 1.nnnn) is "we introduced a breaking change". Things that were considered "Go 2" are being worked in, as the language evolves, without the need to break previously written code.
Maybe Lua? Started in 1993 and LuaJIT is effectively frozen. I could see this one hanging in for a long time as the goto embedded language.
Interestingly, Perl doesn't get a lot of love on HackerNews but I would classify it in the family of "eternal languages."
Even after the Perl 5 / Perl 6 / Raku debacle? Many developers left after that (Python pulled off the same trick a decade later.. apparently some language teams have very short memories.)
Said debacle arguably reinforced Perl 5's eternity, if anything.
Especially after de Perl5/6 debacle. The two separate languages solution let them have fun on Raku, all the while ensuring that Perl 5/7/... will preserve retrocompatibility.
Some of that code has been running for a long time. A lot of the Perl toolchain still works on 5.8.1 (released Sept 2003).

https://metacpan.org/release/JHI/perl-5.8.1

Test::Simple still targets 5.6.2, which looks to have been released around the same time (November 2003).

https://metacpan.org/release/RGARCIA/perl-5.6.2

I have quite a bit of personal scripting in perl that I wrote in the early 90s, still in use every week. Haven't changed any of the code in decades.
C/C++ languages are stable, but building actual software with them is extremely cumbersome on future systems. It is unlikely to "just work" because of how we have inverted the dependency structure of the vast majority of C/C++ programs.
Ehhh. Integrating an old C++ library into a new project may be difficult due to build systems or not useful due to dependencies.

However if you want to take an old C++ game written in 2004 and ship it on modern platforms and consoles you only need to update a very small amount of platform specific code.

Updating a 20 year old C++ project is probably easier than updating a 3 year old web app.

Tbf if you’re just looking to run an app on newer platforms you’d likely not need to do anything with the web app. They have a lot of issues but once stuff works it’s usually a very long time before it doesn’t.

It would probably still be harder to add a new dependency to a 3 year old web app than it would be to integrate a 20yo C++ project though, I agree with you there.

imo that would be a "forever program" not really a "forever language." The lack of standard packaging and terrible paradigm of shared dependencies has made C/C++ incredibly fragile and non-portable when you need something from years ago to compile today.
JavaScript probably qualifies, too. It's not going anywhere for a very long time, if ever. Same with COBOL. COBOL will have to be killed with fire.

I'm assuming here that "eternal language" doesn't necessarily mean "good language". :-)

Unfortunately JavaScript code is often built on DOM and NPM quicksand.
How do you lose Python 2 code? The old interpreter still works.
But is no longer viable option for new work, and in this case a lot of the code IIRC was libraries for writing programs.
> "Eternal Language"

Even more than being able to compile and run it in a few decades (which is awesome) there is also the part that such eternal language ecosystems grow excellent tooling (debuggers, tracing, performance analysis, source tooling, build tooling, library maturity, etc) thanks to the stable platform and all the years dedicated to making it all ever better.

I greatly dislike the language of the year hype not so much because the language change itself, but because all the wonderful mature tooling doesn't exist in the new shiny thing so we're back to debugging via print and performance analysis via guesswork.

The only place LISP is eternal is on HN. A super-microscopic minority of engineers use it for real-world software development. The standard hasn't been updated for 2 decades. There is only one real compiler implementation. No WASM. No proper mobile support. Library support for real world tasks is abysmal.

Common LISP's tomb is indeed shiny and eternal. Developers at HN will mourn at its graveyard for eternity.

> There is only one real compiler implementation

what kind of meaning of 'real' reduces the several compiler implementations to just one?

Example: I use two native code compilers (SBCL and LispWorks) on my Mac. Both are available on other platforms, too. Is one of those not 'real'?

What about, say, ECL or Allegro CL? Are they unreal?

I honestly think most languages belong to this category. I can't really think of a language that changed so much that old code no longer works (other than python 2 -> python 3).
was it you that said that the difference between writing templates in c++ and writing macros in common lisp is like the difference between filling out tax forms and writing poetry :)