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

时间:2011-09-14 22:09:24

标签: ruby eval

我正在使用Ruby 1.9.2 p180。

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

如果我从命令行运行该脚本,但是当通过eval执行时,该图表是错误的 - 一条直线,好像所有数据都消失了,而不是what you see here注意:之前,它在这里说SVG是不同的 - 但事实证明这是加载REXML而不是nokogiri的结果。

Here are the test scripts and eval code.大多数产生直线(下面的编辑部分中描述了例外情况)。

我不知道这是怎么回事。

我对为什么可能发生的事情有一些想法,但对机制没有任何线索。

假设:

  1. eval不允许制作深层副本。从eval中取出的对象在某些上下文中是丢失的部分,特别是当使用lambda将数据处理为正确的绘图格式时。
  2. 出于某种原因,eval在调用require时没有遵守捆绑的dep列表 - 可能在我的绑定中使用了错误版本的nokogiri?
  3. 其他一些必需的库(也许是RSVG?)已经重载了Rubyvis使用的一些方法。
  4. 以前有人见过这样的事吗?我有点在黑暗中感受到 - 完全不知道从哪里开始排除故障。

    编辑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)
    

    如果我在分配数据时使用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)
    

    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)
    

    所以不同之处在于我的数据分配方式。问题是:为什么?

    original gist中提供了输入的副本。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

  

事实证明,如果我只使用哈希,例如,{:x =&gt; x,:y =&gt;   Math.sin(x)},效果很好。但是当我明确地说Hash.new({:x   =&GT; x,:y =&gt; Math.sin(x)}),无论我如何都会产生错误   致电vis.data:

首先,你对Hash.new的调用是错误的。 Hash.new接受一个参数,该参数是散列的默认值。

答案 1 :(得分:0)

我想发布此评论,而不是答案;

您是否尝试过load代替eval