Ruby中的Kernel :: eval的危险和警告?

Doc*_*awk 5 ruby eval

我正在使用Ruby 1.9.2 p180.

我正在为Rubyvis编写一个连续的评估工具(成为SciRuby的一部分).基本上,您Rubyvis::Panel在输入文件中设置(例如test.rb),此SciRuby类(绘图仪)监视test.rb修改.当有变化时,SciRuby会运行脚本eval.

如果我从命令行运行它,该脚本可以工作,但是当执行时eval,绘图是错误的 - 一条直线,好像所有数据都消失了,而不是你在这里看到的.注意:以前,它在这里说SVG是不同的 - 但事实证明这是加载REXML而不是nokogiri的结果.

以下是测试脚本和评估代码.大多数产生直线(下面的编辑部分中描述的例外).

我不知道这是怎么回事.

我有几个想法,为什么它可能会发生,但没有线索的机制.

假设:

  1. eval不允许进行深层复制.从eval某些上下文中取出的对象是缺失的部分,特别是当使用lambda将数据处理为绘图的正确格式时.
  2. 出于某种原因,evalrequire调用时不尊重捆绑的dep列表- 可能在我的绑定中使用了错误版本的nokogiri?
  3. 其他一些必需的库(也许是RSVG?)已经重载了Rubyvis使用的一些方法.

以前有人见过这样的事吗?我有点在黑暗中感受到 - 完全不知道从哪里开始排除故障.

编辑9/15/11:新信息

看来呼叫OpenStruct.new导致问题.

如果我将数据定义为列表列表data = pv.range(0,10,0.1).map { |d| [d,Math.sin(d)+2+rand()] },则效果很好.

但是当数据被定义为OpenStructs列表时,以下代码会给出错误的输出:

data = pv.range(0, 10, 0.1).map {|x|
  o = OpenStruct.new({:x=> x, :y=> Math.sin(x) + 2+rand()})
  STDERR.puts o.inspect # Output is correct.
  o
}
STDERR.puts "size of data: #{data.size}"
STDERR.puts "first x = #{data.first.x}" # Output is first x = 0.0
STDERR.puts "first y = #{data.first.y}" # Output is first y =     (WRONG)
Run Code Online (Sandbox Code Playgroud)

如果我在分配数据时使用collect,我甚至会引发错误,例如,

vis.add(pv.Line).data(data.collect { |d| [d.x,d.y] }

plotter.rb:88:in `block in <main>': undefined method `x' for [0.0, nil]:Array (NoMethodError)
Run Code Online (Sandbox Code Playgroud)

与没有错误vis.add(pv.Line).data(data).该错误似乎来自eval("vis.render()", bind)我的应用程序源代码中的调用(不在绘图脚本中).

事实证明,如果我只使用哈希,例如{:x => x, :y => Math.sin(x)},那就可以了.但是当我明确地说Hash.new({:x => x, :y => Math.sin(x)}),无论我如何调用vis.data,都会产生错误:

rubyvis/lib/rubyvis/internals.rb:184:in `each': comparison of Hash with Hash failed (ArgumentError)
Run Code Online (Sandbox Code Playgroud)

所以区别在于我的数据分配方式.问题是:为什么?

原始要点中提供了输入的副本.谢谢你的帮助.

Dog*_*ert 1

事实证明,如果我只使用哈希,例如 {:x => x, :y => Math.sin(x)},效果很好。但是当我明确地说 Hash.new({:x => x, :y => Math.sin(x)}) 时,无论我如何调用 vis.data 都会给出错误:

首先,您对 Hash.new 的调用是错误的。Hash.new 采用一个参数,该参数是哈希的默认值。