2010-04-08 130 views
21

编写一个函数(或某种DSL文件)的最佳方法是让我可以在Ruby中编写此代码。我将如何构造函数write_pair?Ruby - 打印变量名称,然后打印它的值

username = "tyndall" 
write_pair username 
# where write_pair username outputs 
username: tyndall 

可以吗?寻找最简单的方法来做到这一点。

+0

Exemplor不仅可以做到这一点,甚至可以打印出'list.first:1'。 – 2010-04-09 11:06:24

回答

21

当然有可能!

我的解决方案通过测试对象#OBJECT_ID身份VAR:http://codepad.org/V7TXRxmL
它瘫痪在绑定经过风格...
虽然它只是为本地变量的是,它可以很容易地进行“通用”将使用其他范围值变量列表的方法,如instance_variables

# the function must be defined in such a place 
# ... so as to "catch" the binding of the vars ... cheesy 
# otherwise we're kinda stuck with the extra param on the caller 
@_binding = binding 
def write_pair(p, b = @_binding) 
    eval(" 
    local_variables.each do |v| 
     if eval(v.to_s + \".object_id\") == " + p.object_id.to_s + " 
     puts v.to_s + ': ' + \"" + p.to_s + "\" 
     end 
    end 
    " , b) 
end 

# if the binding is an issue just do here: 
# write_pair = lambda { |p| write_pair(p, binding) } 

# just some test vars to make sure it works 
username1 = "tyndall" 
username = "tyndall" 
username3 = "tyndall" 

# the result: 
write_pair(username) 
# username: tyndall 
+0

我可以在哪里阅读有关此绑定的更多信息(以您使用该术语的方式)?这是我迷路的地方。 – BuddyJoe 2010-04-15 15:05:17

+0

http://ruby-doc.org/core/classes/Binding.html http://onestepback.org/index.cgi/Tech/Ruby/RubyBindings.rdoc/style/print – clyfe 2010-04-15 15:53:37

+9

我会非常想受到伤害任何人都会在项目中实际使用此代码。 – molf 2010-06-28 13:05:51

2

你不能在Ruby中获得变量的名字。但是你可以做这样的事情:

data = {"username" => "tyndall"}

甚至,

username = "tyndall" 
data = {"username", "password", "favorite_color"} 
data.each { |param| 
    value = eval(param) 
    puts "#{param}: #{value}" 
} 
+1

当然你可以,但它很棘手! – clyfe 2010-04-08 23:19:33

14

如果可以让你使用一个符号,而不是变量名,你可以做这样的事情:

def wp (s, &b) 
    puts "#{s} = #{eval(s.to_s, b.binding)}" 
end 

在使用中:

irb(main):001:0> def wp (s, &b) 
irb(main):002:1> puts "#{s} = #{eval(s.to_s, b.binding)}" 
irb(main):003:1> end 
=> nil 
irb(main):004:0> var = 3 
=> 3 
irb(main):005:0> wp(:var) {} 
var = 3 

请注意,您必须将空块{}传递给方法,或者不能得到评估符号的结合。

+0

如果您打算调用.to_s,为什么不直接传递字符串?这样你甚至可以使用更复杂的表达式。此外,为什么你使用b.send(:binding)而不是更明显的b.binding? (我是Ruby的新手)。无论如何,它的效果很好,比其他解决方案(称为write_pair)要简单得多,我甚至不能理解 – marcus 2010-09-26 02:37:23

+0

是的,你可以传递一个字符串而不是符号(不需要修改),第一行解决方案只是指你不能输入'wp(var)'的东西(就像在问题中一样)。不知道/记住为什么我选择符号而不是字符串,或者为什么我放入'.send(:binding)'而不是'.binding' - 可能是因为首先考虑了其他解决方案并从中演变而来。 =) – Arkku 2010-09-26 04:39:51

3

我为这个vim宏:在正常模式下

" Inspect the variable on the current line (in Ruby) 
autocmd FileType ruby nmap ,i ^"oy$Iputs "<esc>A: #{(<esc>"opA).inspect}"<esc> 

把你想对自己的线路检查变量,然后键入,i(逗号,然后我)。事实证明这样的:

foo 

到这一点:

puts "foo: #{(foo).inspect}" 

这是很好的,因为它没有任何外部依赖(例如,你不必有一个库最多可以装载用它做) 。

1
def write_pair var, binding 
    puts "#{ var } = #{ eval(var, binding)}" 
end 


username = "tyndall" 
write_pair "username", binding 

这似乎很奇怪,因为绑定从来没有定义,但它的工作原理。从Ruby: getting variable name

的结合()方法给出的绑定对象,它记住 上下文在该点的方法被调用。然后,您将绑定 传递给eval(),并在该上下文中评估该变量。

一定要传递一个字符串,而不是变量。

1
# make use of dynamic scoping via methods and instance vars 
@_binding = binding 
def eval_debug(expr, binding = @_binding) 
    "#{expr} => #{eval(expr, binding)}" 
end 

# sample invocation: 
x = 10 
puts eval_debug "x" 
puts eval_debug "x**x" 
2

这是一个简单的解决方案:

def bug string 
    puts string + eval(string) 
    end 

这是更具可读性:

def bug string 
    puts '#' * 100 
    puts string + ': ' + eval(string).inspect 
end 

因此调用:

bug "variable" 

如果您需要随身携带的与你的实际变量,你必须t ype它两次,但你可以做到这一点。因此:

puts "variable: #{variable}" 
2

大厦与符号&绑定...如果在变量名路过的符号对你的作品(谁不爱切出多余的按键?)以前的答案,试试这个:

def wp(var_name_as_sym) 
    # gets caller binding, which contains caller's execution environment 
    parent_binding = RubyVM::DebugInspector.open{|i| i.frame_binding(2) } 
    # now puts the symbol as string + the symbol executed as a variable in the caller's binding 
    puts %Q~#{var_name_as_sym.to_s} = #{eval("#{var_name_as_sym.to_s}.inspect", parent_binding)}~ 
end 

aa=1 
bb='some bb string' 
os = OpenStruct.new(z:26, y:25) 

控制台输出:

> wp :aa 
aa = 1 
=> nil 
> wp :bb 
bb = "some bb string" 
=> nil 
> wp :os 
os = #<OpenStruct z=26, y=25> 
=> nil 

使用红宝石2.2.2p95

(拨打banister拨打上下文getting binding