Declaratively caching results of a method

Sean O'Halpin wrote:

···

On 10/17/05, Sean O'Halpin <sean.ohalpin@gmail.com> wrote:

On 10/17/05, Daniel Berger <djberg96@gmail.com> wrote:

Jeff Wood wrote:

if you look at the examples ... normally you include the Memoize
functionality in your class

class Foo
include Memoize

def calc1( *args )
   # do something here
end

memoize :calc1
end

f = Foo.new
f.calc1( 1,2,3 )
f.calc1( 7,8,9 )

This won't work: "undefined method `memoize' for Foo:Class
(NoMethodError)"

Here's one way to do it:

class Foo
include Memoize
def initialize
  memoize :foo
end
def foo(*args)
  puts "calculating foo(#{args.map{|x| x.inspect}.join(',')})"
  args.inject(0) {|sum, x| sum + x}
end

f = Foo.new
puts f.foo(2)
__END__
calculating foo(2)
2

Regards,

Sean

I should have pointed out that this method only memoizes within the
instance... Another instance of Foo won't get the benefit of the
memoization.

Sean

Eh? If you memoize in initialize, why wouldn't another instance of Foo get the benefit?

Regards,

Dan

I prefer Pit's. Otherwise you'll have to hang on to each cache
yourself (should you memoize several methods), instead of just letting
the class do it.

Ryan

···

On 10/17/05, Daniel Berger <Daniel.Berger@qwest.com> wrote:

I'm debating between this suggestion and Pit's (where you access the cache via
it's name and as an instance method). I dunno - what do people prefer?

This one is certainly simpler :slight_smile:

Agreed. Pit's is better (even if more complicated :wink:

Sean

···

On 10/17/05, Ryan Leavengood <leavengood@gmail.com> wrote:

On 10/17/05, Daniel Berger <Daniel.Berger@qwest.com> wrote:
>
> I'm debating between this suggestion and Pit's (where you access the cache via
> it's name and as an instance method). I dunno - what do people prefer?
>
> This one is certainly simpler :slight_smile:

I prefer Pit's. Otherwise you'll have to hang on to each cache
yourself (should you memoize several methods), instead of just letting
the class do it.

Ryan

Try it:

class Foo
  include Memoize
  def initialize
    memoize :foo
  end
  def foo(*args)
    puts "calculating #{self}.foo(#{args.map{|x| x.inspect}.join(',')})"
    args.inject(0) {|sum, x| sum + x}
  end
end

f = Foo.new
puts f.foo(2)
puts f.foo(2)

g = Foo.new
puts g.foo(2)

__END__
calculating #<Foo:0x28705e8>.foo(2)
2
2
calculating #<Foo:0x28703d8>.foo(2)
2

It's because you're defining the memoized method on the singleton class:

    (class << self; self; end).class_eval do ... end

Regards,

Sean

···

On 10/17/05, Daniel Berger <Daniel.Berger@qwest.com> wrote:

Eh? If you memoize in initialize, why wouldn't another instance of Foo get the
benefit?