4 ms·
> Without those imports, how will people reading the code find the definitions? How will they track down the source code for all the methods being called? I th
by epidemian 5y ago
> Without those imports, how will people reading the code find the definitions? How will they track down the source code for all the methods being called?
I think in dynamic languages like Ruby and Python, there are two very different cases that we need to distinguish when thinking about this.
The first one is global references to modules/classes/functions. For example, in Python you may write:
import my_module
foo = my_module.Foo(some_arg)
So, if you wanted to find the definition of that my_module.Foo() reference, it's easy: go to the definition of my_module and search for the Foo class/function definition.
In Ruby, you may see instead something like:
require 'my_module'
foo = MyModule::Foo.new(some_arg)
Which looks very similar to Python, with the difference that the `require` method doesn't assign any local binding, but just executes the file my_module, which in turn will modify the global namespace directly and make `MyModule` available at runtime. The `require 'my_module'` might not even be present on the file that's then using `MyModule`: it might be indirectly required by another module that this file uses. Or, in the case of using Rails or any framework with auto-imports, the file might not have any `require` calls at all!
So, how is this resolved?
By convention, basically. If you see a reference like `MyModule::Foo` and want to see the definition of that, the convention is that that definition will live under my_module/foo.rb, so you can go to that file with some confidence that you'll find the the code for that class there.
So, if the convention is strong, and people follow it, this is basically a non-issue, and the go-to-definition can be done as easily as in Python, with or without an intelligent IDE.
---
The second case is when you have a dynamic reference to an object/function/whatever, like:
def do_something(arg):
arg.foobar()
In this case, neither Ruby nor Python (or any dynamic language in general) will help you much in trying to find the definition of the `foobar` method, as the type of the argument will only be known at runtime at the moment that this function will be called, and can even vary between calls.
There are different ways to make this go-to-definition somewhat more ergonomic than a global search for `def foobar`. But on the language level, i think both Python and Ruby are basically the same in this case: not very helpful. We then compensate by using good naming conventions, type annotations/comments, or using powerful IDEs that analyze the code to make good guesses about who is calling what.