Comparing Proc Objects?

D

Daniel Schierbeck

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
 
S

Sean O'Halpin

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 =3D Hash.new(0)

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

def make_block(&block)
block
end

def test_method(x)
x + 1
end

block =3D proc {|x| x + 1}
block2 =3D 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 =3D method:)test_method)
count_block &meth
count_block &meth

meth2 =3D 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>=
=3D>1,
#<Proc:0x028710f8@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:20>=
=3D>2,
#<Proc:0x02871278@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:19>=
=3D>2,
#<Proc:0x02db4d28@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:38>=
=3D>2,
#<Proc:0x02db4e30@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:32>=
=3D>1,
#<Proc:0x028708a0@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:30>=
=3D>1,
#<Proc:0x02db4d70@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:36>=
=3D>1,
#<Proc:0x028709d8@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:29>=
=3D>1,
#<Proc:0x02870b10@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:28>=
=3D>1,
#<Proc:0x02db4da0@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:35>=
=3D>1,
#<Proc:0x02870c48@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:27>=
=3D>1,
#<Proc:0x02870d80@C:/rubylib/experiments/ruby-talk/compare-blocks.rb:26>=
=3D>1}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,264
Latest member
FletcherDa

Latest Threads

Top