Сравните содержание, а не результаты процессов

Использование 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, но сейчас я смотрю именно на это.


person Community    schedule 09.12.2010    source источник
comment
Я не уверен, как это можно сделать осмысленно. Например, эквивалентные строки в одинарных и двойных кавычках имеют разное содержимое? Один и тот же текст, но созданный разными методами? Табуляции или пробелы? Есть так много вещей, которые не влияют на смысл, но вызывают изменение буквального текста, и вещи, которые не влияют на текст, но вызывают изменение смысла. Что такое контент?   -  person Chuck    schedule 10.12.2010
comment
Я согласен, что это странная проблема, и мне больше не нужно ее решать, но мне любопытно. Однако строки в одинарных и двойных кавычках определенно отличаются. Строка в двойных кавычках будет экранирована, а в одинарных — нет. Например, puts #{variable} выводит значение переменной, а puts '#{variable}' выводит литеральную строку #{variable}.   -  person    schedule 10.12.2010
comment
@ Грег, тот факт, что это вопрос, подразумевается, иначе его не было бы на этом сайте. Обратите внимание, что большинство вопросов на этом сайте сформулированы не в форме вопроса, поскольку это было бы излишним. Также с большой буквы пишется первое слово предложения и большинство слов (существительные, местоимения, прилагательные, глаголы, наречия и подчинительные союзы) в названиях статей. Спасибо за усилия, хотя.   -  person    schedule 10.12.2010
comment
@Mike Bethany, как руководство по стилю для вопросов и ответов, так и Должны ли заголовки вопросов формулироваться как вопросы? (Небольшой опрос) рекомендуется формулировать заголовок как вопрос и в виде предложения. Собственные существительные и аббревиатуры, конечно, должны быть написаны с большой буквы, но названия являются разговорными предложениями, а не названиями книг или статей.   -  person the Tin Man    schedule 10.12.2010
comment
@Greg Это сообщения пользователей, а не фактические правила, установленные сайтом. Цитируя их, вы делаете логическую ошибку argumentsum ad populum, аргументом от популярности, даже не доказывая, что это на самом деле популярные мнения; только потому, что большинство людей верят во что-то, не делает это правдой. Глядя на сообщение с вопросами, я вижу, что обе стороны спора ведут горячие споры, но фактическая суть представленного вопроса заключается не в форме вопроса, а в ясности вопроса. Редактирование на основе контента помогает, а неправильное исправление грамматики в соответствии с личными предпочтениями — нет.   -  person    schedule 10.12.2010
comment
@Mike Вас может заинтересовать это предложение по обмену стеками . Он почти готов к началу бета-тестирования, просто нужно еще несколько.   -  person greatwolf    schedule 18.01.2011


Ответы (2)


Если вы используете Ruby 1.9, вы можете использовать драгоценный камень sourcify.

$ irb
> require 'sourcify'
=> true 
> a = proc {@x == "x"}
=> #<Proc:0x9ba4240@(irb):2> 
> b = proc {@x == %{x}}
=> #<Proc:0x9ba23f0@(irb):3> 
> a == b
=> false 
> a.to_source == b.to_source
=> true 
> RUBY_VERSION
=> "1.9.2" 

Мы также столкнулись с проблемой несовместимости ParseTree/Ruby 1.9. в моей компании.

person Seamus Abshere    schedule 19.12.2010
comment
Спасибо. Это так близко, как я собираюсь получить. - person ; 20.12.2010

person    schedule
comment
+1 за усилия. Я должен был сказать, что использую Ruby 1.9.2. Parse_Tree не работает с 1.9. - person ; 10.12.2010
comment
ну, тогда вам нужно написать расширение c. поскольку AST хранится в памяти для всех процессов, это должно быть относительно легко. - person glebm; 10.12.2010
comment
... это должно быть относительно легко. Не по словам парня, который написал Parse_Tree. Цитирую, Из-за изменений внутренностей в 1.9 ParseTree просто не может работать. Я попросил зацепки/варианты, чтобы мы могли получить информацию, но они так и не появились. В частности, если вы используете ParseTree для доступа к AST живого метода/блока/процедуры, вы SOL. - person ; 10.12.2010