Drew Kitch
Drew Kitch

Reputation: 31

Ruby comparison operations for Proc?

The comparison operator outlined here (shown below) on ruby 2.2.0 is really just a comparison of the Proc#call result with another object. The documentation reads:

proc === obj → result_of_proc

Invokes the block with obj as the proc's parameter like #call. It is to allow a proc object to be a target of when clause in a case statement.

What I'm looking for is something to the effect of:

a = Proc.new { puts 'hi' }
b = Proc.new { puts 'hi' }

a == b
# => true

Can this somehow be done?

Trying to solve for a cache invalidation problem on this gist (code shown below). If there's already a cache file, then any change to the Kinescope block will be ignored.

module Kinescope
  def self.film(reel,&block)
    file_name = "kinescoped_#{reel}.ml"
    begin
      Marshal.load(File.read(file_name))
    rescue
      data = yield
      File.open(file_name,'w') do |f|
        f.write(Marshal.dump(data))
      end
      data
    end
  end
end
 
def time_consuming_calculation
  sleep 60
  true
end
 
test = Kinescope.film :big_data do
  # 'film' gigantic data here
  result = []
  File.foreach('big_file.txt') do |line|
    result << line if time_consuming_calculation
  end
  result
end

Upvotes: 3

Views: 136

Answers (2)

D-side
D-side

Reputation: 9495

You could try to decompose procs back into Ruby source code strings using ruby2ruby, then compare them. However, to handle some subtle differences such as variable names that do not affect behavior you may want to get a syntax tree instead and write some more sophisticared comparison.

Bear in mind that this approach is a comparison of code, not the functions' effect. It will not be able to detect two functions that do the same thing if they are written differently.

Upvotes: 0

J&#246;rg W Mittag
J&#246;rg W Mittag

Reputation: 369536

This is called the Function Problem and is equivalent to solving the Halting Problem. Think about it. If this were possible, then you could solve the Halting Problem like this:

infinite_loop = -> { nil while true }
some_program == infinite_loop # => true

Ergo, it is impossible to algorithmically determine whether two programs compute the same function.

Upvotes: 2

Related Questions