现在谁收容我? (我是 A Class 的实例!耶!)
Who's Containing Me Now? (I'm An Instance Of A Class! Yay!)
我想获取此方法的封闭方法树。这是我的代码(希望有描述性注释):
enclosing_method(var1,var2) do
enclosing_method(var3,var4) do
get_tree # This method should return an array of it's enclosing methods
# e.g. [get_tree, enclosing_method, enclosing_method, main]
end
end
我该怎么做?如果不清楚,请告诉我,我的问题措辞有问题。另外,我的标题也不好。如果有人能想到更好的标题,请在评论中提出。
编辑:
我从@WandMaker 的回答 评论中得知嵌套方法不可能。所以,我正在半改变这个问题。怎么样:
class Myclass
@@all_instances
def initialize
@parents = get_tree # method that will return
# all of the containing instances / anythings
@content = yield
@@all_instances << self
end
attr_reader :content
attr_reader :parents
end
Myclass.new do
Myclass.new do
# bonus points if you make this possible!
# I don't really need this to work but
# it's a kewl thing so please try
get_tree # => [Myclass, Myclass, <main>]
end
end
我正在寻找的是方法 get_tree
必须具有以下输出:
> Myclass.all_instances[0].parents # => [<main>]
> Myclass.all_instances[1].parents # => [Myclass, <main>]
让我在评论中知道这是否令人困惑或以任何方式荒谬。我会修好它。我保证。提前感谢所有天才解决了这个问题。我永远感激。
您实际上可以像您在问题中提到的那样将方法块彼此嵌套。 (简单示例:[1, 2, 3].each{|x| x.tap{|y| puts y}}
)以编程方式找出嵌套是什么有点棘手,但可行。
如果您正在尝试构建类似于 Erector 的 DSL,实际上有几种不同的方法可以解决该问题。也许最简单的方法是在方法调用开始时将一些值压入全局堆栈,然后在您想查看当前嵌套是什么时引用该堆栈。例如:
@call_stack = []
def some_method
@call_stack.push("some_method")
yield
ensure
@call_stack.pop
end
def some_method2
@call_stack.push("some_method2")
yield
ensure
@call_stack.pop
end
用法:
some_method do
some_method2 do
@call_stack #=> ["some_method", "some_method2"]
end
end
另一种可能性是使用instance_exec
更改块内的调用上下文,并实例化一个新对象用作每个嵌套级别的调用上下文。不过这有点复杂,所以我不会在这里介绍。
最后,为了完整起见,我应该提一下,如果您只想将其用于调试目的,还可以选择使用 caller_locations
来获取完整的堆栈跟踪。这使用起来非常简单,但在这种情况下听起来不像你想要的。
我想获取此方法的封闭方法树。这是我的代码(希望有描述性注释):
enclosing_method(var1,var2) do
enclosing_method(var3,var4) do
get_tree # This method should return an array of it's enclosing methods
# e.g. [get_tree, enclosing_method, enclosing_method, main]
end
end
我该怎么做?如果不清楚,请告诉我,我的问题措辞有问题。另外,我的标题也不好。如果有人能想到更好的标题,请在评论中提出。
编辑:
我从@WandMaker 的回答 评论中得知嵌套方法不可能。所以,我正在半改变这个问题。怎么样:
class Myclass
@@all_instances
def initialize
@parents = get_tree # method that will return
# all of the containing instances / anythings
@content = yield
@@all_instances << self
end
attr_reader :content
attr_reader :parents
end
Myclass.new do
Myclass.new do
# bonus points if you make this possible!
# I don't really need this to work but
# it's a kewl thing so please try
get_tree # => [Myclass, Myclass, <main>]
end
end
我正在寻找的是方法 get_tree
必须具有以下输出:
> Myclass.all_instances[0].parents # => [<main>]
> Myclass.all_instances[1].parents # => [Myclass, <main>]
让我在评论中知道这是否令人困惑或以任何方式荒谬。我会修好它。我保证。提前感谢所有天才解决了这个问题。我永远感激。
您实际上可以像您在问题中提到的那样将方法块彼此嵌套。 (简单示例:[1, 2, 3].each{|x| x.tap{|y| puts y}}
)以编程方式找出嵌套是什么有点棘手,但可行。
如果您正在尝试构建类似于 Erector 的 DSL,实际上有几种不同的方法可以解决该问题。也许最简单的方法是在方法调用开始时将一些值压入全局堆栈,然后在您想查看当前嵌套是什么时引用该堆栈。例如:
@call_stack = []
def some_method
@call_stack.push("some_method")
yield
ensure
@call_stack.pop
end
def some_method2
@call_stack.push("some_method2")
yield
ensure
@call_stack.pop
end
用法:
some_method do
some_method2 do
@call_stack #=> ["some_method", "some_method2"]
end
end
另一种可能性是使用instance_exec
更改块内的调用上下文,并实例化一个新对象用作每个嵌套级别的调用上下文。不过这有点复杂,所以我不会在这里介绍。
最后,为了完整起见,我应该提一下,如果您只想将其用于调试目的,还可以选择使用 caller_locations
来获取完整的堆栈跟踪。这使用起来非常简单,但在这种情况下听起来不像你想要的。