This one sentence should be guiding principle for any set of recommendations. Programmers should tape it to the top of their monitor. Programs difficult to reason about are hard to get working and hard to debug and hard to maintain.
In my opinion, this is the key requirement of "good" or clean code. Likewise, programming languages that facilitate this are "better" programming languages.
Depending upon the goals of a program there can be other important requirements (for example, efficiency), but however the program is constructed it should be as easy to reason about as possible given the constraints imposed by these other requirements.
Recognizing this, I tend to pick programming languages that make my programs easier to reason about and tend to program in a style that makes informal reasoning easier. For kernel development, programming in C was appropriate (back when I was doing it) because I needed to know exactly what was going on in the machine in response to the code. At the other end of the scale, straightforward Python code often results in such short programs that they fit entirely on one screen and are consequently easy to understand and reason about.
This style of programming has led me to be very impatient with the "keep debugging" until you think it works style of development. I tend to think that each bug found is evidence of the presence of more bugs.
>> Programs difficult to reason about are hard to get
>> working and hard to debug and hard to maintain.
Actually reasoning and maintaining often are at the opossing ends. The code which is easy to reason about tends to be low on abstractions and tightly coupled, so changes become much more difficult. More modular code is harder to reason about but the changes can be introduced easily.Well said (currently programming by dead reckoning).
Therefore write everything in Prolog.