> automatic formatting, linting and code completion
You are describing tooling that is used to write code, but not to read or debug it. And Ruby is exceptionally easy to write without any tooling whatsoever.
The hard problem with dynamic languages is reading the code and understanding what it is doing at run time. And that is where TFA suggests Ruby is terrible.
One the way to reading about something else, I read an essay by a language developer complaining about type erasure. In functional languages.
In short, when you get to the point in implementing a language where you can do type erasure, you're golden because it usually means you have things nailed down. Unfortunately then people actually implement type erasure and now there is no way to link data structures in memory with a piece of code at run time.
Or at least very easily.
As an example C/C++ does erase type information. There often being nothing that tells you what an object in memory is. But compilers take great pains to preserve that information in the generated output formats. Which allow you to write debuggers. I'm sure languages like Java and .net do the same.
I used to think that it was fine, but then I started working with LISP and SLIME, and the difference between that and what's available in the Ruby-world is striking.
You are describing tooling that is used to write code, but not to read or debug it. And Ruby is exceptionally easy to write without any tooling whatsoever.
The hard problem with dynamic languages is reading the code and understanding what it is doing at run time. And that is where TFA suggests Ruby is terrible.