Ruby:获取变量名 [英] Ruby: getting variable name

查看:50
本文介绍了Ruby:获取变量名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何获取变量名?例如,

How can I get a variable name? E.g.,

def get_var_name(var)
  # return variable name
end

myname = nil
get_var_name myname #=> myname

初衷:

somevar = "value"

puti somevar #=> somevar = "value"
# that is a shortage for
# `puts "somevar = #{somevar.inspect}"`

我的尝试:

def puti(symb)
  var_name  = symb.to_s
  var_value = eval(var_name)
  puts "#{var_name} = #{var_value.inspect}"
end
puti :@somevar # that actually will work only with class vars or whatever considering var scope;

推荐答案

首先,你不能实现一个puti,直接调用puti a_var得到输出为a_var = a_var 的值.在puti的正文中,Ruby只能看到puti的形参名称,无法推断出实际的形参名称.

First, you cannot implement a puti and directly call puti a_var to get the output as a_var = value of a_var. At the body of puti, Ruby sees only the formal parameter names of puti, it cannot infer the actual parameter names.

在 C/C++ 等其他语言中,您可以使用 来实现你的 puti.那是另一个故事了.

In some other language like C/C++, you can use Macro to implement your puti. That's another story.

但是,您可以在 继续.在另一个问题您能否在 Ruby 调用方的上下文中评估代码?",Sony Santos 提供了caller_binding 实现以获取调用者的绑定(类似于 perl 调用者函数).

However, you can implement put :a_var, with the help of Continuation. In another question "Can you eval code in the context of a caller in Ruby?", Sony Santos has provided a caller_binding implementation to get the binding of the caller (something like the perl caller function).

应该稍微改变实现,因为 callcc 在第一次返回时返回块的返回值.所以你会得到一个Continuation 的实例,而不是nil.这是更新的版本:

The implementation should be altered a bit, because callcc returns the return value of the block at its first returning. So you'll get an instance of Continuation rather than nil. Here is the updated version:

require 'continuation' if RUBY_VERSION >= '1.9.0'

def caller_binding
  cc = nil     # must be present to work within lambda
  count = 0    # counter of returns

  set_trace_func lambda { |event, file, lineno, id, binding, klass|
    # First return gets to the caller of this method
    # (which already know its own binding).
    # Second return gets to the caller of the caller.
    # That's we want!
    if count == 2
      set_trace_func nil
      # Will return the binding to the callcc below.
      cc.call binding
    elsif event == "return"
      count += 1
    end
  }
  # First time it'll set the cc and return nil to the caller.
  # So it's important to the caller to return again
  # if it gets nil, then we get the second return.
  # Second time it'll return the binding.
  return callcc { |cont| cc = cont; nil }
end

# Example of use:

def puti *vars
  return unless bnd = caller_binding
  vars.each do |s|
    value = eval s.to_s, bnd
    puts "#{s} = #{value.inspect}"
  end
end

a = 1
b = 2
puti :a, :b
e = 1 # place holder...

# => a = 1
#    b = 2

注意puti不应该是你程序的最后一条语句,否则ruby解释器会立即终止,trace函数没有机会运行.这就是最后一个占位符"行的要点.

Note the puti should not be the last statement of your program, otherwise the ruby interpreter will terminate immediately and the trace function has no chance to run. So that's the point of the last "place holder" line.

这篇关于Ruby:获取变量名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆