> But you're not making sense complaining first about the "in general" situation, then complaining about a 2% situation.

The use of "in general" has long established usage in mathematics to refer to properties that hold for all objects in a given collection [0] [1]. Thus, if 2% of those objects fail to satisfy these properties, you cannot say that such properties hold "in general."

> Secondly, you're mixing concepts of static typing and metaprogramming by saying "the language not only fails to equip IDEs and tooling with the static typing information that would grant definitive answers to such questions." Static typing is not the solution, or at least not the only solution, to metaprogramming concepts.

Propose alternate solutions then.

IDEs and tooling (let's leave LLMs and other stochastic methods aside for now) can only inspect the lexical, syntactic, and semantic (types) structure of source code in order to navigate and validate it. Thus, information that is absent from the lexical, syntactic, and semantic structure of the source code, is unavailable to the IDE and static tooling. Ruby, being a dynamically typed language, does not statically encode any structure regarding types, callgraphs/callsites/usages, definitions, or otherwise, in the syntax of the language alone. The behavior of a Ruby program - how its methods are defined, where they are defined, and which runtime objects invoke send what messages to whatever recipients, are only discoverable at runtime, because nobody bothered to put this information in at compile/typecheck time. You cannot discern information that simply is not there.

> For example, if I statically define a Ruby object via RBS, I may still do the things you list that are problematic.

Yes, and this is because RBS is not actually a sound typesystem [2] [3]. You can declare whatever fake types and interfaces you want in RBS; there is absolutely nothing stopping me from simply using `#define_method` to overwrite your implementation, destroying your static guarantees, or using other runtime metaprogramming facilities to delete your method, change its signature, or otherwise violate whatever other invariants you assumed you had when you wrote the static headers/type declarations and had them checked by the static verifier.

It doesn't matter if you statically verify the code, when the language offers innumerable opportunities to destroy those static guarantees, after they were established, at runtime.

> Thirdly, you're complaining about runtime issues making things difficult for the IDE while doing a lookup. What language and IDE do you prefer that does this so much better?

I already provided an example of C# ReSharper upthread [4]. C# actually provides the static typing information that the tooling requires in order to navigate the AST with deductive certainty, not loose approximations or heuristics as in RubyMine.

Out of curiosity, did you study computer science formally at a post-secondary institution, or did you learn from a bootcamp?

[0] https://en.wikipedia.org/wiki/Glossary_of_mathematical_jargo...

[1] https://en.wikipedia.org/wiki/Glossary_of_mathematical_jargo...

[2] https://en.wikipedia.org/wiki/Type_safety

[3] https://www.typescriptlang.org/play/typescript/language/soun...

[4] https://news.ycombinator.com/item?id=45105283

I didn't read your comment -- I'm sure it was insightful and well researched.

The fact that it ended with an elitist ad hominem attack tells me enough.

Just paying it forward. As a visible minority in Canada, I am subjected to this kind of passive aggressive, plausibly deniable ad hominem on a regular basis - and often by the very same Canadian white progressives who claim to have been educated out of such bigotry and racism. When in Rome...

[deleted]

SLIME is a better approach for dynamic languages, IMO. Interrogating the actual runtime is more effective than trying to do static analysis.

In a Turing complete dynamic language I believe that some properties of the runtime would be undecidable. The advantage of static typing is that many (most?) type systems are sufficiently constrained (i.e. not Turing complete) such that the typecheck procedure can be assured to terminate.

Of course, with sufficiently expressive type systems you end up with Haskell "UndecidableInstances" or Coq dependent types or C++ compile-time tetris, [0] and now you are back to the same problem as with analyzing the runtime. Otherwise you may find it difficult to encode the desired properties or invariants into your type system, for lack of expressive power... tradeoffs abound, and so on.

[0] https://news.ycombinator.com/item?id=9813800

Or my favorite alternative to that story: well, it's currently a str ... maybe it'll still be a str in 5 minutes, who knows

In a dynamic language where code that produces such a side effect is admitted by the (lack of) compiler/typechecker, sure; however a static checker would probably ensure, before runtime, that said binding indeed refers to a str, now and forever.

But I realize now the point of ancestor's comment is that you don't have such a guarantee in a dynamic language - hence the tendency to lean more on REPL-oriented development, highly interactive live runtime environments, tight TDD feedback loops, etc...

[deleted]