Использование Ruby 1.9.2
Проблема
Сравните содержание, а не результаты двух процедур. Я понимаю, что результаты не могут быть проверены из-за проблемы остановки, но это нормально; Я все равно не хочу проверять результаты.
Например
proc {@x == "x"} == proc {@x == "x"} => false # doh!
Это возвращает false, потому что объекты внутри процессов не совпадают.
Мое неуклюжее решение
У меня есть обходное решение, которое вроде как делает то, что я хочу, но на самом деле не проверяет, "равно" ли процедура тому, что я в нее вложил. В моем конкретном случае формат моих процессов всегда будет логическим тестом для переменных экземпляра, например:
{@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, но сейчас я смотрю именно на это.