Ruby 突然发现 Ruby 好像没有 global_variable_get/set 方法?

ibachue · 2013年05月13日 · 最后由 seiran 回复于 2013年05月17日 · 3236 次阅读

RT 貌似只有global_variables定义在Kernel里 是不是啊。。。

共收到 9 条回复

global variables 全局可见, 搞那两个方法多于吧。

#1楼 @zgm 关键是如果我要实现所有global variables打印的功能 我不得不用eval取值了。。 那太evil了。。

可以的...

require 'rbconfig'
require 'fiddle'
libruby = Fiddle.dlopen RbConfig::CONFIG['libdir'] + '/' + RbConfig::CONFIG['LIBRUBY_SO']
rb_gv_get = Fiddle::Function.new libruby['rb_gv_get'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP
$x = 3
$y = 'a'
puts rb_gv_get.('$x').to_value
puts rb_gv_get.('$y').to_value

另外注意要先转成字符串, 不接受 symbol 参数

#4楼 @luikore 大神的答案经常这么不同凡响。

#5楼 @zgm #6楼 @iBachue

只是碰巧知道 rb_gv_get 这个函数(ruby hacking guide)和 fiddle 的用法罢了...

#7楼 @luikore 大神就是总能碰巧知道...

#2楼 @iBachue local_variables的取法才evil…… 单纯global_variables还好…… (不过也没有检测变量名)

def gv_get(a)
  eval a.to_s
end

def gv_set(a, b)
  eval "#{a}=b"
end

def lv_get(a, binding = nil, &block)
  eval a.to_s, binding || block.binding
end

def lv_set(a, b, binding = nil, &block)
  eval "#{a}=ObjectSpace._id2ref(#{b.object_id})", binding || block.binding
end



gv_set(:$a, 3)
gv_get(:$a)

a = 3
p lv_get(:a){}
lv_set(:a, 5){}
p a

r = lambda{
  a = 3
  b = 5
  binding
}.call

p lv_get(:a, r) + lv_get(:b, r)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册