Forum: Ruby Comparing Proc Objects?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
5da4c52f43677f395aff5bde775593c2?d=identicon&s=25 Daniel Schierbeck (dasch)
on 2005-11-14 16:23
(Received via mailing list)
Just for the laugh of it (I've got the flu) I wrote a little Cache Proxy
class. Basically, when you call a method on the proxyed object it checks
if that method has been called with the same arguments before. If that's
the case, it returns the cached return value. What I'm interested in
knowing is how I check whether any supplied block matches the one from
the cached call.

This is my code:

   class EmptyClass
     instance_methods(true).each do |method|
       undef_method(method) unless ["__send__", "__id__"].include?
method
     end
   end

   class Proxy < EmptyClass
     def initialize(obj)
       @obj = obj
     end

     def method_missing(name, *args, &block)
       @obj.send(name, *args, &block)
     end
   end

   class CacheProxy < Proxy
     def initialize(obj)
       @calls = []
       @obj = obj
     end

     def method_missing(name, *args, &block)
       call = MethodCall.new(name, *args, &block)
       if @calls.include? call
         return @calls.detect do |cached_call|
           cached_call == call
         end.return_value
       else
         call.return_value = return_value = super
         @calls << call
         return return_value
       end
     end

     class MethodCall
       include Comparable

       attr_reader :name, :args, :block
       attr_accessor :return_value

       def initialize(name, *args, &block)
         @name, @args, @block = name, args, block
       end

       def <=> (other)
         self.name <=> other.name
       end

       def == (other)
         self.name  == other.name and self.args  == other.args
       end
     end
   end


I bet this has already been done, and probably in a more efficient way,
but hey, I'm bored...


Cheers,
Daniel
E1d641bfe4071a5413bac781f06d3fd1?d=identicon&s=25 Sean O'halpin (sean)
on 2005-11-14 16:47
(Received via mailing list)
On 11/14/05, Daniel Schierbeck <daniel.schierbeck@gmail.com> wrote:
> What I'm interested in
> knowing is how I check whether any supplied block matches the one from
> the cached call.

I think the only way you're going to get equality with a supplied
block is if it is an object, i.e. created with proc or Proc.new or by
passing through another method. Every other form is generated on the
fly AFAIK.

Regards,

Sean

P.S. This is what I used to test this:

require 'pp'

@blocks = Hash.new(0)

def count_block(&block)
  @blocks[block] += 1
end

def make_block(&block)
  block
end

def test_method(x)
  x + 1
end

block = proc {|x| x + 1}
block2 = Proc.new do |x| x + 1 end

count_block &block
count_block &block
count_block &block2
count_block &block2
count_block do |x| x + 1 end
count_block do |x| x + 1 end
count_block { |x| x + 1 }
count_block { |x| x + 1 }
count_block &make_block { |x| x + 1 }

count_block &method(:test_method)
count_block &method(:test_method)
meth = method(:test_method)
count_block &meth
count_block &meth

meth2 = Proc.new &method(:test_method)
count_block &meth2
count_block &meth2

pp @blocks
__END__
---------- OUTPUT ----------
{#<Proc:0x02db4de8@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:33>=>1,
 #<Proc:0x028710f8@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:20>=>2,
 #<Proc:0x02871278@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:19>=>2,
 #<Proc:0x02db4d28@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:38>=>2,
 #<Proc:0x02db4e30@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:32>=>1,
 #<Proc:0x028708a0@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:30>=>1,
 #<Proc:0x02db4d70@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:36>=>1,
 #<Proc:0x028709d8@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:29>=>1,
 #<Proc:0x02870b10@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:28>=>1,
 #<Proc:0x02db4da0@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:35>=>1,
 #<Proc:0x02870c48@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:27>=>1,
 #<Proc:0x02870d80@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:26>=>1}
This topic is locked and can not be replied to.