You ignore the fact that different projects have different requirements. You're advocating for languages with less choice / more rigidity without considering what you want to build. If I build an OS, I need a language that is fast and offers low level access to resources like memory, cpu and other hardware. If I build a control unit for a nuclear reactor, I want a very rigid language. If I'm an early startup, more flexible languages and frameworks like nodejs or ruby on rails are good fits because they allow me to move and iterate fast. Once I reach a series B it's time to think about a stricter approach.

It's ok "to produce a higher-than-average amount of poor-quality code" if speed is more important than quality.

Btw I don't think Kotlin falls into that "higher-than-average amount of poor-quality code" category. It's a statically typed language which puts it on the better side of the dynamically types languages like JS, Ruby, Python etc. Kotlin also produces "less-than-average of poor quality code" than Java (Java vs. Kotlin is the comparison the original article made). Java has a ton of pitfalls and does require "to familiarize themselves with a thousand concepts before the day they sit down and attempt to write production code" to avoid those pitfalls...

E.g these two statements produce different results (why?):

System.out.println("Test" == "Test");

System.out.println(new String("Test") == new String("Test"));

Or this doesn't alter myString:

myString.concat("Test");

Or this creates an endless loop:

for (int i = Integer.MAX_VALUE - 10; i <= Integer.MAX_VALUE; i++) {

System.out.println("i=" + i);

}

Kotlin's null type safety alone makes up for all the cons you might find in comparison with Java. Coroutines are gold compared to Java threads. Properties in Kotlin are so much more powerful than variables in Java and the simple Object keyword saves us from code like this:

// Java Singleton, thread safe with double check locking

public class GFG {

// private instance, so that it can be

// accessed by only by getInstance() method

private static GFG instance;

private GFG()

{

// private constructor

}

public static GFG getInstance()

{

if (instance == null)

{

//synchronized block to remove overhead

synchronized (GFG.class)

{

if(instance==null)

{

// if instance is null, initialize

instance = new GFG();

}

}

}

return instance;

}

}