各位好,在网上搜了好久没找到方法,求助一下本坛。
var1 = 1
def func(params)
#将var1作为参数传入func,怎么获取到var1的变量名即"var1"
end
func(var1)
因为 Ruby 没办法监听 local_variable 的赋值行为,所以原则上是无解的
但是有一些黑科技。。 打个比方你可以分析源代码里对这个函数的调用,把参数拿出来
var1 = 1
def func(params)
line_num = caller[0].match(/#{$0}:(\d+):/)[1].to_i
param_name = File.open($0).readlines[line_num-1].match(/func\((.+)\)/)[1]
end
p func(var1) # => "var1"
大概就是这样,其实取参数用这个正则肯定不行。。但是我不会写正则,就糊弄一下
还有一种方法是看参数的 object_id 或地址,因为 Ruby 传参都是传引用 比对一下 local_variables 的 object_id 就好了,但是在方法内拿外面的 binding 是很麻烦的。。而且有同值不同变量名的话也会 GG
也举一个例子
var1 = 1
$bindings = {}
set_trace_func proc{|*e| $bindings[e[2]] = e[4] if e[0] == "line"}
def func(params)
line_num = caller[0].match(/#{$0}:(\d+):/)[1].to_i
params_binding = $bindings[line_num]
param_name = params_binding.eval("local_variables").first{|x| params_binding.eval("#{x}.object_id") == params.object_id }
end
p func(var1) # => :var1
不过这种不可控的 set_trace_func 会严重拖慢程序的执行
感谢以上各位的回复。 #5 楼 @cicholgricenchos 非常感谢你如此详细的回复,确实有点黑科技,也许还有些更加黑科技的我们目前还没接触到(这也是 Ruby 吸引我,吸引大家的地方),相信是有解决方案的。 :plus1:
提个可能相关的事情,如果你的程序需要辨别获取这个东西,那你需要考虑一下是不是设计方面有什么问题。参见 Tell, Don't ask . 当然如果仅仅是好奇语法就当我没说..
当进入 func 方法时,已经切换了作用域。对于在 func 中,var1 已经不是 local_variable,var1 已经失效。 所以在 func 中输出 var1,只能用其它方法#5。 #5 里面,第二个方法,使用了binding, set_trace_func, 然后用 proc 将当时的 bangding 带入了 方法 func 中,所以 var1 才可以见。
#8 同意 8 楼的说法.....