I sometimes participate in the Advent of Code competition, and have always used Ada in the past. In 2023, Jeremy Grosser at the ada-lang.io forums invited discussion of solutions in other languages with "a focus on safety or reliability." That gave me the idea to try translating the Ada solutions I devised into Rust and Modula-2.
I've detailed a few observations here and there, but they were all on a puzzle-by-puzzle basis. Now that I've completed them all in Ada and Rust, I'd like to step back and take a more general, "higher-level" view.
To that end, I decided to highlight code snippets for four common tasks, datatypes, or techniques. The choice of topic is obviously subjective, but I'll try to restrain my commentary to what's necessary to understand, as well as some distinctive features I'm aware of in each language's approach. Otherwise, I'll avoid talking about personal preference.
Ada is a general-purpose language with an emphasis on safe, secure programming. It has a well-established niche in situations where correctness, reliability, and large-scale development are the primary concern. Its initial, international development culminated in an 1983 ISO standard. Subsequent revisions to the language led to new standards in 1995, 2002, 2007, 20012, and 2022. Ada revisions tend to be backwards compatible; every now and then I'll read someone write with pleasure that he's taken an old Ada 83 codebase and successfuly recompiled it in Ada 2012 (say) with little to no effort. A dialect of Ada called Spark offers additional features and guarantees, subject to a number of restrictions on what you can do. Spark is a pretty big deal in the Ada world.