比较Procs的内容,而不是结果

使用Ruby 1.9.2

问题
比较两个过程的内容,而不是结果。 我知道结果因为停止问题而无法测试但是没关系; 我还是不想测试结果。

例如

proc {@x == "x"} == proc {@x == "x"} => false # doh! 

返回false,因为procs中的对象不一样。

我笨重的解决方案
我有一个解决方案,有点像我做我想要的但它并没有真正测试proc与我放入它的“相同”。 在我的特定情况下,我的procs的格式将始终是对实例变量的布尔测试,如下所示:

 {@x == "x" && @y != "y" || @z == String} 

我编写了一个动态构建类的方法,并创建了设置为指定值的实例变量:

 def create_proc_tester(property_value_hash) new_class = Class.new.new new_class.class.class_eval do define_method(:xql?) { |&block| instance_eval &block } end property_value_hash.each do |key, value| new_class.instance_variable_set("@#{key}", value) end new_class end 

可以使用这样的东西:

 class Foo attr_accessor :block end foo = Foo.new foo.block = proc {@x == "x" && @y != "y" || @z == String} tester = create_proc_tester(:x => "x", :y => "y", :z => Fixnum) puts "Test #1: #{tester.xql? &foo.block}" tester = create_proc_tester(:x => "x", :y => "x", :z => String) puts "Test #2: #{tester.xql? &foo.block}" > Test #1: false > Test #2: true 



这一切都很精彩但我想知道是否有一种更好的,更多元的方式来实现这一点,实际测试过程的内容而不仅仅是解决我的具体问题的工作; 可以用来测试任何过程的东西。

我在想可能有一种方法可以使用Ruby解析器来比较,但我不知道如何。 我现在正在研究它,但我想我会试着看看这里有没有人这样做过,知道怎么做。 这可能是一个死胡同,但由于Ruby的动态特性,但这就是我现在正在寻找的地方。

如果你使用Ruby 1.9,你可以使用sourcify gem。

 $ irb > require 'sourcify' => true > a = proc {@x == "x"} => # > b = proc {@x == %{x}} => # > a == b => false > a.to_source == b.to_source => true > RUBY_VERSION => "1.9.2" 

我们还遇到了我公司的ParseTree / Ruby 1.9不兼容问题 。

 $ sudo gem install ruby2ruby ParseTree require 'parse_tree' require 'ruby2ruby' require 'parse_tree_extensions' # All of these are the same: proc { puts 'a' }.to_ruby # => "proc { puts(\"a\") }" lambda { puts "a" }.to_ruby # => "proc { puts(\"a\") }" Proc.new { puts %{a} }.to_ruby # => "proc { puts(\"a\") }" # If you need to do this with classes: class Bar; define_method(:foo) { 'a' }; end puts Ruby2Ruby.new.process(Unifier.new.process(ParseTree.translate(Bar))) # will print this: # class Bar < Object # def foo # "a" # end # end