赞 | 0 |
VIP | 2 |
好人卡 | 27 |
积分 | 1 |
经验 | 26327 |
最后登录 | 2019-10-13 |
在线时间 | 953 小时 |
Lv1.梦旅人
- 梦石
- 0
- 星屑
- 110
- 在线时间
- 953 小时
- 注册时间
- 2007-4-25
- 帖子
- 805
|
最直观的方法是调用者传递自己的绑定给被调用者:- def foo(a_binding, *params)
- p eval("local_variables", a_binding)
- end
- def bar1(param1)
- foo(binding, param1, "+1")
- end
- def bar2(param2)
- foo(binding, "-1", param2)
- end
- bar2(5) # => 1.8: ["param2"]; 1.9: [:param2]
复制代码 有了调用者的绑定,就可以通过 Kernel#local_variables 这个反射函数来获取局部变量名。方法的参数在局部变量列表的开头,按词法分析器看见局部变量的顺序排列。比如:local_variables[0] 就是第一个参数。如果需要获取参数的值,就再套一层 eval 求值即可(见第三个方法的例子代码)。
另一种方法是在被调用者需要调用者绑定的时候让调用者调用时附带一个 Ruby 块(如果被调用者方法本身就需要块就更好),然后在被调用者里通过 Proc#binding 方法获取调用者的绑定:- def foo(*params, &block)
- p eval("local_variables", block.binding)
- end
- def bar1(param1)
- foo(param1, "+1") {}
- end
- def bar2(param2)
- foo("-1", param2) {}
- end
- bar2(5) # => 1.8: ["param2"]; 1.9: [:param2]
复制代码 如果觉得这种方法太啰嗦,或者是不想更改方法接口,那可以用一个绑定链来跟踪整个调用栈的绑定,只不过在间开销相对就比较大了:
- def foo(*params)
- eval("p eval(local_variables[0].to_s)", Binding.caller_binding)
- end
- def bar1(param1)
- foo(param1, "+1")
- end
- def bar2(param2)
- foo("-1", param2)
- end
- class Binding
- @@caller_bindings = [ nil, TOPLEVEL_BINDING ]
- class << self
- def caller_binding
- @@caller_bindings[-2]
- end
- def push_caller_binding(a_binding)
- @@caller_bindings.push(a_binding)
- end
- def pop_caller_binding
- @@caller_bindings.pop
- end
- end
- end
- set_trace_func lambda { |event, file, line, id, binding, klass|
- return if klass == Binding
- case event
- when 'call'
- Binding.push_caller_binding(binding)
- when 'return'
- Binding.pop_caller_binding
- end
- }
- bar1 999 # => 999
- bar2 888 # => 888
复制代码 |
评分
-
查看全部评分
|