| ▲ | aw1621107 14 hours ago |
| > Backwards compatibility is an absolute non-negotiable for programming languages What programming language(s) satisfy this criteria, if any? |
|
| ▲ | VorpalWay 12 hours ago | parent | next [-] |
| Rust does. You have editions to do breaking changes at the surface level. But that is per crate (library) and you can mix and match crates with different editions freely. Thry do reserve the right to do breaking changes for security fixes, soundness fixes and inference changes (i.e. you may need to add an explicit type that was previously inferred but is now ambiguous). These are quite rare and usually quite small. |
| |
| ▲ | aw1621107 9 hours ago | parent | next [-] | | I'd normally agree that what you say is good enough in practice, but I question whether it meets GP's "absolute non-negotiable" standards. That specific wording is the reason I asked the question in the first place; it seemed to me that there was some standard that apparently wasn't being met and I was wondering where exactly the bar was. | |
| ▲ | loluuw 9 hours ago | parent | prev [-] | | [flagged] |
|
|
| ▲ | GhosT078 13 hours ago | parent | prev | next [-] |
| Ada does. It has been through 5 editions so far and backwards compatibility is always maintained except for some small things that are documented and usually easy to update. |
| |
| ▲ | aw1621107 13 hours ago | parent | next [-] | | I'd normally be inclined to agree that minor things are probably good enough, but "absolute non-negotiable" is a rather strong wording and i think small things technically violate a facial reading, at least. On the other hand, I did find what I think are the relevant docs [0] while looking more into things, so I got to learn something! [0]: https://docs.adacore.com/gnat_rm-docs/html/gnat_rm/gnat_rm/c... | |
| ▲ | cogman10 13 hours ago | parent | prev [-] | | > except for some small things that are documented I can't think of any established language that doesn't fit that exact criteria. The last major language breakage I'm aware of was either the .Net 2 to 3 or Python 2 to 3 changes (not sure which came first). Otherwise, pretty much every language that makes a break will make it in a small fashion that's well documented. |
|
|
| ▲ | gethly 13 hours ago | parent | prev | next [-] |
| Go, PHP, Ruby, JavaScript ... I'd say majority, actually. |
| |
| ▲ | aw1621107 13 hours ago | parent | next [-] | | It's probably borderline due to the opt-in mechanism, but Go did make a technically backwards-incompatible change to how its for loops work in 1.22 [0]. PHP has had breaking changes [1]. Ruby has had breaking changes [2] (at the very least under "Compatibility issues") Not entirely sure whether this counts, but ECMAScript has had breaking changes [3]. [0]: https://go.dev/blog/loopvar-preview [1]: https://www.php.net/manual/en/migration80.incompatible.php [2]: https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-rele... [3]: https://tc39.es/ecma262/2025/#sec-additions-and-changes-that... | | |
| ▲ | kbolino 10 hours ago | parent | next [-] | | The interesting thing about Go's loopvar change is that nobody was able to demonstrate any real-world code that it broke (*1), while several examples were found of real-world code (often tests) that it fixed (*2). Nevertheless, they gated it behind go.mod specifying a go version >= 1.22, which I personally think is overly conservative. *1: A great many examples of synthetic code were contrived to argue against the change, but none of them ever corresponded to Go code anyone would actually write organically, and an extensive period of investigation turned up nothing *2: As in, the original behavior of the code was actually incorrect, but this wasn't discovered until after the loopvar change caused e.g. some tests to fail, prompting manual review of the relevant code; as a tangent, this raises the question of how often tests just conform to the code rather than the other way around | | |
| ▲ | aw1621107 9 hours ago | parent [-] | | You certainly won't find me arguing against that change, and the conservatism is why I called it borderline. The only reason I bring it up is because of the "absolute non-negotiable" bit, which I took to probably indicate a very exacting standard lest it include most widespread languages anyways. | | |
| ▲ | kbolino 9 hours ago | parent [-] | | Yes, I think it's also a good example of how "absolute" backwards compatibility is not necessarily a good thing. Not only was the old loopvar behavior probably the biggest noob trap in Go (*), it turned out not to be what anyone writing Go code in the wild actually wanted, even people experienced with the language. Everyone seems to have: a) assumed it always worked the way it does now, b) wrote code that wasn't sensitive to it in the first place, or c) worked around it but never benefitted from it. *: strongest competitor for "biggest noob trap" IMO is using defer in a loop/thinking defer is block scoped | | |
| ▲ | aw1621107 8 hours ago | parent [-] | | Strongly agree there. IMO breaking backwards compatibility is a tradeoff like any other, and the flexibility non-hardline stances give you is handy for real-world situations, |
|
|
| |
| ▲ | gethly 12 hours ago | parent | prev [-] | | There is no such thing as perfection in the real world. Close enough is good enough. | | |
| ▲ | aw1621107 9 hours ago | parent [-] | | I'd normally agree with you in practice, but since "close enough" seems likely to cover most mainstream languages in use today I figured "absolute non-negotiable" probably was intended to mean a stricter standard. |
|
| |
| ▲ | SideburnsOfDoom 11 hours ago | parent | prev [-] | | Yes, most of them. C# for instance isn't such a "small language", it has grown, but code from older versions, that does not use the newer features will almost always compile and work as before. breaking changes are for corner cases, e.g. https://github.com/dotnet/roslyn/blob/main/docs/compilers/CS... | | |
| ▲ | aw1621107 9 hours ago | parent [-] | | The thing is that "most of them" seems incongruous with a demand for "absolute non-negotiable" backwards compatibility. If not for that particular wording I probably wouldn't have said anything. |
|
|
|
| ▲ | speed_spread 13 hours ago | parent | prev [-] |
| Java rules here. You can take any Java 1.0 (1995) codebase and compile it as-is on a recent JDK. Moreover, you can also use any ancient compiled Java library and link it to modern Java app. Java source and bytecode backward compatibility is fantastic. |
| |
| ▲ | cogman10 13 hours ago | parent | next [-] | | * Terms and conditions apply Java is very good here, but (and not totally it's fault) it did expose internal APIs to the userbase which have caused a decent amount of heartburn. If your old codebase has a route to `sun.misc.unsafe` then you'll have more of a headache making an upgrade. Anyone that's been around for a while and dealt with the 8->9 transition has been bit here. 11->17 wasn't without a few hiccups. 17->21 and 21->25 have been uneventful. | |
| ▲ | aw1621107 13 hours ago | parent | prev [-] | | Java has had some breaking changes (e.g., [0, 1]), though in practice I have to say my experience tends to agree and I've been fortunate enough to never run into issues. [0]: https://stackoverflow.com/q/1654923 [1]: https://news.ycombinator.com/item?id=28542853 |
|