我想为我的简单ruby函数添加一些调试,我写了一个函数如下,
def debug(&block)
varname = block.call.to_s
puts "#{varname} = #{eval(varname,block)}"
end
debug {:x} #prints x = 5
debug {:y} #prints y = 5
Run Code Online (Sandbox Code Playgroud)
我明白,eval是邪恶的.所以我有两个问题.
Jör*_*tag 11
只需使用数组.您可以使用该Array方法确保始终拥有一个数组,即使有人只传入一个值:
def debug(&block)
Array(block[]).each do |var| puts "#{var} = #{eval var.to_s, block}" end
end
x, y = 3, 5
debug {:x} # => "x = 3"
debug {[:x, :y]} # => "x = 3" "y = 5"
Run Code Online (Sandbox Code Playgroud)
BTW:传递一个块作为绑定不再适用于Ruby 1.9.(尽管文档说它确实有效.)你必须显式调用Proc#binding以获取一个Binding对象Proc:
def debug(&block)
Array(block.()).flatten.each do |var|
puts "#{var} = #{eval var.to_s, block.binding}"
end
end
Run Code Online (Sandbox Code Playgroud)
幸运的是,这已经适用于Ruby 1.8,因此您可以通过包含它来保护您的代码.
另一种方法是完全放弃该块.我的意思是,你已经强迫用户debug使用在块中而不是在括号中传递参数的不熟悉的习惯用法.为什么不强迫他们只是通过绑定呢?
def debug(*vars, bnd)
vars.each do |var|
puts "#{var} = #{eval var.to_s, bnd}"
end
end
x, y = 3, 5
debug :x, binding # => "x = 3"
debug :x, :y, binding # => "x = 3" "y = 5"
Run Code Online (Sandbox Code Playgroud)
这具有额外的灵活性,它们实际上可以传递与调用点处的绑定不同的绑定,例如,如果他们想要在应用程序的不同部分中实际调试一段代码.
BTW:Ruby 1.9.2的参数introspection(Proc#parameters)有一些乐趣:
def debug(&block)
block.parameters.map(&:last).each do |var|
puts "#{var} = #{eval var.to_s, block.binding}"
end
end
x, y = 3, 5
debug {|x|} # => "x = 3"
debug {|x, y|} # => "x = 3" "y = 5"
Run Code Online (Sandbox Code Playgroud)