**preface** My priorities are safety, legibility, and expressiveness, in that 
order. I can program in C and C++, but I much prefer _readable_ languages where 
the compiler identifies as many errors as possible before you run it, because 
debugging sucks, and debugging languages that thinks safety and readability are 
signs of weakness is... better left unsaid.

_Languages I like_ (in alphabetical order)

**Ada** : C++ has spent 30+ years trying unsuccessfully to make C as featured 
_and safe_ as Ada 83 (exceptions, generics, multitasking, ability to write 
large, nontrivial programs without pointers, modules, ... oh, wait, C++ _still_ 
doesn't have modules, and on and on...) while still looking like C, because `a 
= (b < c) ? d : e;` is so much more desirable than `a := (if b < c then d else 
e);` or something. Ada 95 was the first ISO-standardized language with 
object-oriented features. Ada 2012 has Design By Contract. A dialect of Ada 
called SPARK offers the ability to prove a program meets specifications laid 
out in DBC and/or pragmas. When Ada came out, people objected that it was too 
complicated, so today we program with even more complicated languages that 
offer fewer features, and no one knows Ada still exists and probably powers the 
airplane you flew to that last FLOSS conference, so companies cannot find Ada 
programmers, so they are switching to other languages which are less safe but, 
hey, the kids coming out of universities these days don't like reading and 
would rather match curly braces, so what can we do? (Yes, I have heard kids 
coming out of universities say that they don't like languages that don't use 
curly braces, with no further reasoning on the matter.)

**Kotlin** (please don't kill me): A better Java than Java. Lots less 
boilerplate. Free & great tooling. The use of `in` and `out` types for 
generics. A serious and almost successful attempt at `null` safety. I only 
learned Kotlin because the choices in Android Studio are Java and Kotlin, so I 
decided to try Kotlin I've never gone back to Java. Kotlin Native may or may 
not turn out to be a thing one day, too.

**Modula-2** : Like others, I learned with Pascal; Modula-2 was Wirth's systems 
programming language, and back in the early 90s the only options I had on an 
Amiga were Modula-2, Oberon-2, and C. I couldn't find learning material on 
Oberon (really) so Modula-2 it was. It was elegant, powerful, and -- given the 
options -- the safest language available.

**Modula-3** : Modula-3 was from DEC, inspired by Modula-2 but different. 
Surprisingly good, frustratingly boneheaded at times (you have to jump through 
far too many hoops to instantiate a generic modules), but whenever I finished 
writing a Modula-3 program, I always felt as if I'd had fun and wanted to do 
more.

**Nim** : Do I have to explain this on a Nim forum?

_Language that was a sore disappointment_ (not asked, but some people are 
writing this anyway)

**Oberon** : [Not to be confused with Oberon-2, which is similar] In principle 
there's a lot to like, but after working through much of Wirth's Compiler 
Construction textbook with Oberon I found myself increasingly frustrated by 
choices that were made for the compiler writer's convenience, even when they 
wouldn't have cost much. Maybe it was unfair because by the time I learned 
Oberon I'd learned a lot of other OO languages, but, for instance:

  * There is no way to initialize an object automatically; you must always 
manually initialize, e.g., `o := NEW(T); o.Init;`
  * Arrays of unknown size are allowed only as parameters to procedures, and 
you cannot allocate an array whose compile-time size is not known except 
through gruesome hacks. That is, you can do `TYPE T=ARRAY 10 OF INTEGER; VAR a 
: POINTER TO T; BEGIN a := NEW(T); END` but not `TYPE T=ARRAY OF INTEGER; VAR a 
: POINTER TO T; BEGIN a := NEW(T, 10); END` or something similar. Some Oberon 
fans claim this defect is evidence of the language's brilliant design, but it's 
important enough that at least two compilers I examined introduced a 
`SYSTEM.NEW` command to do this... and each implemented it differently.
  * In an attempt to minimize the language, some machine-level commands are in 
the language proper, such as `LSL` and `ASR`, but others are consigned to the 
`SYSTEM` module, which you are warned to avoid if you want to write portable 
programs. In particular, masking an `INTEGER` requires you to convert it to a 
`SET` via `SYSTEM.VAL`, use the `*` operator with another `SET`, then convert 
back. All this just to avoid using the `&` operator on integers?
  * Speaking of which, why `&` instead of `AND`? After all, `OR` gets its own 
keyword. What happened to the aim of readability?
  * In the command `o.method()`, `o` is not automatically passed to `method()` 
as an argument, so you have to write `o.method(o)`, which grows really tiresome 
after a while, especially if you use name variables according to their purpose 
rather than just `s`, `o`, etc. (Amazingly to me, Wirth usually uses 
single-letter variable names.)
  * The language specification is maintained at Wirth's website. It keeps 
changing, and often it seems as if the changes are done entirely for Wirth's 
convenience. For example, he recently took up an interest in drones, and rather 
than submit to his own medicine ("as simple as possible, but no simpler") [he 
added a couple of 
keywords.](https://inf.ethz.ch/personal/wirth/Oberon/Oberon.ARM.Compiler.pdf) 
\-- **In fairness** , my understanding is that Wirth comes from a school of 
thought where languages were supposed to be specified as minimally as possible, 
but extended in practice, and he hated the complexity of Modula-2's compiler. 
So, rather than add parallelism to Oberon, researchers at ETH developed an 
extension called Concurrent Pascal.


Reply via email to