> so not really any point in trying to convince you
You’re right about that, but I take a stronger position on this than for example something very subjective like curly braces versus white space indentation. I am indeed very dogmatic and take a hard-line on this. To the point that I’ll say this: dynamic typing is simply a wrong and bad engineering decision.
Another example of a bad thing is allowing null to be a part of every type instead of requiring an explicit ? in the type, or the use of an Optional wrapper — and this is something any modern languages — to name a few Rust, Kotlin, etc fixes. But that isn’t meant to level a personal attack against the languages designers of the past (or to say that they were stupid). Allowing every type to be Union[T, null] was a simply a language design mistake (that potentially cost us billions) that we need to rectify and move forward from.
However, imo, dynamic typing is a 100 times worse than not having null safety (or not having memory safety like C or C++). I can work with a C or C++ without much trouble, but not with dynamic typing. Dynamic typing is simply just inexcusably horrid.
Untyped languages tend to be at the forefront of paradigms, and typed languages come in toward the end when reliability and need for tooling are more important than innovation/discovery.
In the 90s a bunch of kids were building websites with LAMP stacks while serious engineers were building aging/about-to-be-irrelevant desktop software in serious, typed languages.
I kickstarted a project in Python a decade ago that was wild on dynamic typing. As it passed a critical threshold of ~10k LoC, it became nearly ummaintainable.
What's that `response` passed here? A verbatim response object from `requests`? A proxy mapping? Bytes? A JSON string? If so, a list or a dict? And what fields are inside?
Multiply it by tens or hundreds of methods and classes, and it's easy to see why projects based on purely dynamic patterns fail to scale.
By now I have almost completely rewritten that project to use type hints everywhere I could. And guess what? In 95% of the cases I knew exactly what was being passed - or the choice was about 2-3 types at most, so a Union sufficed.
Yes, there's a 5% of cases where Python's dynamic typing features are a blessing. The power of meta programming in Python is often underestimated. Reflection is amazingly intuitive compared to the patchwork mess of Java, Kotlin and friends. Everything can be mocked without hassle and boilerplate. And duck typing can really be useful sometimes.
But, again, in an average project I wouldn't expect code that benefits from these features to make up more than 5-10% of the codebase.
For everything else, just do yourself, your future self and anyone who will work on your code a favour, and use type hints.
The P in the LAMP stack is still a bit of a mystery to me. It could (one could wish) have been Haskell instead, but oh well.
Just reading this sent a chill down my spine. I have horrible memories of having to read the code to figure out what something was doing (in JavaScript, Python, Ruby, etc), due to the disaster of an anti-feature called dynamic typing having been used.