jeteve has asked for the wisdom of the Perl Monks concerning the following question:

Hi fellow monks,

I've got a problem of collision when I use memoize on an object method.

For instance if I write:
package Foo; sub new{ bless { a => undef } , shift ;} memoize('bar'); sub bar{shift->{'a'} ;}

Then when I build a lot of instances of Foo, the bar method starts to behave as they are collisions between object addresses.

I believe this is due to the fact memoize uses a string version of the function arguments, and that the first argument here is something like Foo==HASH(0x8759090) . After a lot of creation/destroy of instance, the garbage collection starts to recycle memory addresses and memoize starts to make your function return phantom values.

Is there a recipe to avoid that ? Should I overload the quote operator and give a unique id to each instance of foo ?

Cheers !

-- Jerome

Replies are listed 'Best First'.
Re: Memoize collision with objects
by almut (Canon) on Nov 12, 2008 at 12:09 UTC

    Overloading stringification would certainly be one approach.  Another possibility might be to (mis)use the NORMALIZER option. Quoted from the docs:

    (...) supply a NORMALIZER function that turns the program arguments into a string in a way that equivalent arguments turn into the same string.

    Now, the idea would be to supply a function that turns non-equivalent arguments (i.e. object instances which are different, despite residing at the same (recycled) address) into different strings, e.g. by having some unique ID associated with each object (attribute assigned upon construction), which you then somehow munge into the string returned by the normalizer function... Just an idea.

      Hi,

      I actually added a unique id to all my instances, and it solves the problem:

      sub bar{ my ( $self, etc .. ) = @_; return $self->_memBar($self->id(), etc ...); } memoize('_memBar') ; sub _memBar{ my ( $self , $id , etc .. ) ; .. do the real stuff .. }
Re: Memoize collision with objects
by fmerges (Chaplain) on Nov 12, 2008 at 12:22 UTC

    Hi,

    As almut said, one option is to do it via providing a normalizer, the other option is to just treat the "method" as a function, where you provide plain arguments, instead of providing objects, here for sure it depends on the problem you have in hands.

    Regards,

    fmerges at irc.freenode.net
Re: Memoize collision with objects
by JavaFan (Canon) on Nov 12, 2008 at 13:42 UTC
    Yet another way of tackling this is to use the SCALAR_CACHE and LIST_CACHE options of memoize, so you have a handle on the cache used my memoize. Then define a Foo::DESTROY function where you remove the corresponding entries in the cache.