You are right, the compiler for a statically typed language can do checks that are impossible to perform for a language like Ruby, that could also create methods calls and add arguments at runtime.
I tend not to use metaprogramming except some object.send(method, args) when strictly necessary. The reason is that it slows down the team when trying to understand what a piece of code does and if not properly understood it generates bugs. Metaprogramming is buried down into third party libraries (e.g.: Rails) but we are not testing it there.
I occasionally get bugs that a compiler would catch, maybe one every year or two. One happened on Python this year. I can't remember what. I should dig into slack: I remember I wrote a note to my customer (maybe the classic id as string vs int?) But the time not lost writing type annotations is immense. I wasted cumulative weeks on that when I was working in Java 10+ years ago. And cumulative weeks of malloc/free when I was working in C before Java. All considered I prefer the occasional bug and extra test in Ruby and Python. I consider that path (GC and no types) an improvement. Of course it costs performances but customers are happy running Ruby and Python and are still in business. It can't be wrong
It's not just at runtime -- again, a common case for me (I maintain Ruby, Java, and C++ codebases that are 15 years old) are in major framework upgrades.
I've got Rails apps that were written for Rails 2 that are now on Rails 6. A Rails upgrade is a multi-day, multi-person effort. A Qt upgrade is usually about an hour for one person.
My argument isn't that C++ on the whole is saner than Ruby. There are advantages to both. (Though, to be honest, refactoring Java, which I otherwise dislike, is positively sublime.) My argument is that with something like Crystal where you basically write Ruby and get the advantages of C++ and Java, that that's a net win.
The other part of my argument is that the sum total of tests + code for Ruby isn't significantly more concise than just using a statically typed language with more minimal tests. They're really pretty close. And I personally find the roteness of static typing less mentally taxing than having to imagine all code paths in a duck-typed function.
I genuinely believe that the success of duck typed languages is their support of fast iteration for cowboy coding. I'm wholly convinced that for long lived code bases, static typing makes far more sense. But that's why I'm happy to see languages that support it with minimal to trivial cognitive overhead.
That said: almost always the right reason to pick a particular language is the frameworks. I'm doing some ML stuff in Python right now, even though I hate Python, because Python has the best libs for it. At the end of the day, purity is rarely a strong argument, particularly when it means reinventing the wheel in the language du jour.
You are right, the compiler for a statically typed language can do checks that are impossible to perform for a language like Ruby, that could also create methods calls and add arguments at runtime.
I tend not to use metaprogramming except some object.send(method, args) when strictly necessary. The reason is that it slows down the team when trying to understand what a piece of code does and if not properly understood it generates bugs. Metaprogramming is buried down into third party libraries (e.g.: Rails) but we are not testing it there.
I occasionally get bugs that a compiler would catch, maybe one every year or two. One happened on Python this year. I can't remember what. I should dig into slack: I remember I wrote a note to my customer (maybe the classic id as string vs int?) But the time not lost writing type annotations is immense. I wasted cumulative weeks on that when I was working in Java 10+ years ago. And cumulative weeks of malloc/free when I was working in C before Java. All considered I prefer the occasional bug and extra test in Ruby and Python. I consider that path (GC and no types) an improvement. Of course it costs performances but customers are happy running Ruby and Python and are still in business. It can't be wrong