Как найти вложенность метода в Ruby?
в Ruby постоянный поиск зависит от вложенности, а методы сохраняют вложенность.
например, если у меня есть эти модули:
module A
X = 1
end
module B
X = 2
end
module Foo
end
Я могу определить метод Foo.a это имеет гнездо [A, Foo]:
module Foo
module ::A
Module.nesting #=> [A, Foo]
def Foo.a
X
end
end
end
Foo.a #=> 1
и метод Foo.b это имеет гнездо [Foo, B]:
module B
module ::Foo
Module.nesting #=> [Foo, B]
def Foo.b
X
end
end
end
Foo.b #=> 2
разница становится очевидной, если я определяю Foo::X:
Foo::X = 3
Foo.a #=> 1 <- still resolves to A::X
Foo.b #=> 3 <- now resolves to Foo::X
но как определить вложенность данного метода?
2 ответов
Это будет работать:
Foo.method(:a).to_proc.binding.eval('Module.nesting')
#=> [A, Foo]
Foo.method(:b).to_proc.binding.eval('Module.nesting')
#=> [Foo, B]
протестировано с Ruby 2.2.1 и 2.3.1. Он не работает с Ruby 2.1.5.
вы думаете об этом неправильно. Нет такой вещи, как "вложение методами". Константы где-то вложены. Вложенность имеет разрешение пути, связанное с именами модулей и классов. Методы содержатся в модуле / классе (будь то "нормальные" или синглтон).
где метод помещается семантический. Существует понятие, подобное self, который определяет, где будет определен метод, называемый definee по умолчанию. Там это не ключевое слово для него, но это примерно эквивалентно:
kind_of?(Module) ? name : self.class.name
где константа помещается / ищется, является чисто синтаксической. Когда вы ссылаетесь на X, ему все равно, если вы разместили его методом или нет:
DEEP_MIND = Object.new
module Foo
X = 42
end
module Foo
module Bar
def DEEP_MIND.talk
p X
end
end
end
DEEP_MIND.talk # => 42
module Foo::Bar
def DEEP_MIND.talk
p X
end
end
DEEP_MIND.talk # => uninitialized constant
все это заботится о том, что "текущие вложения" в строке кода, где вы пытались ссылаться на него.
теперь, если вы действительно хотели найти "текущие вложения внутри тело метода", тогда вам нужно как-то притвориться, что вы действительно там.
к сожалению, я не думаю, что есть какой-либо другой способ, кроме показанного в @Эрика. Используя блок instance_eval/instance_exec даст вам вложенность того, где был определен блок.