在Ruby中添加变量name = value格式

Kan*_*ath 3 ruby

我想为我的简单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是邪恶的.所以我有两个问题.

  1. 有没有办法在不使用eval的情况下编写调试方法?如果没有,那么首选方法是什么?
  2. 有没有办法将参数列表传递给此方法?理想情况下,我更喜欢debug {:x,:y.:anynumOfvariables}.我无法弄清楚如何将其纳入调试方法(即,获取参数列表)

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)